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