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