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