Showing error 1738

User: Jiri Slaby
Error type: Invalid Pointer Dereference
Error type description: A pointer which is invalid is being dereferenced
File location: drivers/mmc/host/sdhci-pci.c
Line in file: 571
Project: Linux Kernel
Project version: 2.6.28
Confirmation: Fixed by c60a32cd129b1c41f98888b03ba2904406bac8f8
Tools: Smatch (1.59)
Entered: 2013-09-10 20:24:52 UTC


Source:

  1/*  linux/drivers/mmc/host/sdhci-pci.c - SDHCI on PCI bus interface
  2 *
  3 *  Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved.
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License as published by
  7 * the Free Software Foundation; either version 2 of the License, or (at
  8 * your option) any later version.
  9 *
 10 * Thanks to the following companies for their support:
 11 *
 12 *     - JMicron (hardware and technical support)
 13 */
 14
 15#include <linux/delay.h>
 16#include <linux/highmem.h>
 17#include <linux/pci.h>
 18#include <linux/dma-mapping.h>
 19
 20#include <linux/mmc/host.h>
 21
 22#include <asm/scatterlist.h>
 23#include <asm/io.h>
 24
 25#include "sdhci.h"
 26
 27/*
 28 * PCI registers
 29 */
 30
 31#define PCI_SDHCI_IFPIO                        0x00
 32#define PCI_SDHCI_IFDMA                        0x01
 33#define PCI_SDHCI_IFVENDOR                0x02
 34
 35#define PCI_SLOT_INFO                        0x40        /* 8 bits */
 36#define  PCI_SLOT_INFO_SLOTS(x)                ((x >> 4) & 7)
 37#define  PCI_SLOT_INFO_FIRST_BAR_MASK        0x07
 38
 39#define MAX_SLOTS                        8
 40
 41struct sdhci_pci_chip;
 42struct sdhci_pci_slot;
 43
 44struct sdhci_pci_fixes {
 45        unsigned int                quirks;
 46
 47        int                        (*probe)(struct sdhci_pci_chip*);
 48
 49        int                        (*probe_slot)(struct sdhci_pci_slot*);
 50        void                        (*remove_slot)(struct sdhci_pci_slot*, int);
 51
 52        int                        (*suspend)(struct sdhci_pci_chip*,
 53                                        pm_message_t);
 54        int                        (*resume)(struct sdhci_pci_chip*);
 55};
 56
 57struct sdhci_pci_slot {
 58        struct sdhci_pci_chip        *chip;
 59        struct sdhci_host        *host;
 60
 61        int                        pci_bar;
 62};
 63
 64struct sdhci_pci_chip {
 65        struct pci_dev                *pdev;
 66
 67        unsigned int                quirks;
 68        const struct sdhci_pci_fixes *fixes;
 69
 70        int                        num_slots;        /* Slots on controller */
 71        struct sdhci_pci_slot        *slots[MAX_SLOTS]; /* Pointers to host slots */
 72};
 73
 74
 75/*****************************************************************************\
 76 *                                                                           *
 77 * Hardware specific quirk handling                                          *
 78 *                                                                           *
 79\*****************************************************************************/
 80
 81static int ricoh_probe(struct sdhci_pci_chip *chip)
 82{
 83        if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
 84                chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET;
 85
 86        if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)
 87                chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET;
 88
 89        return 0;
 90}
 91
 92static const struct sdhci_pci_fixes sdhci_ricoh = {
 93        .probe                = ricoh_probe,
 94        .quirks                = SDHCI_QUIRK_32BIT_DMA_ADDR,
 95};
 96
 97static const struct sdhci_pci_fixes sdhci_ene_712 = {
 98        .quirks                = SDHCI_QUIRK_SINGLE_POWER_WRITE |
 99                          SDHCI_QUIRK_BROKEN_DMA,
100};
101
102static const struct sdhci_pci_fixes sdhci_ene_714 = {
103        .quirks                = SDHCI_QUIRK_SINGLE_POWER_WRITE |
104                          SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
105                          SDHCI_QUIRK_BROKEN_DMA,
106};
107
108static const struct sdhci_pci_fixes sdhci_cafe = {
109        .quirks                = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
110                          SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
111};
112
113static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
114{
115        u8 scratch;
116        int ret;
117
118        ret = pci_read_config_byte(chip->pdev, 0xAE, &scratch);
119        if (ret)
120                return ret;
121
122        /*
123         * Turn PMOS on [bit 0], set over current detection to 2.4 V
124         * [bit 1:2] and enable over current debouncing [bit 6].
125         */
126        if (on)
127                scratch |= 0x47;
128        else
129                scratch &= ~0x47;
130
131        ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
132        if (ret)
133                return ret;
134
135        return 0;
136}
137
138static int jmicron_probe(struct sdhci_pci_chip *chip)
139{
140        int ret;
141
142        if (chip->pdev->revision == 0) {
143                chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR |
144                          SDHCI_QUIRK_32BIT_DMA_SIZE |
145                          SDHCI_QUIRK_32BIT_ADMA_SIZE |
146                          SDHCI_QUIRK_RESET_AFTER_REQUEST |
147                          SDHCI_QUIRK_BROKEN_SMALL_PIO |
148                          SDHCI_QUIRK_FORCE_HIGHSPEED;
149        }
150
151        /*
152         * JMicron chips can have two interfaces to the same hardware
153         * in order to work around limitations in Microsoft's driver.
154         * We need to make sure we only bind to one of them.
155         *
156         * This code assumes two things:
157         *
158         * 1. The PCI code adds subfunctions in order.
159         *
160         * 2. The MMC interface has a lower subfunction number
161         *    than the SD interface.
162         */
163        if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD) {
164                struct pci_dev *sd_dev;
165
166                sd_dev = NULL;
167                while ((sd_dev = pci_get_device(PCI_VENDOR_ID_JMICRON,
168                        PCI_DEVICE_ID_JMICRON_JMB38X_MMC, sd_dev)) != NULL) {
169                        if ((PCI_SLOT(chip->pdev->devfn) ==
170                                PCI_SLOT(sd_dev->devfn)) &&
171                                (chip->pdev->bus == sd_dev->bus))
172                                break;
173                }
174
175                if (sd_dev) {
176                        pci_dev_put(sd_dev);
177                        dev_info(&chip->pdev->dev, "Refusing to bind to "
178                                "secondary interface.\n");
179                        return -ENODEV;
180                }
181        }
182
183        /*
184         * JMicron chips need a bit of a nudge to enable the power
185         * output pins.
186         */
187        ret = jmicron_pmos(chip, 1);
188        if (ret) {
189                dev_err(&chip->pdev->dev, "Failure enabling card power\n");
190                return ret;
191        }
192
193        return 0;
194}
195
196static void jmicron_enable_mmc(struct sdhci_host *host, int on)
197{
198        u8 scratch;
199
200        scratch = readb(host->ioaddr + 0xC0);
201
202        if (on)
203                scratch |= 0x01;
204        else
205                scratch &= ~0x01;
206
207        writeb(scratch, host->ioaddr + 0xC0);
208}
209
210static int jmicron_probe_slot(struct sdhci_pci_slot *slot)
211{
212        if (slot->chip->pdev->revision == 0) {
213                u16 version;
214
215                version = readl(slot->host->ioaddr + SDHCI_HOST_VERSION);
216                version = (version & SDHCI_VENDOR_VER_MASK) >>
217                        SDHCI_VENDOR_VER_SHIFT;
218
219                /*
220                 * Older versions of the chip have lots of nasty glitches
221                 * in the ADMA engine. It's best just to avoid it
222                 * completely.
223                 */
224                if (version < 0xAC)
225                        slot->host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
226        }
227
228        /*
229         * The secondary interface requires a bit set to get the
230         * interrupts.
231         */
232        if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
233                jmicron_enable_mmc(slot->host, 1);
234
235        return 0;
236}
237
238static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
239{
240        if (dead)
241                return;
242
243        if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
244                jmicron_enable_mmc(slot->host, 0);
245}
246
247static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state)
248{
249        int i;
250
251        if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
252                for (i = 0;i < chip->num_slots;i++)
253                        jmicron_enable_mmc(chip->slots[i]->host, 0);
254        }
255
256        return 0;
257}
258
259static int jmicron_resume(struct sdhci_pci_chip *chip)
260{
261        int ret, i;
262
263        if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
264                for (i = 0;i < chip->num_slots;i++)
265                        jmicron_enable_mmc(chip->slots[i]->host, 1);
266        }
267
268        ret = jmicron_pmos(chip, 1);
269        if (ret) {
270                dev_err(&chip->pdev->dev, "Failure enabling card power\n");
271                return ret;
272        }
273
274        return 0;
275}
276
277static const struct sdhci_pci_fixes sdhci_jmicron = {
278        .probe                = jmicron_probe,
279
280        .probe_slot        = jmicron_probe_slot,
281        .remove_slot        = jmicron_remove_slot,
282
283        .suspend        = jmicron_suspend,
284        .resume                = jmicron_resume,
285};
286
287static const struct pci_device_id pci_ids[] __devinitdata = {
288        {
289                .vendor                = PCI_VENDOR_ID_RICOH,
290                .device                = PCI_DEVICE_ID_RICOH_R5C822,
291                .subvendor        = PCI_ANY_ID,
292                .subdevice        = PCI_ANY_ID,
293                .driver_data        = (kernel_ulong_t)&sdhci_ricoh,
294        },
295
296        {
297                .vendor                = PCI_VENDOR_ID_ENE,
298                .device                = PCI_DEVICE_ID_ENE_CB712_SD,
299                .subvendor        = PCI_ANY_ID,
300                .subdevice        = PCI_ANY_ID,
301                .driver_data        = (kernel_ulong_t)&sdhci_ene_712,
302        },
303
304        {
305                .vendor                = PCI_VENDOR_ID_ENE,
306                .device                = PCI_DEVICE_ID_ENE_CB712_SD_2,
307                .subvendor        = PCI_ANY_ID,
308                .subdevice        = PCI_ANY_ID,
309                .driver_data        = (kernel_ulong_t)&sdhci_ene_712,
310        },
311
312        {
313                .vendor                = PCI_VENDOR_ID_ENE,
314                .device                = PCI_DEVICE_ID_ENE_CB714_SD,
315                .subvendor        = PCI_ANY_ID,
316                .subdevice        = PCI_ANY_ID,
317                .driver_data        = (kernel_ulong_t)&sdhci_ene_714,
318        },
319
320        {
321                .vendor                = PCI_VENDOR_ID_ENE,
322                .device                = PCI_DEVICE_ID_ENE_CB714_SD_2,
323                .subvendor        = PCI_ANY_ID,
324                .subdevice        = PCI_ANY_ID,
325                .driver_data        = (kernel_ulong_t)&sdhci_ene_714,
326        },
327
328        {
329                .vendor         = PCI_VENDOR_ID_MARVELL,
330                .device         = PCI_DEVICE_ID_MARVELL_88ALP01_SD,
331                .subvendor      = PCI_ANY_ID,
332                .subdevice      = PCI_ANY_ID,
333                .driver_data    = (kernel_ulong_t)&sdhci_cafe,
334        },
335
336        {
337                .vendor                = PCI_VENDOR_ID_JMICRON,
338                .device                = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
339                .subvendor        = PCI_ANY_ID,
340                .subdevice        = PCI_ANY_ID,
341                .driver_data        = (kernel_ulong_t)&sdhci_jmicron,
342        },
343
344        {
345                .vendor                = PCI_VENDOR_ID_JMICRON,
346                .device                = PCI_DEVICE_ID_JMICRON_JMB38X_MMC,
347                .subvendor        = PCI_ANY_ID,
348                .subdevice        = PCI_ANY_ID,
349                .driver_data        = (kernel_ulong_t)&sdhci_jmicron,
350        },
351
352        {        /* Generic SD host controller */
353                PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
354        },
355
356        { /* end: all zeroes */ },
357};
358
359MODULE_DEVICE_TABLE(pci, pci_ids);
360
361/*****************************************************************************\
362 *                                                                           *
363 * SDHCI core callbacks                                                      *
364 *                                                                           *
365\*****************************************************************************/
366
367static int sdhci_pci_enable_dma(struct sdhci_host *host)
368{
369        struct sdhci_pci_slot *slot;
370        struct pci_dev *pdev;
371        int ret;
372
373        slot = sdhci_priv(host);
374        pdev = slot->chip->pdev;
375
376        if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) &&
377                ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) &&
378                (host->flags & SDHCI_USE_DMA)) {
379                dev_warn(&pdev->dev, "Will use DMA mode even though HW "
380                        "doesn't fully claim to support it.\n");
381        }
382
383        ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
384        if (ret)
385                return ret;
386
387        pci_set_master(pdev);
388
389        return 0;
390}
391
392static struct sdhci_ops sdhci_pci_ops = {
393        .enable_dma        = sdhci_pci_enable_dma,
394};
395
396/*****************************************************************************\
397 *                                                                           *
398 * Suspend/resume                                                            *
399 *                                                                           *
400\*****************************************************************************/
401
402#ifdef CONFIG_PM
403
404static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
405{
406        struct sdhci_pci_chip *chip;
407        struct sdhci_pci_slot *slot;
408        int i, ret;
409
410        chip = pci_get_drvdata(pdev);
411        if (!chip)
412                return 0;
413
414        for (i = 0;i < chip->num_slots;i++) {
415                slot = chip->slots[i];
416                if (!slot)
417                        continue;
418
419                ret = sdhci_suspend_host(slot->host, state);
420
421                if (ret) {
422                        for (i--;i >= 0;i--)
423                                sdhci_resume_host(chip->slots[i]->host);
424                        return ret;
425                }
426        }
427
428        if (chip->fixes && chip->fixes->suspend) {
429                ret = chip->fixes->suspend(chip, state);
430                if (ret) {
431                        for (i = chip->num_slots - 1;i >= 0;i--)
432                                sdhci_resume_host(chip->slots[i]->host);
433                        return ret;
434                }
435        }
436
437        pci_save_state(pdev);
438        pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
439        pci_disable_device(pdev);
440        pci_set_power_state(pdev, pci_choose_state(pdev, state));
441
442        return 0;
443}
444
445static int sdhci_pci_resume (struct pci_dev *pdev)
446{
447        struct sdhci_pci_chip *chip;
448        struct sdhci_pci_slot *slot;
449        int i, ret;
450
451        chip = pci_get_drvdata(pdev);
452        if (!chip)
453                return 0;
454
455        pci_set_power_state(pdev, PCI_D0);
456        pci_restore_state(pdev);
457        ret = pci_enable_device(pdev);
458        if (ret)
459                return ret;
460
461        if (chip->fixes && chip->fixes->resume) {
462                ret = chip->fixes->resume(chip);
463                if (ret)
464                        return ret;
465        }
466
467        for (i = 0;i < chip->num_slots;i++) {
468                slot = chip->slots[i];
469                if (!slot)
470                        continue;
471
472                ret = sdhci_resume_host(slot->host);
473                if (ret)
474                        return ret;
475        }
476
477        return 0;
478}
479
480#else /* CONFIG_PM */
481
482#define sdhci_pci_suspend NULL
483#define sdhci_pci_resume NULL
484
485#endif /* CONFIG_PM */
486
487/*****************************************************************************\
488 *                                                                           *
489 * Device probing/removal                                                    *
490 *                                                                           *
491\*****************************************************************************/
492
493static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
494        struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar)
495{
496        struct sdhci_pci_slot *slot;
497        struct sdhci_host *host;
498
499        resource_size_t addr;
500
501        int ret;
502
503        if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
504                dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
505                return ERR_PTR(-ENODEV);
506        }
507
508        if (pci_resource_len(pdev, bar) != 0x100) {
509                dev_err(&pdev->dev, "Invalid iomem size. You may "
510                        "experience problems.\n");
511        }
512
513        if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
514                dev_err(&pdev->dev, "Vendor specific interface. Aborting.\n");
515                return ERR_PTR(-ENODEV);
516        }
517
518        if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) {
519                dev_err(&pdev->dev, "Unknown interface. Aborting.\n");
520                return ERR_PTR(-ENODEV);
521        }
522
523        host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot));
524        if (IS_ERR(host)) {
525                ret = PTR_ERR(host);
526                goto unmap;
527        }
528
529        slot = sdhci_priv(host);
530
531        slot->chip = chip;
532        slot->host = host;
533        slot->pci_bar = bar;
534
535        host->hw_name = "PCI";
536        host->ops = &sdhci_pci_ops;
537        host->quirks = chip->quirks;
538
539        host->irq = pdev->irq;
540
541        ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
542        if (ret) {
543                dev_err(&pdev->dev, "cannot request region\n");
544                return ERR_PTR(ret);
545        }
546
547        addr = pci_resource_start(pdev, bar);
548        host->ioaddr = ioremap_nocache(addr, pci_resource_len(pdev, bar));
549        if (!host->ioaddr) {
550                dev_err(&pdev->dev, "failed to remap registers\n");
551                goto release;
552        }
553
554        if (chip->fixes && chip->fixes->probe_slot) {
555                ret = chip->fixes->probe_slot(slot);
556                if (ret)
557                        goto unmap;
558        }
559
560        ret = sdhci_add_host(host);
561        if (ret)
562                goto remove;
563
564        return slot;
565
566remove:
567        if (chip->fixes && chip->fixes->remove_slot)
568                chip->fixes->remove_slot(slot, 0);
569
570unmap:
571        iounmap(host->ioaddr);
572
573release:
574        pci_release_region(pdev, bar);
575        sdhci_free_host(host);
576
577        return ERR_PTR(ret);
578}
579
580static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
581{
582        int dead;
583        u32 scratch;
584
585        dead = 0;
586        scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
587        if (scratch == (u32)-1)
588                dead = 1;
589
590        sdhci_remove_host(slot->host, dead);
591
592        if (slot->chip->fixes && slot->chip->fixes->remove_slot)
593                slot->chip->fixes->remove_slot(slot, dead);
594
595        pci_release_region(slot->chip->pdev, slot->pci_bar);
596
597        sdhci_free_host(slot->host);
598}
599
600static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
601                                     const struct pci_device_id *ent)
602{
603        struct sdhci_pci_chip *chip;
604        struct sdhci_pci_slot *slot;
605
606        u8 slots, rev, first_bar;
607        int ret, i;
608
609        BUG_ON(pdev == NULL);
610        BUG_ON(ent == NULL);
611
612        pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
613
614        dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n",
615                 (int)pdev->vendor, (int)pdev->device, (int)rev);
616
617        ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
618        if (ret)
619                return ret;
620
621        slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
622        dev_dbg(&pdev->dev, "found %d slot(s)\n", slots);
623        if (slots == 0)
624                return -ENODEV;
625
626        BUG_ON(slots > MAX_SLOTS);
627
628        ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
629        if (ret)
630                return ret;
631
632        first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
633
634        if (first_bar > 5) {
635                dev_err(&pdev->dev, "Invalid first BAR. Aborting.\n");
636                return -ENODEV;
637        }
638
639        ret = pci_enable_device(pdev);
640        if (ret)
641                return ret;
642
643        chip = kzalloc(sizeof(struct sdhci_pci_chip), GFP_KERNEL);
644        if (!chip) {
645                ret = -ENOMEM;
646                goto err;
647        }
648
649        chip->pdev = pdev;
650        chip->fixes = (const struct sdhci_pci_fixes*)ent->driver_data;
651        if (chip->fixes)
652                chip->quirks = chip->fixes->quirks;
653        chip->num_slots = slots;
654
655        pci_set_drvdata(pdev, chip);
656
657        if (chip->fixes && chip->fixes->probe) {
658                ret = chip->fixes->probe(chip);
659                if (ret)
660                        goto free;
661        }
662
663        for (i = 0;i < slots;i++) {
664                slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
665                if (IS_ERR(slot)) {
666                        for (i--;i >= 0;i--)
667                                sdhci_pci_remove_slot(chip->slots[i]);
668                        ret = PTR_ERR(slot);
669                        goto free;
670                }
671
672                chip->slots[i] = slot;
673        }
674
675        return 0;
676
677free:
678        pci_set_drvdata(pdev, NULL);
679        kfree(chip);
680
681err:
682        pci_disable_device(pdev);
683        return ret;
684}
685
686static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
687{
688        int i;
689        struct sdhci_pci_chip *chip;
690
691        chip = pci_get_drvdata(pdev);
692
693        if (chip) {
694                for (i = 0;i < chip->num_slots; i++)
695                        sdhci_pci_remove_slot(chip->slots[i]);
696
697                pci_set_drvdata(pdev, NULL);
698                kfree(chip);
699        }
700
701        pci_disable_device(pdev);
702}
703
704static struct pci_driver sdhci_driver = {
705        .name =         "sdhci-pci",
706        .id_table =        pci_ids,
707        .probe =         sdhci_pci_probe,
708        .remove =        __devexit_p(sdhci_pci_remove),
709        .suspend =        sdhci_pci_suspend,
710        .resume        =        sdhci_pci_resume,
711};
712
713/*****************************************************************************\
714 *                                                                           *
715 * Driver init/exit                                                          *
716 *                                                                           *
717\*****************************************************************************/
718
719static int __init sdhci_drv_init(void)
720{
721        return pci_register_driver(&sdhci_driver);
722}
723
724static void __exit sdhci_drv_exit(void)
725{
726        pci_unregister_driver(&sdhci_driver);
727}
728
729module_init(sdhci_drv_init);
730module_exit(sdhci_drv_exit);
731
732MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
733MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
734MODULE_LICENSE("GPL");