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