1/* 2 * SDIO access interface for drivers - linux specific (pci only) 3 * 4 * Copyright (C) 1999-2012, Broadcom Corporation 5 * 6 * Unless you and Broadcom execute a separate written software license 7 * agreement governing use of this software, this software is licensed to you 8 * under the terms of the GNU General Public License version 2 (the "GPL"), 9 * available at http://www.broadcom.com/licenses/GPLv2.php, with the 10 * following added to such license: 11 * 12 * As a special exception, the copyright holders of this software give you 13 * permission to link this software with independent modules, and to copy and 14 * distribute the resulting executable under terms of your choice, provided that 15 * you also meet, for each linked independent module, the terms and conditions of 16 * the license of that module. An independent module is a module which is not 17 * derived from this software. The special exception does not apply to any 18 * modifications of the software. 19 * 20 * Notwithstanding the above, under no circumstances may you combine this 21 * software in any way with any other Broadcom software provided under a license 22 * other than the GPL, without Broadcom's express prior written consent. 23 * 24 * $Id: bcmsdh_linux.c 309796 2012-01-20 18:21:51Z $ 25 */ 26 27/** 28 * @file bcmsdh_linux.c 29 */ 30 31#define __UNDEF_NO_VERSION__ 32 33#include <typedefs.h> 34#include <linuxver.h> 35 36#include <linux/pci.h> 37#include <linux/completion.h> 38 39#include <osl.h> 40#include <pcicfg.h> 41#include <bcmdefs.h> 42#include <bcmdevs.h> 43 44#if defined(OOB_INTR_ONLY) 45#include <linux/irq.h> 46extern void dhdsdio_isr(void * args); 47#include <bcmutils.h> 48#include <dngl_stats.h> 49#include <dhd.h> 50#endif /* defined(OOB_INTR_ONLY) */ 51 52/** 53 * SDIO Host Controller info 54 */ 55typedef struct bcmsdh_hc bcmsdh_hc_t; 56 57struct bcmsdh_hc { 58 bcmsdh_hc_t *next; 59#ifdef BCMPLATFORM_BUS 60 struct device *dev; /* platform device handle */ 61#else 62 struct pci_dev *dev; /* pci device handle */ 63#endif /* BCMPLATFORM_BUS */ 64 osl_t *osh; 65 void *regs; /* SDIO Host Controller address */ 66 bcmsdh_info_t *sdh; /* SDIO Host Controller handle */ 67 void *ch; 68 unsigned int oob_irq; 69 unsigned long oob_flags; /* OOB Host specifiction as edge and etc */ 70 bool oob_irq_registered; 71 bool oob_irq_enable_flag; 72#if defined(OOB_INTR_ONLY) 73 spinlock_t irq_lock; 74#endif 75}; 76static bcmsdh_hc_t *sdhcinfo = NULL; 77 78/* driver info, initialized when bcmsdh_register is called */ 79static bcmsdh_driver_t drvinfo = {NULL, NULL}; 80 81/* debugging macros */ 82#define SDLX_MSG(x) 83 84/** 85 * Checks to see if vendor and device IDs match a supported SDIO Host Controller. 86 */ 87bool 88bcmsdh_chipmatch(uint16 vendor, uint16 device) 89{ 90 /* Add other vendors and devices as required */ 91 92#ifdef BCMSDIOH_STD 93 /* Check for Arasan host controller */ 94 if (vendor == VENDOR_SI_IMAGE) { 95 return (TRUE); 96 } 97 /* Check for BRCM 27XX Standard host controller */ 98 if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM) { 99 return (TRUE); 100 } 101 /* Check for BRCM Standard host controller */ 102 if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM) { 103 return (TRUE); 104 } 105 /* Check for TI PCIxx21 Standard host controller */ 106 if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI) { 107 return (TRUE); 108 } 109 if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI) { 110 return (TRUE); 111 } 112 /* Ricoh R5C822 Standard SDIO Host */ 113 if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH) { 114 return (TRUE); 115 } 116 /* JMicron Standard SDIO Host */ 117 if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON) { 118 return (TRUE); 119 } 120 121#endif /* BCMSDIOH_STD */ 122#ifdef BCMSDIOH_SPI 123 /* This is the PciSpiHost. */ 124 if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) { 125 printf("Found PCI SPI Host Controller\n"); 126 return (TRUE); 127 } 128 129#endif /* BCMSDIOH_SPI */ 130 131 return (FALSE); 132} 133 134#if defined(BCMPLATFORM_BUS) 135#if defined(BCMLXSDMMC) 136/* forward declarations */ 137int bcmsdh_probe(struct device *dev); 138int bcmsdh_remove(struct device *dev); 139 140EXPORT_SYMBOL(bcmsdh_probe); 141EXPORT_SYMBOL(bcmsdh_remove); 142 143#else 144/* forward declarations */ 145static int __devinit bcmsdh_probe(struct device *dev); 146static int __devexit bcmsdh_remove(struct device *dev); 147#endif /* BCMLXSDMMC */ 148 149#ifndef BCMLXSDMMC 150static 151#endif /* BCMLXSDMMC */ 152int bcmsdh_probe(struct device *dev) 153{ 154 osl_t *osh = NULL; 155 bcmsdh_hc_t *sdhc = NULL; 156 ulong regs = 0; 157 bcmsdh_info_t *sdh = NULL; 158#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) 159 struct platform_device *pdev; 160 struct resource *r; 161#endif /* BCMLXSDMMC */ 162 int irq = 0; 163 uint32 vendevid; 164 unsigned long irq_flags = 0; 165 166#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) 167 pdev = to_platform_device(dev); 168 r = platform_get_resource(pdev, IORESOURCE_MEM, 0); 169 irq = platform_get_irq(pdev, 0); 170 if (!r || irq == NO_IRQ) 171 return -ENXIO; 172#endif /* BCMLXSDMMC */ 173 174#if defined(OOB_INTR_ONLY) 175#ifdef HW_OOB 176 irq_flags = 177 IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; 178#else 179 irq_flags = IRQF_TRIGGER_FALLING; 180#endif /* HW_OOB */ 181 182 /* Get customer specific OOB IRQ parametres: IRQ number as IRQ type */ 183 irq = dhd_customer_oob_irq_map(&irq_flags); 184 if (irq < 0) { 185 SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__)); 186 return 1; 187 } 188#endif /* defined(OOB_INTR_ONLY) */ 189 /* allocate SDIO Host Controller state info */ 190 if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) { 191 SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); 192 goto err; 193 } 194 if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) { 195 SDLX_MSG(("%s: out of memory, allocated %d bytes\n", 196 __FUNCTION__, 197 MALLOCED(osh))); 198 goto err; 199 } 200 bzero(sdhc, sizeof(bcmsdh_hc_t)); 201 sdhc->osh = osh; 202 203 sdhc->dev = (void *)dev; 204 205#ifdef BCMLXSDMMC 206 if (!(sdh = bcmsdh_attach(osh, (void *)0, 207 (void **)®s, irq))) { 208 SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); 209 goto err; 210 } 211#else 212 if (!(sdh = bcmsdh_attach(osh, (void *)r->start, 213 (void **)®s, irq))) { 214 SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); 215 goto err; 216 } 217#endif /* BCMLXSDMMC */ 218 sdhc->sdh = sdh; 219 sdhc->oob_irq = irq; 220 sdhc->oob_flags = irq_flags; 221 sdhc->oob_irq_registered = FALSE; /* to make sure.. */ 222 sdhc->oob_irq_enable_flag = FALSE; 223#if defined(OOB_INTR_ONLY) 224 spin_lock_init(&sdhc->irq_lock); 225#endif 226 227 /* chain SDIO Host Controller info together */ 228 sdhc->next = sdhcinfo; 229 sdhcinfo = sdhc; 230 231 /* Read the vendor/device ID from the CIS */ 232 vendevid = bcmsdh_query_device(sdh); 233 /* try to attach to the target device */ 234 if (!(sdhc->ch = drvinfo.attach((vendevid >> 16), 235 (vendevid & 0xFFFF), 0, 0, 0, 0, 236 (void *)regs, NULL, sdh))) { 237 SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); 238 goto err; 239 } 240 241 return 0; 242 243 /* error handling */ 244err: 245 if (sdhc) { 246 if (sdhc->sdh) 247 bcmsdh_detach(sdhc->osh, sdhc->sdh); 248 MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); 249 } 250 if (osh) 251 osl_detach(osh); 252 return -ENODEV; 253} 254 255#ifndef BCMLXSDMMC 256static 257#endif /* BCMLXSDMMC */ 258int bcmsdh_remove(struct device *dev) 259{ 260 bcmsdh_hc_t *sdhc, *prev; 261 osl_t *osh; 262 263 sdhc = sdhcinfo; 264 drvinfo.detach(sdhc->ch); 265 bcmsdh_detach(sdhc->osh, sdhc->sdh); 266 267 /* find the SDIO Host Controller state for this pdev and take it out from the list */ 268 for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { 269 if (sdhc->dev == (void *)dev) { 270 if (prev) 271 prev->next = sdhc->next; 272 else 273 sdhcinfo = NULL; 274 break; 275 } 276 prev = sdhc; 277 } 278 if (!sdhc) { 279 SDLX_MSG(("%s: failed\n", __FUNCTION__)); 280 return 0; 281 } 282 283 /* release SDIO Host Controller info */ 284 osh = sdhc->osh; 285 MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); 286 osl_detach(osh); 287 288#if !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY) 289 dev_set_drvdata(dev, NULL); 290#endif /* !defined(BCMLXSDMMC) || defined(OOB_INTR_ONLY) */ 291 292 return 0; 293} 294 295#else /* BCMPLATFORM_BUS */ 296 297#if !defined(BCMLXSDMMC) 298/* forward declarations for PCI probe and remove functions. */ 299static int __devinit bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); 300static void __devexit bcmsdh_pci_remove(struct pci_dev *pdev); 301 302/** 303 * pci id table 304 */ 305static struct pci_device_id bcmsdh_pci_devid[] __devinitdata = { 306 { vendor: PCI_ANY_ID, 307 device: PCI_ANY_ID, 308 subvendor: PCI_ANY_ID, 309 subdevice: PCI_ANY_ID, 310 class: 0, 311 class_mask: 0, 312 driver_data: 0, 313 }, 314 { 0, } 315}; 316MODULE_DEVICE_TABLE(pci, bcmsdh_pci_devid); 317 318/** 319 * SDIO Host Controller pci driver info 320 */ 321static struct pci_driver bcmsdh_pci_driver = { 322 node: {}, 323 name: "bcmsdh", 324 id_table: bcmsdh_pci_devid, 325 probe: bcmsdh_pci_probe, 326 remove: bcmsdh_pci_remove, 327#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) 328 save_state: NULL, 329#endif 330 suspend: NULL, 331 resume: NULL, 332 }; 333 334 335extern uint sd_pci_slot; /* Force detection to a particular PCI */ 336 /* slot only . Allows for having multiple */ 337 /* WL devices at once in a PC */ 338 /* Only one instance of dhd will be */ 339 /* usable at a time */ 340 /* Upper word is bus number, */ 341 /* lower word is slot number */ 342 /* Default value of 0xffffffff turns this */ 343 /* off */ 344module_param(sd_pci_slot, uint, 0); 345 346 347/** 348 * Detect supported SDIO Host Controller and attach if found. 349 * 350 * Determine if the device described by pdev is a supported SDIO Host 351 * Controller. If so, attach to it and attach to the target device. 352 */ 353static int __devinit 354bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) 355{ 356 osl_t *osh = NULL; 357 bcmsdh_hc_t *sdhc = NULL; 358 ulong regs; 359 bcmsdh_info_t *sdh = NULL; 360 int rc; 361 362 if (sd_pci_slot != 0xFFFFffff) { 363 if (pdev->bus->number != (sd_pci_slot>>16) || 364 PCI_SLOT(pdev->devfn) != (sd_pci_slot&0xffff)) { 365 SDLX_MSG(("%s: %s: bus %X, slot %X, vend %X, dev %X\n", 366 __FUNCTION__, 367 bcmsdh_chipmatch(pdev->vendor, pdev->device) 368 ?"Found compatible SDIOHC" 369 :"Probing unknown device", 370 pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, 371 pdev->device)); 372 return -ENODEV; 373 } 374 SDLX_MSG(("%s: %s: bus %X, slot %X, vendor %X, device %X (good PCI location)\n", 375 __FUNCTION__, 376 bcmsdh_chipmatch(pdev->vendor, pdev->device) 377 ?"Using compatible SDIOHC" 378 :"WARNING, forced use of unkown device", 379 pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device)); 380 } 381 382 if ((pdev->vendor == VENDOR_TI) && ((pdev->device == PCIXX21_FLASHMEDIA_ID) || 383 (pdev->device == PCIXX21_FLASHMEDIA0_ID))) { 384 uint32 config_reg; 385 386 SDLX_MSG(("%s: Disabling TI FlashMedia Controller.\n", __FUNCTION__)); 387 if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) { 388 SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); 389 goto err; 390 } 391 392 config_reg = OSL_PCI_READ_CONFIG(osh, 0x4c, 4); 393 394 /* 395 * Set MMC_SD_DIS bit in FlashMedia Controller. 396 * Disbling the SD/MMC Controller in the FlashMedia Controller 397 * allows the Standard SD Host Controller to take over control 398 * of the SD Slot. 399 */ 400 config_reg |= 0x02; 401 OSL_PCI_WRITE_CONFIG(osh, 0x4c, 4, config_reg); 402 osl_detach(osh); 403 } 404 /* match this pci device with what we support */ 405 /* we can't solely rely on this to believe it is our SDIO Host Controller! */ 406 if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) { 407 return -ENODEV; 408 } 409 410 /* this is a pci device we might support */ 411 SDLX_MSG(("%s: Found possible SDIO Host Controller: bus %d slot %d func %d irq %d\n", 412 __FUNCTION__, 413 pdev->bus->number, PCI_SLOT(pdev->devfn), 414 PCI_FUNC(pdev->devfn), pdev->irq)); 415 416 /* use bcmsdh_query_device() to get the vendor ID of the target device so 417 * it will eventually appear in the Broadcom string on the console 418 */ 419 420 /* allocate SDIO Host Controller state info */ 421 if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) { 422 SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); 423 goto err; 424 } 425 if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) { 426 SDLX_MSG(("%s: out of memory, allocated %d bytes\n", 427 __FUNCTION__, 428 MALLOCED(osh))); 429 goto err; 430 } 431 bzero(sdhc, sizeof(bcmsdh_hc_t)); 432 sdhc->osh = osh; 433 434 sdhc->dev = pdev; 435 436 /* map to address where host can access */ 437 pci_set_master(pdev); 438 rc = pci_enable_device(pdev); 439 if (rc) { 440 SDLX_MSG(("%s: Cannot enable PCI device\n", __FUNCTION__)); 441 goto err; 442 } 443 if (!(sdh = bcmsdh_attach(osh, (void *)(uintptr)pci_resource_start(pdev, 0), 444 (void **)®s, pdev->irq))) { 445 SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); 446 goto err; 447 } 448 449 sdhc->sdh = sdh; 450 451 /* try to attach to the target device */ 452 if (!(sdhc->ch = drvinfo.attach(VENDOR_BROADCOM, /* pdev->vendor, */ 453 bcmsdh_query_device(sdh) & 0xFFFF, 0, 0, 0, 0, 454 (void *)regs, NULL, sdh))) { 455 SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); 456 goto err; 457 } 458 459 /* chain SDIO Host Controller info together */ 460 sdhc->next = sdhcinfo; 461 sdhcinfo = sdhc; 462 463 return 0; 464 465 /* error handling */ 466err: 467 if (sdhc) { 468 if (sdhc->sdh) 469 bcmsdh_detach(sdhc->osh, sdhc->sdh); 470 MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); 471 } 472 if (osh) 473 osl_detach(osh); 474 return -ENODEV; 475} 476 477 478/** 479 * Detach from target devices and SDIO Host Controller 480 */ 481static void __devexit 482bcmsdh_pci_remove(struct pci_dev *pdev) 483{ 484 bcmsdh_hc_t *sdhc, *prev; 485 osl_t *osh; 486 487 /* find the SDIO Host Controller state for this pdev and take it out from the list */ 488 for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { 489 if (sdhc->dev == pdev) { 490 if (prev) 491 prev->next = sdhc->next; 492 else 493 sdhcinfo = NULL; 494 break; 495 } 496 prev = sdhc; 497 } 498 if (!sdhc) 499 return; 500 501 drvinfo.detach(sdhc->ch); 502 503 bcmsdh_detach(sdhc->osh, sdhc->sdh); 504 505 /* release SDIO Host Controller info */ 506 osh = sdhc->osh; 507 MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); 508 osl_detach(osh); 509} 510#endif /* BCMLXSDMMC */ 511#endif /* BCMPLATFORM_BUS */ 512 513extern int sdio_function_init(void); 514 515extern int sdio_func_reg_notify(void* semaphore); 516extern void sdio_func_unreg_notify(void); 517 518int bcmsdh_reg_sdio_notify(void* semaphore) 519{ 520 int ret = -1; 521 522#ifdef BCMLXSDMMC 523 ret = sdio_func_reg_notify(semaphore); 524#endif 525 526 return ret; 527} 528 529void bcmsdh_unreg_sdio_notify(void) 530{ 531#ifdef BCMLXSDMMC 532 sdio_func_unreg_notify(); 533#endif 534 535} 536 537int 538bcmsdh_register(bcmsdh_driver_t *driver) 539{ 540 int error = 0; 541 542 drvinfo = *driver; 543 544#if defined(BCMPLATFORM_BUS) 545 SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); 546 error = sdio_function_init(); 547 return error; 548#endif /* defined(BCMPLATFORM_BUS) */ 549 550#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) 551#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) 552 if (!(error = pci_module_init(&bcmsdh_pci_driver))) 553 return 0; 554#else 555 if (!(error = pci_register_driver(&bcmsdh_pci_driver))) 556 return 0; 557#endif 558 559 SDLX_MSG(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error)); 560#endif /* BCMPLATFORM_BUS */ 561 562 return error; 563} 564 565extern void sdio_function_cleanup(void); 566 567void 568bcmsdh_unregister(void) 569{ 570#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) 571 if (bcmsdh_pci_driver.node.next) 572#endif 573 574#if defined(BCMLXSDMMC) 575 sdio_function_cleanup(); 576#endif /* BCMLXSDMMC */ 577 578#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) 579 pci_unregister_driver(&bcmsdh_pci_driver); 580#endif /* BCMPLATFORM_BUS */ 581} 582 583#if defined(OOB_INTR_ONLY) 584void bcmsdh_oob_intr_set(bool enable) 585{ 586 static bool curstate = 1; 587 unsigned long flags; 588 589 spin_lock_irqsave(&sdhcinfo->irq_lock, flags); 590 if (curstate != enable) { 591 if (enable) 592 enable_irq(sdhcinfo->oob_irq); 593 else 594 disable_irq_nosync(sdhcinfo->oob_irq); 595 curstate = enable; 596 } 597 spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags); 598} 599 600static irqreturn_t wlan_oob_irq(int irq, void *dev_id) 601{ 602 dhd_pub_t *dhdp; 603 604 dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev); 605 606 bcmsdh_oob_intr_set(0); 607 608 if (dhdp == NULL) { 609 SDLX_MSG(("Out of band GPIO interrupt fired way too early\n")); 610 return IRQ_HANDLED; 611 } 612 613 dhdsdio_isr((void *)dhdp->bus); 614 615 return IRQ_HANDLED; 616} 617 618int bcmsdh_register_oob_intr(void * dhdp) 619{ 620 int error = 0; 621 622 SDLX_MSG(("%s Enter \n", __FUNCTION__)); 623 624 /* IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE; */ 625 626 dev_set_drvdata(sdhcinfo->dev, dhdp); 627 628 if (!sdhcinfo->oob_irq_registered) { 629 SDLX_MSG(("%s IRQ=%d Type=%X \n", __FUNCTION__, 630 (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags)); 631 /* Refer to customer Host IRQ docs about proper irqflags definition */ 632 error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, sdhcinfo->oob_flags, 633 "bcmsdh_sdmmc", NULL); 634 if (error) 635 return -ENODEV; 636 637 enable_irq_wake(sdhcinfo->oob_irq); 638 sdhcinfo->oob_irq_registered = TRUE; 639 sdhcinfo->oob_irq_enable_flag = TRUE; 640 } 641 642 return 0; 643} 644 645void *bcmsdh_get_drvdata(void) 646{ 647 if (!sdhcinfo) 648 return NULL; 649 return dev_get_drvdata(sdhcinfo->dev); 650} 651void bcmsdh_set_irq(int flag) 652{ 653 if (sdhcinfo->oob_irq_registered && sdhcinfo->oob_irq_enable_flag != flag) { 654 SDLX_MSG(("%s Flag = %d", __FUNCTION__, flag)); 655 sdhcinfo->oob_irq_enable_flag = flag; 656 if (flag) { 657 enable_irq(sdhcinfo->oob_irq); 658 enable_irq_wake(sdhcinfo->oob_irq); 659 } else { 660 disable_irq_wake(sdhcinfo->oob_irq); 661 disable_irq(sdhcinfo->oob_irq); 662 } 663 } 664} 665 666void bcmsdh_unregister_oob_intr(void) 667{ 668 SDLX_MSG(("%s: Enter\n", __FUNCTION__)); 669 670 if (sdhcinfo->oob_irq_registered == TRUE) { 671 bcmsdh_set_irq(FALSE); 672 free_irq(sdhcinfo->oob_irq, NULL); 673 sdhcinfo->oob_irq_registered = FALSE; 674 } 675} 676#endif /* defined(OOB_INTR_ONLY) */ 677 678/* Module parameters specific to each host-controller driver */ 679 680extern uint sd_msglevel; /* Debug message level */ 681module_param(sd_msglevel, uint, 0); 682 683extern uint sd_power; /* 0 = SD Power OFF, 1 = SD Power ON. */ 684module_param(sd_power, uint, 0); 685 686extern uint sd_clock; /* SD Clock Control, 0 = SD Clock OFF, 1 = SD Clock ON */ 687module_param(sd_clock, uint, 0); 688 689extern uint sd_divisor; /* Divisor (-1 means external clock) */ 690module_param(sd_divisor, uint, 0); 691 692extern uint sd_sdmode; /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */ 693module_param(sd_sdmode, uint, 0); 694 695extern uint sd_hiok; /* Ok to use hi-speed mode */ 696module_param(sd_hiok, uint, 0); 697 698extern uint sd_f2_blocksize; 699module_param(sd_f2_blocksize, int, 0); 700 701#ifdef BCMSDIOH_STD 702extern int sd_uhsimode; 703module_param(sd_uhsimode, int, 0); 704#endif 705 706#ifdef BCMSDH_MODULE 707EXPORT_SYMBOL(bcmsdh_attach); 708EXPORT_SYMBOL(bcmsdh_detach); 709EXPORT_SYMBOL(bcmsdh_intr_query); 710EXPORT_SYMBOL(bcmsdh_intr_enable); 711EXPORT_SYMBOL(bcmsdh_intr_disable); 712EXPORT_SYMBOL(bcmsdh_intr_reg); 713EXPORT_SYMBOL(bcmsdh_intr_dereg); 714 715#if defined(DHD_DEBUG) 716EXPORT_SYMBOL(bcmsdh_intr_pending); 717#endif 718 719EXPORT_SYMBOL(bcmsdh_devremove_reg); 720EXPORT_SYMBOL(bcmsdh_cfg_read); 721EXPORT_SYMBOL(bcmsdh_cfg_write); 722EXPORT_SYMBOL(bcmsdh_cis_read); 723EXPORT_SYMBOL(bcmsdh_reg_read); 724EXPORT_SYMBOL(bcmsdh_reg_write); 725EXPORT_SYMBOL(bcmsdh_regfail); 726EXPORT_SYMBOL(bcmsdh_send_buf); 727EXPORT_SYMBOL(bcmsdh_recv_buf); 728 729EXPORT_SYMBOL(bcmsdh_rwdata); 730EXPORT_SYMBOL(bcmsdh_abort); 731EXPORT_SYMBOL(bcmsdh_query_device); 732EXPORT_SYMBOL(bcmsdh_query_iofnum); 733EXPORT_SYMBOL(bcmsdh_iovar_op); 734EXPORT_SYMBOL(bcmsdh_register); 735EXPORT_SYMBOL(bcmsdh_unregister); 736EXPORT_SYMBOL(bcmsdh_chipmatch); 737EXPORT_SYMBOL(bcmsdh_reset); 738EXPORT_SYMBOL(bcmsdh_waitlockfree); 739 740EXPORT_SYMBOL(bcmsdh_get_dstatus); 741EXPORT_SYMBOL(bcmsdh_cfg_read_word); 742EXPORT_SYMBOL(bcmsdh_cfg_write_word); 743EXPORT_SYMBOL(bcmsdh_cur_sbwad); 744EXPORT_SYMBOL(bcmsdh_chipinfo); 745 746#endif /* BCMSDH_MODULE */ 747