linux-user-bde.c (46765B)
1 /* 2 * Copyright 2017 Broadcom 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License, version 2, as 6 * published by the Free Software Foundation (the "GPL"). 7 * 8 * This program is distributed in the hope that it will be useful, but 9 * WITHOUT ANY WARRANTY; without even the implied warranty of 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 11 * General Public License version 2 (GPLv2) for more details. 12 * 13 * You should have received a copy of the GNU General Public License 14 * version 2 (GPLv2) along with this source code. 15 */ 16 /* 17 * $Id: linux-user-bde.c,v 1.80 Broadcom SDK $ 18 * $Copyright: (c) 2005 Broadcom Corp. 19 * All Rights Reserved.$ 20 * 21 * Linux User BDE Helper Module 22 */ 23 #include <gmodule.h> 24 #include <mpool.h> 25 #include <linux-bde.h> 26 27 #include <sal/core/thread.h> 28 #include <sal/core/sync.h> 29 #include <soc/devids.h> 30 #include <soc/drv.h> 31 32 #include "linux-user-bde.h" 33 34 #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) 35 #include <linux/uaccess.h> 36 #endif 37 38 39 MODULE_AUTHOR("Broadcom Corporation"); 40 MODULE_DESCRIPTION("User BDE Helper Module"); 41 MODULE_LICENSE("GPL"); 42 43 /* CMIC/CMICe defines */ 44 #define CMIC_IRQ_STAT 0x00000144 45 #define CMIC_IRQ_MASK 0x00000148 46 #define CMIC_IRQ_MASK_1 0x0000006C 47 #define CMIC_IRQ_MASK_2 0x00000070 48 49 /* CMICm defines */ 50 #define CMIC_CMCx_IRQ_STAT0_OFFSET(x) (0x31400 + (0x1000 * x)) 51 #define CMIC_CMCx_IRQ_STAT1_OFFSET(x) (0x31404 + (0x1000 * x)) 52 #define CMIC_CMCx_IRQ_STAT2_OFFSET(x) (0x31408 + (0x1000 * x)) 53 #define CMIC_CMCx_IRQ_STAT3_OFFSET(x) (0x3140c + (0x1000 * x)) 54 #define CMIC_CMCx_IRQ_STAT4_OFFSET(x) (0x31410 + (0x1000 * x)) 55 56 #define CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(x) (0x31414 + (0x1000 * x)) 57 #define CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(x) (0x31418 + (0x1000 * x)) 58 #define CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(x) (0x3141c + (0x1000 * x)) 59 #define CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(x) (0x31420 + (0x1000 * x)) 60 #define CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(x) (0x31424 + (0x1000 * x)) 61 62 /* CMICd defines */ 63 #define CMIC_CMCx_IRQ_STAT5_OFFSET(x) (0x314b0 + (0x1000 * x)) 64 #define CMIC_CMCx_IRQ_STAT6_OFFSET(x) (0x314b4 + (0x1000 * x)) 65 #define CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(x) (0x314b8 + (0x1000 * x)) 66 #define CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(x) (0x314bc + (0x1000 * x)) 67 #define CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(x) (0x314c0 + (0x1000 * x)) 68 #define CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(x) (0x314c4 + (0x1000 * x)) 69 70 #define CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(x) (0x31428 + (0x1000 * x)) 71 #define CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(x) (0x3142c + (0x1000 * x)) 72 #define CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(x) (0x31430 + (0x1000 * x)) 73 #define CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(x) (0x31434 + (0x1000 * x)) 74 #define CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(x) (0x31438 + (0x1000 * x)) 75 76 /* CMICX defines */ 77 #define INTC_INTR_REG_NUM (8) 78 79 /* 80 TODO:HX5 81 The INTR base address values are changed for HX5, 82 hence making new #defines so runtime decisions can 83 be made. 84 */ 85 86 #define INTC_INTR_ENABLE_REG0 (0x180130f0) 87 #define INTC_INTR_STATUS_REG0 (0x18013190) 88 #define INTC_INTR_RAW_STATUS_REG0 (0x18013140) 89 90 #define INTC_INTR_ENABLE_BASE (INTC_INTR_ENABLE_REG0) 91 #define INTC_INTR_STATUS_BASE (INTC_INTR_STATUS_REG0) 92 #define INTC_INTR_RAW_STATUS_BASE (INTC_INTR_RAW_STATUS_REG0) 93 94 #define HX5_INTC_INTR_ENABLE_REG0 (0x102310f0) 95 #define HX5_INTC_INTR_STATUS_REG0 (0x10231190) 96 #define HX5_INTC_INTR_RAW_STATUS_REG0 (0x10231140) 97 98 #define HX5_INTC_INTR_ENABLE_BASE (HX5_INTC_INTR_ENABLE_REG0) 99 #define HX5_INTC_INTR_STATUS_BASE (HX5_INTC_INTR_STATUS_REG0) 100 #define HX5_INTC_INTR_RAW_STATUS_BASE (HX5_INTC_INTR_RAW_STATUS_REG0) 101 102 #define IOREMAP(addr, size) ioremap_nocache(addr, size) 103 104 #define HX5_IHOST_GICD_ISENABLERN_0 (0x10781100) 105 #define HX5_IHOST_GICD_ISENABLERN_1 (0x10781104) 106 #define HX5_IHOST_GICD_ICENABLERN_1 (0x10781184) 107 #define HX5_IHOST_GICD_ICENABLERN_8 (0x107811a0) 108 /* Offset between ISENABLERN_1 and ICENABLERN_1 in 4-bytes */ 109 #define HX5_IHOST_IRQ_MASK_OFFSET 0x20 110 #define HX5_IHOST_INTR_MAP_NUM (HX5_IHOST_GICD_ICENABLERN_8 - HX5_IHOST_GICD_ISENABLERN_0) 111 #define HX5_IHOST_INTR_STATUS_MAP_NUM (INTC_INTR_REG_NUM * (sizeof(uint32))) 112 #define IRQ_BIT(intr) (intr % (sizeof(uint32)*8)) 113 #define IRQ_MASK_INDEX(intr) (intr / (sizeof(uint32)*8)) 114 #define HX5_CHIP_INTR_LOW_PRIORITY 119 115 #define INTR_LOW_PRIORITY_BITPOS (1 << IRQ_BIT(HX5_CHIP_INTR_LOW_PRIORITY)) 116 #define INTC_LOW_PRIORITY_INTR_REG_IND IRQ_MASK_INDEX(HX5_CHIP_INTR_LOW_PRIORITY) 117 #define INTC_PDMA_INTR_REG_IND 4 118 119 #define READ_INTC_INTR(d, reg, v) \ 120 (v = user_bde->iproc_read(d, reg)) 121 #define WRITE_INTC_INTR(d, reg, v) \ 122 (user_bde->iproc_write(d, reg, v)) 123 124 #define IHOST_READ_INTR(d, reg, v) \ 125 (v = readl((reg))) 126 #define IHOST_WRITE_INTR(d, reg, v) \ 127 (writel((v), (reg))) 128 129 /* Allow override of default CMICm CMC */ 130 #ifndef BDE_CMICM_PCIE_CMC 131 #define BDE_CMICM_PCIE_CMC 0 132 #endif 133 134 /* Allow override of default CMICm CMC */ 135 #ifndef BDE_CMICD_PCIE_CMC 136 #define BDE_CMICD_PCIE_CMC 0 137 #endif 138 139 /* Defines used to distinguish CMICe from CMICm */ 140 #define CMICE_DEV_REV_ID (0x178 / sizeof(uint32)) 141 142 static uint32 *ihost_intr_status_base = NULL; 143 static uint32 *ihost_intr_enable_base = NULL; 144 145 static ibde_t *user_bde = NULL; 146 147 typedef void (*isr_f)(void *); 148 149 typedef struct bde_ctrl_s { 150 uint32 dev_type; 151 int irq; 152 int enabled; 153 int devid; 154 isr_f isr; 155 uint32 *ba; 156 int inst; /* associate to _bde_inst_resource[] */ 157 } bde_ctrl_t; 158 159 #define VALID_DEVICE(_n) (_n < LINUX_BDE_MAX_DEVICES) 160 161 static bde_ctrl_t _devices[LINUX_BDE_MAX_DEVICES]; 162 163 static wait_queue_head_t _ether_interrupt_wq; 164 static atomic_t _ether_interrupt_has_taken_place = ATOMIC_INIT(0); 165 166 /* 167 * Multiple instance resource data structure. 168 * To keep the DMA resource per instance. 169 * And track the DMA pool usage. 170 */ 171 static int _bde_multi_inst = 0; 172 173 typedef struct { 174 unsigned int inst_id; 175 unsigned int dma_offset; 176 unsigned int dma_size; 177 wait_queue_head_t intr_wq; 178 atomic_t intr; 179 } bde_inst_resource_t; 180 181 static bde_inst_resource_t _bde_inst_resource[LINUX_BDE_MAX_DEVICES]; 182 183 typedef struct { 184 phys_addr_t cpu_pbase; /* CPU physical base address of the DMA pool */ 185 phys_addr_t dma_pbase; /* Bus base address of the DMA pool */ 186 uint32 total_size; /* Total size of the pool in MB */ 187 uint32 offset; /* Current offset of the pool in MB */ 188 }_dma_pool_t; 189 190 static _dma_pool_t _dma_pool; 191 192 #define ONE_MB (1024 * 1024) 193 194 #ifdef KEYSTONE 195 /* 196 * Enforce PCIE transaction ordering. Commit the write transaction. 197 */ 198 199 #define SSOC_WRITEL(val, addr) \ 200 do { \ 201 writel((val), (addr)); \ 202 __asm__ __volatile__("sync"); \ 203 } while(0) 204 205 #else 206 207 #define SSOC_WRITEL(val, addr) \ 208 writel((val), (addr)) 209 210 #endif 211 /* 212 * Function: _interrupt 213 * 214 * Purpose: 215 * Interrupt Handler. 216 * Mask all interrupts on device and wake up interrupt 217 * thread. It is assumed that the interrupt thread unmasks 218 * interrupts again when interrupt handling is complete. 219 * Parameters: 220 * ctrl - BDE control structure for this device. 221 * Returns: 222 * Nothing 223 */ 224 static void 225 _cmic_interrupt(bde_ctrl_t *ctrl) 226 { 227 int d; 228 uint32_t mask = 0, stat, imask = 0, fmask = 0; 229 bde_inst_resource_t *res; 230 231 d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); 232 res = &_bde_inst_resource[ctrl->inst]; 233 234 /* Check for secondary interrupt handler */ 235 if (lkbde_irq_mask_get(d, &mask, &fmask) < 0) { 236 fmask = 0; 237 } 238 239 if (fmask != 0) { 240 imask = mask & ~fmask; 241 /* Check for pending user mode interrupts */ 242 stat = user_bde->read(d, CMIC_IRQ_STAT); 243 if ((stat & imask) == 0) { 244 /* All handled in kernel mode */ 245 lkbde_irq_mask_set(d, CMIC_IRQ_MASK, imask, 0); 246 return; 247 } 248 } 249 250 lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0); 251 252 atomic_set(&res->intr, 1); 253 254 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 255 wake_up(&res->intr_wq); 256 #else 257 wake_up_interruptible(&res->intr_wq); 258 #endif 259 } 260 261 static void 262 _cmicx_interrupt(bde_ctrl_t *ctrl) 263 { 264 int d, ind; 265 uint32 stat, iena, mask, fmask; 266 bde_inst_resource_t *res; 267 uint32 intc_intr_status_base = 0, intc_intr_enable_base = 0; 268 269 d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); 270 res = &_bde_inst_resource[ctrl->inst]; 271 272 lkbde_irq_mask_get(d, &mask, &fmask); 273 274 if ((ctrl->dev_type & BDE_SWITCH_DEV_TYPE) && 275 ((user_bde->get_dev(d)->device == BCM56370_DEVICE_ID) || 276 (user_bde->get_dev(d)->device == BCM56371_DEVICE_ID) || 277 (user_bde->get_dev(d)->device == BCM56372_DEVICE_ID) || 278 (user_bde->get_dev(d)->device == BCM56374_DEVICE_ID) || 279 (user_bde->get_dev(d)->device == BCM56375_DEVICE_ID) || 280 (user_bde->get_dev(d)->device == BCM56376_DEVICE_ID) || 281 (user_bde->get_dev(d)->device == BCM56377_DEVICE_ID) || 282 (user_bde->get_dev(d)->device == BCM56577_DEVICE_ID) || 283 (user_bde->get_dev(d)->device == BCM56578_DEVICE_ID) || 284 (user_bde->get_dev(d)->device == BCM56579_DEVICE_ID))) { 285 intc_intr_status_base = HX5_INTC_INTR_STATUS_BASE; 286 intc_intr_enable_base = HX5_INTC_INTR_ENABLE_BASE; 287 } else { 288 intc_intr_status_base = INTC_INTR_STATUS_BASE; 289 intc_intr_enable_base = INTC_INTR_ENABLE_BASE; 290 } 291 if (fmask) { 292 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 293 IHOST_READ_INTR(d, ihost_intr_status_base + INTC_PDMA_INTR_REG_IND, stat); 294 IHOST_READ_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND, iena); 295 } else { 296 READ_INTC_INTR(d, intc_intr_status_base + 4 * INTC_PDMA_INTR_REG_IND, stat); 297 READ_INTC_INTR(d, intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, iena); 298 } 299 if (stat & iena) { 300 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 301 IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_PDMA_INTR_REG_IND + 302 HX5_IHOST_IRQ_MASK_OFFSET, ~0); 303 } else { 304 WRITE_INTC_INTR(d, intc_intr_enable_base + 4 * INTC_PDMA_INTR_REG_IND, 0); 305 } 306 307 for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { 308 if (ind == INTC_PDMA_INTR_REG_IND) { 309 continue; 310 } 311 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 312 if (ind < INTC_LOW_PRIORITY_INTR_REG_IND) { 313 continue; 314 } 315 IHOST_READ_INTR(d, ihost_intr_status_base + ind, stat); 316 IHOST_READ_INTR(d, ihost_intr_enable_base + ind, iena); 317 if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) { 318 stat &= INTR_LOW_PRIORITY_BITPOS; 319 } 320 } else { 321 READ_INTC_INTR(d, intc_intr_status_base + 4 * ind, stat); 322 READ_INTC_INTR(d, intc_intr_enable_base + 4 * ind, iena); 323 } 324 if (stat & iena) { 325 break; 326 } 327 } 328 329 if (ind >= INTC_INTR_REG_NUM) { 330 return; 331 } 332 } 333 } 334 335 /* Disable all interrupts.. Re-enable unserviced interrupts later 336 * So as to avoid getting new interrupts until the user level driver 337 * enumerates the interrupts to be serviced 338 */ 339 for (ind = 0; ind < INTC_INTR_REG_NUM; ind++) { 340 if (fmask && ind == INTC_PDMA_INTR_REG_IND) { 341 continue; 342 } 343 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 344 if (ind < INTC_LOW_PRIORITY_INTR_REG_IND) { 345 continue; 346 } 347 if (ind == INTC_LOW_PRIORITY_INTR_REG_IND) { 348 IHOST_WRITE_INTR(d, ihost_intr_enable_base + INTC_LOW_PRIORITY_INTR_REG_IND + 349 HX5_IHOST_IRQ_MASK_OFFSET, INTR_LOW_PRIORITY_BITPOS); 350 } else { 351 IHOST_WRITE_INTR(d, ihost_intr_enable_base + ind + 352 HX5_IHOST_IRQ_MASK_OFFSET, ~0); 353 } 354 } else { 355 WRITE_INTC_INTR(d, intc_intr_enable_base + 4*ind, 0); 356 } 357 } 358 359 /* Notify */ 360 atomic_set(&res->intr, 1); 361 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 362 wake_up(&res->intr_wq); 363 #else 364 wake_up_interruptible(&res->intr_wq); 365 #endif 366 } 367 368 static void 369 _cmicm_interrupt(bde_ctrl_t *ctrl) 370 { 371 int d; 372 int cmc = BDE_CMICM_PCIE_CMC; 373 uint32 stat, mask = 0, fmask = 0, imask = 0; 374 bde_inst_resource_t *res; 375 376 d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); 377 res = &_bde_inst_resource[ctrl->inst]; 378 379 lkbde_irq_mask_get(d, &mask, &fmask); 380 381 while (fmask) { 382 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 383 imask = mask & ~fmask; 384 if (stat & imask) { 385 break; 386 } 387 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 388 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 389 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); 390 } else { 391 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); 392 } 393 if (stat & mask) { 394 break; 395 } 396 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 397 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 398 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); 399 } else { 400 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); 401 } 402 if (stat & mask) { 403 break; 404 } 405 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 406 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 407 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); 408 } else { 409 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); 410 } 411 if (stat & mask) { 412 break; 413 } 414 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); 415 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 416 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); 417 } else { 418 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); 419 } 420 if (stat & mask) { 421 break; 422 } 423 return; 424 } 425 426 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 427 lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); 428 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); 429 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); 430 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); 431 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); 432 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0); 433 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0); 434 } 435 else { 436 lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); 437 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); 438 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); 439 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); 440 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); 441 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0); 442 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0); 443 } 444 atomic_set(&res->intr, 1); 445 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 446 wake_up(&res->intr_wq); 447 #else 448 wake_up_interruptible(&res->intr_wq); 449 #endif 450 } 451 452 /* some device has cmc0 only */ 453 static void 454 _cmicd_cmc0_interrupt(bde_ctrl_t *ctrl) 455 { 456 int d; 457 int cmc = 0; 458 uint32 stat, mask = 0, fmask = 0, imask = 0; 459 bde_inst_resource_t *res; 460 461 d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); 462 res = &_bde_inst_resource[ctrl->inst]; 463 lkbde_irq_mask_get(d, &mask, &fmask); 464 465 while (fmask) { 466 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 467 imask = mask & ~fmask; 468 if (stat & imask) { 469 break; 470 } 471 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 472 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 473 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); 474 } else { 475 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); 476 } 477 if (stat & mask) { 478 break; 479 } 480 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 481 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 482 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); 483 } else { 484 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); 485 } 486 if (stat & mask) { 487 break; 488 } 489 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 490 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 491 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); 492 } else { 493 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); 494 } 495 if (stat & mask) { 496 break; 497 } 498 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); 499 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 500 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); 501 } else { 502 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); 503 } 504 if (stat & mask) { 505 break; 506 } 507 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); 508 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 509 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc)); 510 } else { 511 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc)); 512 } 513 if (stat & mask) { 514 break; 515 } 516 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); 517 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 518 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc)); 519 } else { 520 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc)); 521 } 522 if (stat & mask) { 523 break; 524 } 525 return; 526 } 527 528 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 529 lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); 530 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); 531 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); 532 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); 533 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); 534 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0); 535 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0); 536 } else { 537 lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); 538 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); 539 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); 540 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); 541 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); 542 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0); 543 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0); 544 } 545 atomic_set(&res->intr, 1); 546 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 547 wake_up(&res->intr_wq); 548 #else 549 wake_up_interruptible(&res->intr_wq); 550 #endif 551 } 552 553 static void 554 _cmicd_interrupt(bde_ctrl_t *ctrl) 555 { 556 int d; 557 int cmc = BDE_CMICD_PCIE_CMC; 558 uint32 stat, mask = 0, fmask = 0, imask = 0; 559 bde_inst_resource_t *res; 560 561 d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); 562 res = &_bde_inst_resource[ctrl->inst]; 563 lkbde_irq_mask_get(d, &mask, &fmask); 564 565 while (fmask) { 566 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT0_OFFSET(cmc)); 567 imask = mask & ~fmask; 568 if (stat & imask) { 569 break; 570 } 571 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT1_OFFSET(cmc)); 572 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 573 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc)); 574 } else { 575 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc)); 576 } 577 if (stat & mask) { 578 break; 579 } 580 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT2_OFFSET(cmc)); 581 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 582 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc)); 583 } else { 584 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc)); 585 } 586 if (stat & mask) { 587 break; 588 } 589 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT3_OFFSET(cmc)); 590 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 591 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc)); 592 } else { 593 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc)); 594 } 595 if (stat & mask) { 596 break; 597 } 598 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT4_OFFSET(cmc)); 599 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 600 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc)); 601 } else { 602 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc)); 603 } 604 if (stat & mask) { 605 break; 606 } 607 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT5_OFFSET(cmc)); 608 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 609 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc)); 610 } else { 611 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc)); 612 } 613 if (stat & mask) { 614 break; 615 } 616 stat = user_bde->read(d, CMIC_CMCx_IRQ_STAT6_OFFSET(cmc)); 617 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 618 mask = user_bde->read(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc)); 619 } else { 620 mask = user_bde->read(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc)); 621 } 622 if (stat & mask) { 623 break; 624 } 625 return; 626 } 627 628 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 629 lkbde_irq_mask_set(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(cmc), 0, 0); 630 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK1_OFFSET(cmc), 0); 631 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK2_OFFSET(cmc), 0); 632 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK3_OFFSET(cmc), 0); 633 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK4_OFFSET(cmc), 0); 634 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK5_OFFSET(cmc), 0); 635 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK6_OFFSET(cmc), 0); 636 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(1), 0); 637 user_bde->write(d, CMIC_CMCx_UC0_IRQ_MASK0_OFFSET(2), 0); 638 } else { 639 lkbde_irq_mask_set(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(cmc), 0, 0); 640 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK1_OFFSET(cmc), 0); 641 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK2_OFFSET(cmc), 0); 642 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK3_OFFSET(cmc), 0); 643 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK4_OFFSET(cmc), 0); 644 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK5_OFFSET(cmc), 0); 645 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK6_OFFSET(cmc), 0); 646 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(1), 0); 647 user_bde->write(d, CMIC_CMCx_PCIE_IRQ_MASK0_OFFSET(2), 0); 648 } 649 atomic_set(&res->intr, 1); 650 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 651 wake_up(&res->intr_wq); 652 #else 653 wake_up_interruptible(&res->intr_wq); 654 #endif 655 } 656 657 static void 658 _bcm88750_interrupt(bde_ctrl_t *ctrl) 659 { 660 int d; 661 bde_inst_resource_t *res; 662 663 d = (((uint8 *)ctrl - (uint8 *)_devices) / sizeof (bde_ctrl_t)); 664 res = &_bde_inst_resource[ctrl->inst]; 665 lkbde_irq_mask_set(d, CMIC_IRQ_MASK, 0, 0); 666 667 lkbde_irq_mask_set(d, CMIC_IRQ_MASK_1, 0, 0); 668 lkbde_irq_mask_set(d, CMIC_IRQ_MASK_2, 0, 0); 669 atomic_set(&res->intr, 1); 670 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 671 wake_up(&res->intr_wq); 672 #else 673 wake_up_interruptible(&res->intr_wq); 674 #endif 675 } 676 677 /* The actual interrupt handler of ethernet devices */ 678 static void 679 _ether_interrupt(bde_ctrl_t *ctrl) 680 { 681 SSOC_WRITEL(0, ctrl->ba + 0x024/4); 682 683 atomic_set(&_ether_interrupt_has_taken_place, 1); 684 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 685 wake_up(&_ether_interrupt_wq); 686 #else 687 wake_up_interruptible(&_ether_interrupt_wq); 688 #endif 689 } 690 691 692 static struct _intr_mode_s { 693 isr_f isr; 694 const char *name; 695 } _intr_mode[] = { 696 { (isr_f)_cmic_interrupt, "CMIC/CMICe" }, 697 { (isr_f)_cmicm_interrupt, "CMICm" }, 698 { (isr_f)_cmicd_interrupt, "CMICd" }, 699 { (isr_f)_cmicd_cmc0_interrupt, "CMICd CMC0" }, 700 { (isr_f)_bcm88750_interrupt, "BCM88750" }, 701 { (isr_f)_cmicx_interrupt, "CMICx" }, 702 { NULL, NULL } 703 }; 704 705 static const char * 706 _intr_mode_str(void *isr) 707 { 708 int imx; 709 710 imx = 0; 711 while (_intr_mode[imx].isr != NULL) { 712 if (isr == _intr_mode[imx].isr) { 713 return _intr_mode[imx].name; 714 } 715 imx++; 716 } 717 return NULL; 718 } 719 720 static void 721 _devices_init(int d) 722 { 723 bde_ctrl_t *ctrl; 724 uint32 ver; 725 uint16 device_id_mask = 0xFFF0; 726 uint16 device_id; 727 uint32 state = 0; 728 729 (void)lkbde_dev_state_get(d, &state); 730 if (state == BDE_DEV_STATE_REMOVED) { 731 return; 732 } 733 734 ctrl = &_devices[d]; 735 /* Initialize our control info */ 736 ctrl->dev_type = user_bde->get_dev_type(d); 737 ctrl->devid = user_bde->get_dev(d)->device; 738 ctrl->inst = 0; 739 740 if (BDE_DEV_MEM_MAPPED(ctrl->dev_type)) { 741 ctrl->enabled = 0; 742 ctrl->ba = lkbde_get_dev_virt(d); 743 } 744 if (ctrl->dev_type & BDE_SWITCH_DEV_TYPE) { 745 switch (user_bde->get_dev(d)->device) { 746 case BCM88750_DEVICE_ID: 747 case BCM88753_DEVICE_ID: 748 case BCM88754_DEVICE_ID: 749 case BCM88755_DEVICE_ID: 750 case BCM88752_DEVICE_ID: 751 ctrl->isr = (isr_f)_bcm88750_interrupt; 752 break; 753 case BCM53540_DEVICE_ID: 754 case BCM53547_DEVICE_ID: 755 case BCM53548_DEVICE_ID: 756 case BCM53549_DEVICE_ID: 757 case BCM88670_DEVICE_ID: 758 case BCM88671_DEVICE_ID: 759 case BCM88671M_DEVICE_ID: 760 case BCM88672_DEVICE_ID: 761 case BCM88673_DEVICE_ID: 762 case BCM88674_DEVICE_ID: 763 case BCM88675_DEVICE_ID: 764 case BCM88675M_DEVICE_ID: 765 case BCM88676_DEVICE_ID: 766 case BCM88676M_DEVICE_ID: 767 case BCM88677_DEVICE_ID: 768 case BCM88678_DEVICE_ID: 769 case BCM88679_DEVICE_ID: 770 case BCM88370_DEVICE_ID: 771 case BCM88371_DEVICE_ID: 772 case BCM88371M_DEVICE_ID: 773 case BCM88375_DEVICE_ID: 774 case BCM88376_DEVICE_ID: 775 case BCM88376M_DEVICE_ID: 776 case BCM88377_DEVICE_ID: 777 case BCM88378_DEVICE_ID: 778 case BCM88379_DEVICE_ID: 779 case BCM88681_DEVICE_ID: 780 case BCM88682_DEVICE_ID: 781 case BCM88683_DEVICE_ID: 782 case BCM88684_DEVICE_ID: 783 case BCM88685_DEVICE_ID: 784 case BCM88380_DEVICE_ID: 785 case BCM88381_DEVICE_ID: 786 case BCM88680_DEVICE_ID: 787 case BCM88800_DEVICE_ID: 788 case BCM88770_DEVICE_ID: 789 case BCM88773_DEVICE_ID: 790 case BCM88774_DEVICE_ID: 791 case BCM88775_DEVICE_ID: 792 case BCM88776_DEVICE_ID: 793 case BCM88777_DEVICE_ID: 794 case BCM88470_DEVICE_ID: 795 case BCM88470P_DEVICE_ID: 796 case BCM88471_DEVICE_ID: 797 case BCM88473_DEVICE_ID: 798 case BCM88474_DEVICE_ID: 799 case BCM88474H_DEVICE_ID: 800 case BCM88476_DEVICE_ID: 801 case BCM88477_DEVICE_ID: 802 case BCM88270_DEVICE_ID: 803 case BCM88272_DEVICE_ID: 804 case BCM88273_DEVICE_ID: 805 case BCM88274_DEVICE_ID: 806 case BCM88278_DEVICE_ID: 807 case BCM88279_DEVICE_ID: 808 case BCM8206_DEVICE_ID: 809 case BCM88950_DEVICE_ID: 810 case BCM88953_DEVICE_ID: 811 case BCM88954_DEVICE_ID: 812 case BCM88955_DEVICE_ID: 813 case BCM88956_DEVICE_ID: 814 case BCM88772_DEVICE_ID: 815 case BCM88952_DEVICE_ID: 816 ctrl->isr = (isr_f)_cmicd_cmc0_interrupt; 817 break; 818 case BCM88790_DEVICE_ID: 819 ctrl->isr = (isr_f)_cmicx_interrupt; 820 break; 821 case BCM56370_DEVICE_ID: 822 case BCM56371_DEVICE_ID: 823 case BCM56372_DEVICE_ID: 824 case BCM56374_DEVICE_ID: 825 case BCM56375_DEVICE_ID: 826 case BCM56376_DEVICE_ID: 827 case BCM56377_DEVICE_ID: 828 case BCM56577_DEVICE_ID: 829 case BCM56578_DEVICE_ID: 830 case BCM56579_DEVICE_ID: 831 ctrl->isr = (isr_f)_cmicx_interrupt; 832 if (ctrl->dev_type & BDE_AXI_DEV_TYPE) { 833 if (!ihost_intr_enable_base) { 834 ihost_intr_enable_base = (uint32_t *)IOREMAP(HX5_IHOST_GICD_ISENABLERN_1, 835 HX5_IHOST_INTR_MAP_NUM); 836 } 837 if (!ihost_intr_status_base) { 838 ihost_intr_status_base = (uint32_t *)IOREMAP(HX5_INTC_INTR_RAW_STATUS_REG0, 839 HX5_IHOST_INTR_STATUS_MAP_NUM); 840 } 841 } 842 break; 843 default: 844 /* Get CMIC version */ 845 if (user_bde->get_cmic_ver(d, &ver) != 0) { 846 ver = -1; 847 } 848 device_id = ctrl->devid & device_id_mask; 849 /* TH/TH+/TH2 should use cmicd interrupt handler */ 850 if (BCM56960_DEVICE_ID == device_id || 851 BCM56930_DEVICE_ID == device_id || 852 BCM56970_DEVICE_ID == device_id) { 853 ctrl->isr = (isr_f)_cmicd_interrupt; 854 } 855 /* check if version is CMICX */ 856 else if (ver == 0x04) { 857 ctrl->isr = (isr_f)_cmicx_interrupt; 858 } else { 859 ctrl->isr = (isr_f)_cmic_interrupt; 860 if ((ctrl->dev_type & BDE_256K_REG_SPACE) && 861 #ifdef BCM_PETRA_SUPPORT /* FIXME remove code when hardware design is fixed */ 862 ctrl->devid != 0x1234 && 863 #endif 864 readl(ctrl->ba + CMICE_DEV_REV_ID) == 0) { 865 ctrl->isr = (isr_f)_cmicm_interrupt; 866 } 867 } 868 break; 869 } 870 871 #ifdef BCM_DNX_SUPPORT 872 /*All Jericho 2 devices from 0x8690 to 0x869F*/ 873 if (SOC_IS_JERICHO_2_TYPE(user_bde->get_dev(d)->device)) { 874 ctrl->isr = (isr_f)_cmicx_interrupt; 875 } 876 #endif 877 878 /*All Ramon devices from 0x8790 to 0x879F*/ 879 if ((user_bde->get_dev(d)->device & BCM88790_DEVICE_ID) == BCM88790_DEVICE_ID) { 880 ctrl->isr = (isr_f)_cmicx_interrupt; 881 } 882 if (_intr_mode_str(ctrl->isr) == NULL) { 883 gprintk("Warning: Unknown interrupt mode\n"); 884 } 885 } 886 } 887 /* 888 * Function: _init 889 * 890 * Purpose: 891 * Module initialization. 892 * Attaches to kernel BDE. 893 * Parameters: 894 * None 895 * Returns: 896 * Always 0 897 */ 898 static int 899 _init(void) 900 { 901 int i; 902 phys_addr_t cpu_pbase, dma_pbase; 903 ssize_t dmasize; 904 bde_inst_resource_t *res; 905 906 /* Connect to the kernel bde */ 907 if ((linux_bde_create(NULL, &user_bde) < 0) || user_bde == NULL) { 908 return -ENODEV; 909 } 910 911 init_waitqueue_head(&_ether_interrupt_wq); 912 913 lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &dmasize); 914 915 memset(&_dma_pool, 0, sizeof(_dma_pool)); 916 _dma_pool.cpu_pbase = cpu_pbase; 917 _dma_pool.dma_pbase = dma_pbase; 918 _dma_pool.total_size = dmasize / ONE_MB; 919 920 memset(_devices, 0, sizeof(_devices)); 921 922 /* Use _bde_inst_resource[0] as the default resource */ 923 memset(_bde_inst_resource, 0, sizeof(_bde_inst_resource)); 924 res = &_bde_inst_resource[0]; 925 res->dma_offset = 0; 926 res->dma_size = _dma_pool.total_size; 927 init_waitqueue_head(&res->intr_wq); 928 atomic_set(&res->intr, 0); 929 930 ihost_intr_enable_base = NULL; 931 ihost_intr_status_base = NULL; 932 933 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 934 res->inst_id |= (1 << i); 935 _devices_init(i); 936 } 937 938 return 0; 939 } 940 941 /* 942 * Function: _cleanup 943 * 944 * Purpose: 945 * Module cleanup function. 946 * Parameters: 947 * None 948 * Returns: 949 * Always 0 950 */ 951 static int 952 _cleanup(void) 953 { 954 int i; 955 956 if (user_bde) { 957 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 958 if (_devices[i].enabled && 959 BDE_DEV_MEM_MAPPED(_devices[i].dev_type)) { 960 user_bde->interrupt_disconnect(i); 961 } 962 lkbde_dev_instid_set(i, 0); 963 } 964 linux_bde_destroy(user_bde); 965 user_bde = NULL; 966 } 967 968 if (ihost_intr_enable_base) { 969 iounmap(ihost_intr_enable_base); 970 ihost_intr_enable_base = NULL; 971 } 972 if (ihost_intr_status_base) { 973 iounmap(ihost_intr_status_base); 974 ihost_intr_status_base = NULL; 975 } 976 977 return 0; 978 } 979 980 /* 981 * Function: _pprint 982 * 983 * Purpose: 984 * Print proc filesystem information. 985 * Parameters: 986 * None 987 * Returns: 988 * Always 0 989 */ 990 static int 991 _pprint(void) 992 { 993 int idx; 994 const char *name; 995 bde_inst_resource_t *res; 996 uint32 state, instid; 997 998 pprintf("Broadcom Device Enumerator (%s)\n", LINUX_USER_BDE_NAME); 999 for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { 1000 name = _intr_mode_str(_devices[idx].isr); 1001 if (name == NULL) { 1002 name = "unknown"; 1003 } 1004 pprintf("\t%d: Interrupt mode %s ",idx, name); 1005 (void)lkbde_dev_state_get(idx, &state); 1006 if (state == BDE_DEV_STATE_REMOVED) { 1007 pprintf(" Device REMOVED ! \n"); 1008 } else { 1009 (void)lkbde_dev_instid_get(idx, &instid); 1010 if (instid) { 1011 pprintf("Inst id 0x%x\n",instid); 1012 } else { 1013 pprintf("\n"); 1014 } 1015 } 1016 } 1017 pprintf("Instance resource \n"); 1018 1019 for (idx = 0; idx < user_bde->num_devices(BDE_ALL_DEVICES); idx++) { 1020 res = &_bde_inst_resource[idx]; 1021 if (res->inst_id) { 1022 pprintf("\tDev mask 0x%x : " 1023 "DMA offset %d size %d MB\n", 1024 res->inst_id, 1025 res->dma_offset, 1026 res->dma_size); 1027 } 1028 } 1029 1030 return 0; 1031 } 1032 1033 /* 1034 * Allocate the DMA resource from DMA pool 1035 * Parameter : 1036 * dma_size (IN): allocate dma_size in MB 1037 * dma_offset (OUT): dma offset in MB 1038 */ 1039 static int 1040 _dma_resource_alloc(unsigned int dma_size, unsigned int *dma_offset) 1041 { 1042 uint32 left; 1043 1044 left = _dma_pool.total_size - _dma_pool.offset; 1045 if (dma_size > left) { 1046 gprintk("ERROR: Run out the dma resource!\n"); 1047 return -1; 1048 } 1049 *dma_offset = _dma_pool.offset; 1050 _dma_pool.offset += dma_size; 1051 return 0; 1052 } 1053 1054 static int 1055 _dma_resource_get(int inst_id, phys_addr_t *cpu_pbase, phys_addr_t *dma_pbase, ssize_t* size) 1056 { 1057 int i; 1058 unsigned int dma_size = 0, dma_offset = 0; 1059 bde_inst_resource_t *res; 1060 1061 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 1062 res = &_bde_inst_resource[i]; 1063 if (res->inst_id == inst_id) { 1064 dma_size = res->dma_size; 1065 dma_offset = res->dma_offset; 1066 break; 1067 } 1068 } 1069 1070 *cpu_pbase = _dma_pool.cpu_pbase + dma_offset * ONE_MB; 1071 *dma_pbase = _dma_pool.dma_pbase + dma_offset * ONE_MB; 1072 *size = dma_size * ONE_MB; 1073 1074 return 0; 1075 } 1076 1077 static int 1078 _instance_validate(unsigned int inst_id, unsigned int dmasize) 1079 { 1080 int i; 1081 bde_inst_resource_t *res; 1082 1083 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 1084 res = &_bde_inst_resource[i]; 1085 if (res->inst_id == inst_id) { 1086 if (res->dma_size != dmasize) { 1087 if(_devices[i].inst == 0){ 1088 /* Skip _instance_validate (not init yet) */ 1089 return LUBDE_SUCCESS; 1090 } 1091 gprintk("ERROR: dma_size mismatch\n"); 1092 return LUBDE_FAIL; 1093 } 1094 return (1); 1095 } 1096 } 1097 return LUBDE_SUCCESS; 1098 } 1099 1100 static int 1101 _device_reprobe(void) 1102 { 1103 int i; 1104 1105 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 1106 if (_devices[i].devid == 0) { 1107 _devices_init(i); 1108 } 1109 } 1110 return 0; 1111 } 1112 1113 static int 1114 _instance_attach(unsigned int inst_id, unsigned int dma_size) 1115 { 1116 unsigned int dma_offset; 1117 int i, exist; 1118 bde_inst_resource_t *res; 1119 int inst_idx = -1; 1120 uint32 instid; 1121 1122 /* Reprobe the system for hot-plugged device */ 1123 _device_reprobe(); 1124 1125 /* Validate the resource with inst_id */ 1126 exist = _instance_validate(inst_id, dma_size); 1127 if (exist < 0) { 1128 return LUBDE_FAIL; 1129 } 1130 if (exist > 0) { 1131 return LUBDE_SUCCESS; 1132 } 1133 if (_dma_resource_alloc(dma_size, &dma_offset) < 0) { 1134 return LUBDE_FAIL; 1135 } 1136 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 1137 res = &_bde_inst_resource[i]; 1138 if ((_bde_multi_inst == 0) || (res->inst_id == 0)) { 1139 res->inst_id = inst_id; 1140 res->dma_offset = dma_offset; 1141 res->dma_size = dma_size; 1142 _bde_multi_inst++; 1143 inst_idx = i; 1144 init_waitqueue_head(&res->intr_wq); 1145 atomic_set(&res->intr, 0); 1146 break; 1147 } 1148 } 1149 1150 for (i = 0; i < user_bde->num_devices(BDE_ALL_DEVICES); i++) { 1151 if (inst_id & (1 << i)) { 1152 _devices[i].inst = inst_idx; 1153 /* Pass the instid to the kernel BDE */ 1154 if (lkbde_dev_instid_get(i, &instid) == 0) { 1155 if (!instid) { 1156 lkbde_dev_instid_set(i, inst_id); 1157 } 1158 } 1159 } 1160 } 1161 1162 return LUBDE_SUCCESS; 1163 } 1164 1165 /* 1166 * Function: _ioctl 1167 * 1168 * Purpose: 1169 * Handle IOCTL commands from user mode. 1170 * Parameters: 1171 * cmd - IOCTL cmd 1172 * arg - IOCTL parameters 1173 * Returns: 1174 * 0 on success, <0 on error 1175 */ 1176 static int 1177 _ioctl(unsigned int cmd, unsigned long arg) 1178 { 1179 lubde_ioctl_t io; 1180 phys_addr_t cpu_pbase, dma_pbase; 1181 ssize_t size; 1182 const ibde_dev_t *bde_dev; 1183 int inst_id; 1184 bde_inst_resource_t *res; 1185 uint32_t *mapaddr; 1186 1187 if (copy_from_user(&io, (void *)arg, sizeof(io))) { 1188 return -EFAULT; 1189 } 1190 1191 io.rc = LUBDE_SUCCESS; 1192 1193 switch(cmd) { 1194 case LUBDE_VERSION: 1195 io.d0 = KBDE_VERSION; 1196 break; 1197 case LUBDE_GET_NUM_DEVICES: 1198 io.d0 = user_bde->num_devices(io.dev); 1199 break; 1200 case LUBDE_GET_DEVICE: 1201 if (!VALID_DEVICE(io.dev)) { 1202 return -EINVAL; 1203 } 1204 bde_dev = user_bde->get_dev(io.dev); 1205 if (bde_dev) { 1206 io.d0 = bde_dev->device; 1207 io.d1 = bde_dev->rev; 1208 if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { 1209 /* Get physical address to map */ 1210 io.d2 = lkbde_get_dev_phys(io.dev); 1211 io.d3 = lkbde_get_dev_phys_hi(io.dev); 1212 } 1213 } else { 1214 io.rc = LUBDE_FAIL; 1215 } 1216 break; 1217 case LUBDE_GET_DEVICE_TYPE: 1218 if (!VALID_DEVICE(io.dev)) { 1219 return -EINVAL; 1220 } 1221 io.d0 = _devices[io.dev].dev_type; 1222 break; 1223 case LUBDE_GET_BUS_FEATURES: 1224 user_bde->pci_bus_features(io.dev, (int *) &io.d0, (int *) &io.d1, 1225 (int *) &io.d2); 1226 break; 1227 case LUBDE_PCI_CONFIG_PUT32: 1228 if (!VALID_DEVICE(io.dev)) { 1229 return -EINVAL; 1230 } 1231 if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) { 1232 user_bde->pci_conf_write(io.dev, io.d0, io.d1); 1233 } else { 1234 io.rc = LUBDE_FAIL; 1235 } 1236 break; 1237 case LUBDE_PCI_CONFIG_GET32: 1238 if (!VALID_DEVICE(io.dev)) { 1239 return -EINVAL; 1240 } 1241 if (_devices[io.dev].dev_type & BDE_PCI_DEV_TYPE) { 1242 io.d0 = user_bde->pci_conf_read(io.dev, io.d0); 1243 } else { 1244 io.rc = LUBDE_FAIL; 1245 } 1246 break; 1247 case LUBDE_GET_DMA_INFO: 1248 inst_id = io.dev; 1249 if (_bde_multi_inst){ 1250 _dma_resource_get(inst_id, &cpu_pbase, &dma_pbase, &size); 1251 } else { 1252 lkbde_get_dma_info(&cpu_pbase, &dma_pbase, &size); 1253 } 1254 io.d0 = dma_pbase; 1255 io.d1 = size; 1256 /* Optionally enable DMA mmap via /dev/linux-kernel-bde */ 1257 io.d2 = USE_LINUX_BDE_MMAP; 1258 /* Get physical address for mmap */ 1259 io.dx.dw[0] = cpu_pbase; 1260 #ifdef PHYS_ADDRS_ARE_64BITS 1261 io.dx.dw[1] = cpu_pbase >> 32; 1262 #else 1263 io.dx.dw[1] = 0; 1264 #endif 1265 break; 1266 case LUBDE_ENABLE_INTERRUPTS: 1267 if (!VALID_DEVICE(io.dev)) { 1268 return -EINVAL; 1269 } 1270 if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { 1271 if (_devices[io.dev].isr && !_devices[io.dev].enabled) { 1272 user_bde->interrupt_connect(io.dev, 1273 _devices[io.dev].isr, 1274 _devices+io.dev); 1275 _devices[io.dev].enabled = 1; 1276 } 1277 } else { 1278 /* Process ethernet device interrupt */ 1279 /* FIXME: for multiple chips */ 1280 if (!_devices[io.dev].enabled) { 1281 user_bde->interrupt_connect(io.dev, 1282 (void(*)(void *))_ether_interrupt, 1283 _devices+io.dev); 1284 _devices[io.dev].enabled = 1; 1285 } 1286 } 1287 break; 1288 case LUBDE_DISABLE_INTERRUPTS: 1289 if (!VALID_DEVICE(io.dev)) { 1290 return -EINVAL; 1291 } 1292 if (_devices[io.dev].enabled) { 1293 user_bde->interrupt_disconnect(io.dev); 1294 _devices[io.dev].enabled = 0; 1295 } 1296 break; 1297 case LUBDE_WAIT_FOR_INTERRUPT: 1298 if (!VALID_DEVICE(io.dev)) { 1299 return -EINVAL; 1300 } 1301 if (_devices[io.dev].dev_type & BDE_SWITCH_DEV_TYPE) { 1302 res = &_bde_inst_resource[_devices[io.dev].inst]; 1303 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 1304 wait_event_timeout(res->intr_wq, 1305 atomic_read(&res->intr) != 0, 100); 1306 1307 #else 1308 wait_event_interruptible(res->intr_wq, 1309 atomic_read(&res->intr) != 0); 1310 #endif 1311 /* 1312 * Even if we get multiple interrupts, we 1313 * only run the interrupt handler once. 1314 */ 1315 atomic_set(&res->intr, 0); 1316 } else { 1317 #ifdef BDE_LINUX_NON_INTERRUPTIBLE 1318 wait_event_timeout(_ether_interrupt_wq, 1319 atomic_read(&_ether_interrupt_has_taken_place) != 0, 100); 1320 #else 1321 wait_event_interruptible(_ether_interrupt_wq, 1322 atomic_read(&_ether_interrupt_has_taken_place) != 0); 1323 #endif 1324 /* 1325 * Even if we get multiple interrupts, we 1326 * only run the interrupt handler once. 1327 */ 1328 atomic_set(&_ether_interrupt_has_taken_place, 0); 1329 } 1330 break; 1331 case LUBDE_USLEEP: 1332 case LUBDE_UDELAY: 1333 case LUBDE_SEM_OP: 1334 return -EINVAL; 1335 case LUBDE_WRITE_IRQ_MASK: 1336 io.rc = lkbde_irq_mask_set(io.dev, io.d0, io.d1, 0); 1337 break; 1338 case LUBDE_SPI_READ_REG: 1339 if (user_bde->spi_read(io.dev, io.d0, io.dx.buf, io.d1) == -1) { 1340 io.rc = LUBDE_FAIL; 1341 } 1342 break; 1343 case LUBDE_SPI_WRITE_REG: 1344 if (user_bde->spi_write(io.dev, io.d0, io.dx.buf, io.d1) == -1) { 1345 io.rc = LUBDE_FAIL; 1346 } 1347 break; 1348 case LUBDE_READ_REG_16BIT_BUS: 1349 io.d1 = user_bde->read(io.dev, io.d0); 1350 break; 1351 case LUBDE_WRITE_REG_16BIT_BUS: 1352 io.rc = user_bde->write(io.dev, io.d0, io.d1); 1353 break; 1354 #ifdef BCM_SAND_SUPPORT 1355 case LUBDE_CPU_WRITE_REG: 1356 { 1357 if (lkbde_cpu_write(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { 1358 io.rc = LUBDE_FAIL; 1359 } 1360 break; 1361 } 1362 case LUBDE_CPU_READ_REG: 1363 { 1364 if (lkbde_cpu_read(io.dev, io.d0, (uint32*)io.dx.buf) == -1) { 1365 io.rc = LUBDE_FAIL; 1366 } 1367 break; 1368 } 1369 case LUBDE_CPU_PCI_REGISTER: 1370 { 1371 if (lkbde_cpu_pci_register(io.dev) == -1) { 1372 io.rc = LUBDE_FAIL; 1373 } 1374 break; 1375 } 1376 #endif 1377 case LUBDE_DEV_RESOURCE: 1378 if (!VALID_DEVICE(io.dev)) { 1379 return -EINVAL; 1380 } 1381 bde_dev = user_bde->get_dev(io.dev); 1382 if (bde_dev) { 1383 if (BDE_DEV_MEM_MAPPED(_devices[io.dev].dev_type)) { 1384 /* Get physical address to map */ 1385 io.rc = lkbde_get_dev_resource(io.dev, io.d0, 1386 &io.d1, &io.d2, &io.d3); 1387 } 1388 } else { 1389 io.rc = LUBDE_FAIL; 1390 } 1391 break; 1392 case LUBDE_IPROC_READ_REG: 1393 if (!VALID_DEVICE(io.dev)) { 1394 return -EINVAL; 1395 } 1396 if (_devices[io.dev].dev_type & BDE_AXI_DEV_TYPE) { 1397 mapaddr = IOREMAP(io.d0, sizeof(uint32_t)); 1398 if (mapaddr == NULL) { 1399 io.rc = LUBDE_FAIL; 1400 return -1; 1401 } 1402 io.d1 = readl(mapaddr); 1403 iounmap(mapaddr); 1404 } else { 1405 io.d1 = user_bde->iproc_read(io.dev, io.d0); 1406 if (io.d1 == -1) { 1407 io.rc = LUBDE_FAIL; 1408 } 1409 } 1410 break; 1411 case LUBDE_IPROC_WRITE_REG: 1412 if (user_bde->iproc_write(io.dev, io.d0, io.d1) == -1) { 1413 io.rc = LUBDE_FAIL; 1414 } 1415 break; 1416 case LUBDE_ATTACH_INSTANCE: 1417 io.rc = _instance_attach(io.d0, io.d1); 1418 break; 1419 case LUBDE_GET_DEVICE_STATE: 1420 io.rc = lkbde_dev_state_get(io.dev, &io.d0); 1421 break; 1422 case LUBDE_REPROBE: 1423 io.rc = _device_reprobe(); 1424 break; 1425 default: 1426 gprintk("Error: Invalid ioctl (%08x)\n", cmd); 1427 io.rc = LUBDE_FAIL; 1428 break; 1429 } 1430 1431 if (copy_to_user((void *)arg, &io, sizeof(io))) { 1432 return -EFAULT; 1433 } 1434 1435 return 0; 1436 } 1437 1438 /* Workaround for broken Busybox/PPC insmod */ 1439 static char _modname[] = LINUX_USER_BDE_NAME; 1440 1441 static gmodule_t _gmodule = 1442 { 1443 name: LINUX_USER_BDE_NAME, 1444 major: LINUX_USER_BDE_MAJOR, 1445 init: _init, 1446 cleanup: _cleanup, 1447 pprint: _pprint, 1448 ioctl: _ioctl, 1449 }; 1450 1451 gmodule_t* 1452 gmodule_get(void) 1453 { 1454 _gmodule.name = _modname; 1455 return &_gmodule; 1456 }