e7ad60d98affc01fbfe4fa20ff6214e9b3d04fee
[pandora-kernel.git] / drivers / staging / brcm80211 / brcmfmac / bcmsdh_linux.c
1 /*
2  * Copyright (c) 2010 Broadcom Corporation
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11  * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16
17 /**
18  * @file bcmsdh_linux.c
19  */
20
21 #define __UNDEF_NO_VERSION__
22
23 #include <typedefs.h>
24 #include <linuxver.h>
25
26 #include <linux/pci.h>
27 #include <linux/completion.h>
28
29 #include <osl.h>
30 #include <pcicfg.h>
31 #include <bcmdefs.h>
32 #include <bcmdevs.h>
33
34 #if defined(OOB_INTR_ONLY)
35 #include <linux/irq.h>
36 extern void dhdsdio_isr(void *args);
37 #include <bcmutils.h>
38 #include <dngl_stats.h>
39 #include <dhd.h>
40 #endif                          /* defined(OOB_INTR_ONLY) */
41 #if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270)
42 #if !defined(BCMPLATFORM_BUS)
43 #define BCMPLATFORM_BUS
44 #endif                          /* !defined(BCMPLATFORM_BUS) */
45
46 #include <linux/platform_device.h>
47 #endif                          /* CONFIG_MACH_SANDGATE2G */
48
49 /**
50  * SDIO Host Controller info
51  */
52 typedef struct bcmsdh_hc bcmsdh_hc_t;
53
54 struct bcmsdh_hc {
55         bcmsdh_hc_t *next;
56 #ifdef BCMPLATFORM_BUS
57         struct device *dev;     /* platform device handle */
58 #else
59         struct pci_dev *dev;    /* pci device handle */
60 #endif                          /* BCMPLATFORM_BUS */
61         osl_t *osh;
62         void *regs;             /* SDIO Host Controller address */
63         bcmsdh_info_t *sdh;     /* SDIO Host Controller handle */
64         void *ch;
65         unsigned int oob_irq;
66         unsigned long oob_flags;        /* OOB Host specifiction
67                                         as edge and etc */
68         bool oob_irq_registered;
69 #if defined(OOB_INTR_ONLY)
70         spinlock_t irq_lock;
71 #endif
72 };
73 static bcmsdh_hc_t *sdhcinfo;
74
75 /* driver info, initialized when bcmsdh_register is called */
76 static bcmsdh_driver_t drvinfo = { NULL, NULL };
77
78 /* debugging macros */
79 #define SDLX_MSG(x)
80
81 /**
82  * Checks to see if vendor and device IDs match a supported SDIO Host Controller.
83  */
84 bool bcmsdh_chipmatch(u16 vendor, u16 device)
85 {
86         /* Add other vendors and devices as required */
87
88 #ifdef BCMSDIOH_STD
89         /* Check for Arasan host controller */
90         if (vendor == VENDOR_SI_IMAGE)
91                 return true;
92
93         /* Check for BRCM 27XX Standard host controller */
94         if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM)
95                 return true;
96
97         /* Check for BRCM Standard host controller */
98         if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM)
99                 return true;
100
101         /* Check for TI PCIxx21 Standard host controller */
102         if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI)
103                 return true;
104
105         if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI)
106                 return true;
107
108         /* Ricoh R5C822 Standard SDIO Host */
109         if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH)
110                 return true;
111
112         /* JMicron Standard SDIO Host */
113         if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON)
114                 return true;
115 #endif                          /* BCMSDIOH_STD */
116 #ifdef BCMSDIOH_SPI
117         /* This is the PciSpiHost. */
118         if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) {
119                 printf("Found PCI SPI Host Controller\n");
120                 return true;
121         }
122 #endif                          /* BCMSDIOH_SPI */
123
124         return false;
125 }
126
127 #if defined(BCMPLATFORM_BUS)
128 #if defined(BCMLXSDMMC)
129 /* forward declarations */
130 int bcmsdh_probe(struct device *dev);
131 EXPORT_SYMBOL(bcmsdh_probe);
132
133 int bcmsdh_remove(struct device *dev);
134 EXPORT_SYMBOL(bcmsdh_remove);
135
136 #else
137 /* forward declarations */
138 static int __devinit bcmsdh_probe(struct device *dev);
139 static int __devexit bcmsdh_remove(struct device *dev);
140 #endif                          /* BCMLXSDMMC */
141
142 #ifndef BCMLXSDMMC
143 static struct device_driver bcmsdh_driver = {
144         .name = "pxa2xx-mci",
145         .bus = &platform_bus_type,
146         .probe = bcmsdh_probe,
147         .remove = bcmsdh_remove,
148         .suspend = NULL,
149         .resume = NULL,
150 };
151 #endif                          /* BCMLXSDMMC */
152
153 #ifndef BCMLXSDMMC
154 static
155 #endif                          /* BCMLXSDMMC */
156 int bcmsdh_probe(struct device *dev)
157 {
158         osl_t *osh = NULL;
159         bcmsdh_hc_t *sdhc = NULL;
160         unsigned long regs = 0;
161         bcmsdh_info_t *sdh = NULL;
162 #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
163         struct platform_device *pdev;
164         struct resource *r;
165 #endif                          /* BCMLXSDMMC */
166         int irq = 0;
167         u32 vendevid;
168         unsigned long irq_flags = 0;
169
170 #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS)
171         pdev = to_platform_device(dev);
172         r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
173         irq = platform_get_irq(pdev, 0);
174         if (!r || irq == NO_IRQ)
175                 return -ENXIO;
176 #endif                          /* BCMLXSDMMC */
177
178 #if defined(OOB_INTR_ONLY)
179 #ifdef HW_OOB
180         irq_flags =
181             IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
182             IORESOURCE_IRQ_SHAREABLE;
183 #else
184         irq_flags = IRQF_TRIGGER_FALLING;
185 #endif                          /* HW_OOB */
186         irq = dhd_customer_oob_irq_map(&irq_flags);
187         if (irq < 0) {
188                 SDLX_MSG(("%s: Host irq is not defined\n", __func__));
189                 return 1;
190         }
191 #endif                          /* defined(OOB_INTR_ONLY) */
192         /* allocate SDIO Host Controller state info */
193         osh = osl_attach(dev, PCI_BUS, false);
194         if (!osh) {
195                 SDLX_MSG(("%s: osl_attach failed\n", __func__));
196                 goto err;
197         }
198         sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
199         if (!sdhc) {
200                 SDLX_MSG(("%s: out of memory\n", __func__));
201                 goto err;
202         }
203         sdhc->osh = osh;
204
205         sdhc->dev = (void *)dev;
206
207 #ifdef BCMLXSDMMC
208         sdh = bcmsdh_attach(osh, (void *)0, (void **)&regs, irq);
209         if (!sdh) {
210                 SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
211                 goto err;
212         }
213 #else
214         sdh = bcmsdh_attach(osh, (void *)r->start, (void **)&regs, irq);
215         if (!sdh) {
216                 SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
217                 goto err;
218         }
219 #endif                          /* BCMLXSDMMC */
220         sdhc->sdh = sdh;
221         sdhc->oob_irq = irq;
222         sdhc->oob_flags = irq_flags;
223         sdhc->oob_irq_registered = false;       /* to make sure.. */
224 #if defined(OOB_INTR_ONLY)
225         spin_lock_init(&sdhc->irq_lock);
226 #endif
227
228         /* chain SDIO Host Controller info together */
229         sdhc->next = sdhcinfo;
230         sdhcinfo = sdhc;
231         /* Read the vendor/device ID from the CIS */
232         vendevid = bcmsdh_query_device(sdh);
233
234         /* try to attach to the target device */
235         sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
236                                 0, 0, 0, 0, (void *)regs, NULL, sdh);
237         if (!sdhc->ch) {
238                 SDLX_MSG(("%s: device attach failed\n", __func__));
239                 goto err;
240         }
241
242         return 0;
243
244         /* error handling */
245 err:
246         if (sdhc) {
247                 if (sdhc->sdh)
248                         bcmsdh_detach(sdhc->osh, sdhc->sdh);
249                 kfree(sdhc);
250         }
251         if (osh)
252                 osl_detach(osh);
253         return -ENODEV;
254 }
255
256 #ifndef BCMLXSDMMC
257 static
258 #endif                          /* BCMLXSDMMC */
259 int bcmsdh_remove(struct device *dev)
260 {
261         bcmsdh_hc_t *sdhc, *prev;
262         osl_t *osh;
263
264         sdhc = sdhcinfo;
265         drvinfo.detach(sdhc->ch);
266         bcmsdh_detach(sdhc->osh, sdhc->sdh);
267         /* find the SDIO Host Controller state for this pdev
268                  and take it out from the list */
269         for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
270                 if (sdhc->dev == (void *)dev) {
271                         if (prev)
272                                 prev->next = sdhc->next;
273                         else
274                                 sdhcinfo = NULL;
275                         break;
276                 }
277                 prev = sdhc;
278         }
279         if (!sdhc) {
280                 SDLX_MSG(("%s: failed\n", __func__));
281                 return 0;
282         }
283
284         /* release SDIO Host Controller info */
285         osh = sdhc->osh;
286         kfree(sdhc);
287         osl_detach(osh);
288
289 #if !defined(BCMLXSDMMC)
290         dev_set_drvdata(dev, NULL);
291 #endif                          /* !defined(BCMLXSDMMC) */
292
293         return 0;
294 }
295
296 #else                           /* BCMPLATFORM_BUS */
297
298 #if !defined(BCMLXSDMMC)
299 /* forward declarations for PCI probe and remove functions. */
300 static int __devinit bcmsdh_pci_probe(struct pci_dev *pdev,
301                                       const struct pci_device_id *ent);
302 static void __devexit bcmsdh_pci_remove(struct pci_dev *pdev);
303
304 /**
305  * pci id table
306  */
307 static struct pci_device_id bcmsdh_pci_devid[] __devinitdata = {
308 {
309         .vendor = PCI_ANY_ID,
310         .device = PCI_ANY_ID,
311         .subvendor = PCI_ANY_ID,
312         .subdevice = PCI_ANY_ID,
313         .class = 0,
314         .class_mask = 0,
315         .driver_data = 0,
316 },
317 {0,}
318 };
319
320 MODULE_DEVICE_TABLE(pci, bcmsdh_pci_devid);
321
322 /**
323  * SDIO Host Controller pci driver info
324  */
325 static struct pci_driver bcmsdh_pci_driver = {
326         .node = {},
327         .name = "bcmsdh",
328         .id_table = bcmsdh_pci_devid,
329         .probe = bcmsdh_pci_probe,
330         .remove = bcmsdh_pci_remove,
331         .suspend = NULL,
332         .resume = NULL,
333 };
334
335 extern 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 */
344 module_param(sd_pci_slot, uint, 0);
345
346 /**
347  * Detect supported SDIO Host Controller and attach if found.
348  *
349  * Determine if the device described by pdev is a supported SDIO Host
350  * Controller.  If so, attach to it and attach to the target device.
351  */
352 static int __devinit
353 bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
354 {
355         osl_t *osh = NULL;
356         bcmsdh_hc_t *sdhc = NULL;
357         unsigned long regs;
358         bcmsdh_info_t *sdh = NULL;
359         int rc;
360
361         if (sd_pci_slot != 0xFFFFffff) {
362                 if (pdev->bus->number != (sd_pci_slot >> 16) ||
363                     PCI_SLOT(pdev->devfn) != (sd_pci_slot & 0xffff)) {
364                         SDLX_MSG(("%s: %s: bus %X, slot %X, vend %X, dev %X\n",
365                                   __func__,
366                                   bcmsdh_chipmatch(pdev->vendor, pdev->device) ?
367                                   "Found compatible SDIOHC" :
368                                   "Probing unknown device",
369                                   pdev->bus->number, PCI_SLOT(pdev->devfn),
370                                   pdev->vendor, pdev->device));
371                         return -ENODEV;
372                 }
373                 SDLX_MSG(("%s: %s: bus %X, slot %X, vendor %X, device %X "
374                         "(good PCI location)\n", __func__,
375                         bcmsdh_chipmatch(pdev->vendor, pdev->device) ?
376                         "Using compatible SDIOHC" : "WARNING, forced use "
377                         "of unkown device",
378                 pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor,
379                 pdev->device));
380         }
381
382         if ((pdev->vendor == VENDOR_TI)
383             && ((pdev->device == PCIXX21_FLASHMEDIA_ID)
384                 || (pdev->device == PCIXX21_FLASHMEDIA0_ID))) {
385                 u32 config_reg;
386
387                 SDLX_MSG(("%s: Disabling TI FlashMedia Controller.\n",
388                           __func__));
389                 osh = osl_attach(pdev, PCI_BUS, false);
390                 if (!osh) {
391                         SDLX_MSG(("%s: osl_attach failed\n", __func__));
392                         goto err;
393                 }
394
395                 config_reg = OSL_PCI_READ_CONFIG(osh, 0x4c, 4);
396
397                 /*
398                  * Set MMC_SD_DIS bit in FlashMedia Controller.
399                  * Disbling the SD/MMC Controller in the FlashMedia Controller
400                  * allows the Standard SD Host Controller to take over control
401                  * of the SD Slot.
402                  */
403                 config_reg |= 0x02;
404                 OSL_PCI_WRITE_CONFIG(osh, 0x4c, 4, config_reg);
405                 osl_detach(osh);
406         }
407         /* match this pci device with what we support */
408         /* we can't solely rely on this to believe it is
409                 our SDIO Host Controller! */
410         if (!bcmsdh_chipmatch(pdev->vendor, pdev->device))
411                 return -ENODEV;
412
413         /* this is a pci device we might support */
414         SDLX_MSG(("%s: Found possible SDIO Host Controller: "
415                 "bus %d slot %d func %d irq %d\n", __func__,
416                 pdev->bus->number, PCI_SLOT(pdev->devfn),
417                 PCI_FUNC(pdev->devfn), pdev->irq));
418
419         /* use bcmsdh_query_device() to get the vendor ID of the target device
420          * so it will eventually appear in the Broadcom string on the console
421          */
422
423         /* allocate SDIO Host Controller state info */
424         osh = osl_attach(pdev, PCI_BUS, false);
425         if (!osh) {
426                 SDLX_MSG(("%s: osl_attach failed\n", __func__));
427                 goto err;
428         }
429         sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
430         if (!sdhc) {
431                 SDLX_MSG(("%s: out of memory\n", __func__));
432                 goto err;
433         }
434         sdhc->osh = osh;
435
436         sdhc->dev = pdev;
437
438         /* map to address where host can access */
439         pci_set_master(pdev);
440         rc = pci_enable_device(pdev);
441         if (rc) {
442                 SDLX_MSG(("%s: Cannot enable PCI device\n", __func__));
443                 goto err;
444         }
445         sdh = bcmsdh_attach(osh, (void *)(unsigned long)pci_resource_start(pdev, 0),
446                         (void **)&regs, pdev->irq);
447         if (!sdh) {
448                 SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
449                 goto err;
450         }
451
452         sdhc->sdh = sdh;
453
454         /* try to attach to the target device */
455         sdhc->ch = drvinfo.attach(VENDOR_BROADCOM, /* pdev->vendor, */
456                                 bcmsdh_query_device(sdh) & 0xFFFF, 0, 0, 0, 0,
457                                 (void *)regs, NULL, sdh);
458         if (!sdhc->ch) {
459                 SDLX_MSG(("%s: device attach failed\n", __func__));
460                 goto err;
461         }
462
463         /* chain SDIO Host Controller info together */
464         sdhc->next = sdhcinfo;
465         sdhcinfo = sdhc;
466
467         return 0;
468
469         /* error handling */
470 err:
471         if (sdhc->sdh)
472                 bcmsdh_detach(sdhc->osh, sdhc->sdh);
473         if (sdhc)
474                 kfree(sdhc);
475         if (osh)
476                 osl_detach(osh);
477         return -ENODEV;
478 }
479
480 /**
481  * Detach from target devices and SDIO Host Controller
482  */
483 static void __devexit bcmsdh_pci_remove(struct pci_dev *pdev)
484 {
485         bcmsdh_hc_t *sdhc, *prev;
486         osl_t *osh;
487
488         /* find the SDIO Host Controller state for this
489                  pdev and take it out from the list */
490         for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
491                 if (sdhc->dev == pdev) {
492                         if (prev)
493                                 prev->next = sdhc->next;
494                         else
495                                 sdhcinfo = NULL;
496                         break;
497                 }
498                 prev = sdhc;
499         }
500         if (!sdhc)
501                 return;
502
503         drvinfo.detach(sdhc->ch);
504
505         bcmsdh_detach(sdhc->osh, sdhc->sdh);
506
507         /* release SDIO Host Controller info */
508         osh = sdhc->osh;
509         kfree(sdhc);
510         osl_detach(osh);
511 }
512 #endif                          /* BCMLXSDMMC */
513 #endif                          /* BCMPLATFORM_BUS */
514
515 extern int sdio_function_init(void);
516
517 int bcmsdh_register(bcmsdh_driver_t *driver)
518 {
519         int error = 0;
520
521         drvinfo = *driver;
522
523 #if defined(BCMPLATFORM_BUS)
524 #if defined(BCMLXSDMMC)
525         SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n"));
526         error = sdio_function_init();
527 #else
528         SDLX_MSG(("Intel PXA270 SDIO Driver\n"));
529         error = driver_register(&bcmsdh_driver);
530 #endif                          /* defined(BCMLXSDMMC) */
531         return error;
532 #endif                          /* defined(BCMPLATFORM_BUS) */
533
534 #if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
535         error = pci_register_driver(&bcmsdh_pci_driver);
536         if (!error)
537                 return 0;
538
539         SDLX_MSG(("%s: pci_register_driver failed 0x%x\n", __func__, error));
540 #endif                          /* BCMPLATFORM_BUS */
541
542         return error;
543 }
544
545 extern void sdio_function_cleanup(void);
546
547 void bcmsdh_unregister(void)
548 {
549 #if defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
550                 driver_unregister(&bcmsdh_driver);
551 #endif
552 #if defined(BCMLXSDMMC)
553         sdio_function_cleanup();
554 #endif                          /* BCMLXSDMMC */
555 #if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC)
556         pci_unregister_driver(&bcmsdh_pci_driver);
557 #endif                          /* BCMPLATFORM_BUS */
558 }
559
560 #if defined(OOB_INTR_ONLY)
561 void bcmsdh_oob_intr_set(bool enable)
562 {
563         static bool curstate = 1;
564         unsigned long flags;
565
566         spin_lock_irqsave(&sdhcinfo->irq_lock, flags);
567         if (curstate != enable) {
568                 if (enable)
569                         enable_irq(sdhcinfo->oob_irq);
570                 else
571                         disable_irq_nosync(sdhcinfo->oob_irq);
572                 curstate = enable;
573         }
574         spin_unlock_irqrestore(&sdhcinfo->irq_lock, flags);
575 }
576
577 static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
578 {
579         dhd_pub_t *dhdp;
580
581         dhdp = (dhd_pub_t *) dev_get_drvdata(sdhcinfo->dev);
582
583         bcmsdh_oob_intr_set(0);
584
585         if (dhdp == NULL) {
586                 SDLX_MSG(("Out of band GPIO interrupt fired way too early\n"));
587                 return IRQ_HANDLED;
588         }
589
590         WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
591
592         dhdsdio_isr((void *)dhdp->bus);
593
594         return IRQ_HANDLED;
595 }
596
597 int bcmsdh_register_oob_intr(void *dhdp)
598 {
599         int error = 0;
600
601         SDLX_MSG(("%s Enter\n", __func__));
602
603         sdhcinfo->oob_flags =
604             IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL |
605             IORESOURCE_IRQ_SHAREABLE;
606         dev_set_drvdata(sdhcinfo->dev, dhdp);
607
608         if (!sdhcinfo->oob_irq_registered) {
609                 SDLX_MSG(("%s IRQ=%d Type=%X\n", __func__,
610                           (int)sdhcinfo->oob_irq, (int)sdhcinfo->oob_flags));
611                 /* Refer to customer Host IRQ docs about
612                          proper irqflags definition */
613                 error =
614                     request_irq(sdhcinfo->oob_irq, wlan_oob_irq,
615                                 sdhcinfo->oob_flags, "bcmsdh_sdmmc", NULL);
616                 if (error)
617                         return -ENODEV;
618
619                 set_irq_wake(sdhcinfo->oob_irq, 1);
620                 sdhcinfo->oob_irq_registered = true;
621         }
622
623         return 0;
624 }
625
626 void bcmsdh_unregister_oob_intr(void)
627 {
628         SDLX_MSG(("%s: Enter\n", __func__));
629
630         set_irq_wake(sdhcinfo->oob_irq, 0);
631         disable_irq(sdhcinfo->oob_irq); /* just in case.. */
632         free_irq(sdhcinfo->oob_irq, NULL);
633         sdhcinfo->oob_irq_registered = false;
634 }
635 #endif                          /* defined(OOB_INTR_ONLY) */
636 /* Module parameters specific to each host-controller driver */
637
638 extern uint sd_msglevel;        /* Debug message level */
639 module_param(sd_msglevel, uint, 0);
640
641 extern uint sd_power;           /* 0 = SD Power OFF,
642                                          1 = SD Power ON. */
643 module_param(sd_power, uint, 0);
644
645 extern uint sd_clock;           /* SD Clock Control, 0 = SD Clock OFF,
646                                  1 = SD Clock ON */
647 module_param(sd_clock, uint, 0);
648
649 extern uint sd_divisor;         /* Divisor (-1 means external clock) */
650 module_param(sd_divisor, uint, 0);
651
652 extern uint sd_sdmode;          /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */
653 module_param(sd_sdmode, uint, 0);
654
655 extern uint sd_hiok;            /* Ok to use hi-speed mode */
656 module_param(sd_hiok, uint, 0);
657
658 extern uint sd_f2_blocksize;
659 module_param(sd_f2_blocksize, int, 0);