Branch data Line data Source code
1 : : /*
2 : : * This file contains work-arounds for many known SD/MMC
3 : : * and SDIO hardware bugs.
4 : : *
5 : : * Copyright (c) 2011 Andrei Warkentin <andreiw@motorola.com>
6 : : * Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com>
7 : : * Inspired from pci fixup code:
8 : : * Copyright (c) 1999 Martin Mares <mj@ucw.cz>
9 : : *
10 : : */
11 : :
12 : : #include <linux/types.h>
13 : : #include <linux/kernel.h>
14 : : #include <linux/export.h>
15 : : #include <linux/mmc/card.h>
16 : :
17 : : #ifndef SDIO_VENDOR_ID_TI
18 : : #define SDIO_VENDOR_ID_TI 0x0097
19 : : #endif
20 : :
21 : : #ifndef SDIO_DEVICE_ID_TI_WL1271
22 : : #define SDIO_DEVICE_ID_TI_WL1271 0x4076
23 : : #endif
24 : :
25 : : #ifndef SDIO_VENDOR_ID_STE
26 : : #define SDIO_VENDOR_ID_STE 0x0020
27 : : #endif
28 : :
29 : : #ifndef SDIO_DEVICE_ID_STE_CW1200
30 : : #define SDIO_DEVICE_ID_STE_CW1200 0x2280
31 : : #endif
32 : :
33 : : /*
34 : : * This hook just adds a quirk for all sdio devices
35 : : */
36 : 0 : static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
37 : : {
38 [ # # ]: 0 : if (mmc_card_sdio(card))
39 : 0 : card->quirks |= data;
40 : 0 : }
41 : :
42 : : static const struct mmc_fixup mmc_fixup_methods[] = {
43 : : /* by default sdio devices are considered CLK_GATING broken */
44 : : /* good cards will be whitelisted as they are tested */
45 : : SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID,
46 : : add_quirk_for_sdio_devices,
47 : : MMC_QUIRK_BROKEN_CLK_GATING),
48 : :
49 : : SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
50 : : remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),
51 : :
52 : : SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
53 : : add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
54 : :
55 : : SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
56 : : add_quirk, MMC_QUIRK_DISABLE_CD),
57 : :
58 : : SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200,
59 : : add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512),
60 : :
61 : : END_FIXUP
62 : : };
63 : :
64 : 0 : void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
65 : : {
66 : : const struct mmc_fixup *f;
67 : 0 : u64 rev = cid_rev_card(card);
68 : :
69 : : /* Non-core specific workarounds. */
70 [ # # ]: 0 : if (!table)
71 : : table = mmc_fixup_methods;
72 : :
73 [ # # ]: 0 : for (f = table; f->vendor_fixup; f++) {
74 [ # # ][ # # ]: 0 : if ((f->manfid == CID_MANFID_ANY ||
75 [ # # ]: 0 : f->manfid == card->cid.manfid) &&
76 [ # # ]: 0 : (f->oemid == CID_OEMID_ANY ||
77 [ # # ]: 0 : f->oemid == card->cid.oemid) &&
78 [ # # ]: 0 : (f->name == CID_NAME_ANY ||
79 : 0 : !strncmp(f->name, card->cid.prod_name,
80 [ # # ]: 0 : sizeof(card->cid.prod_name))) &&
81 [ # # ]: 0 : (f->cis_vendor == card->cis.vendor ||
82 [ # # ]: 0 : f->cis_vendor == (u16) SDIO_ANY_ID) &&
83 [ # # ]: 0 : (f->cis_device == card->cis.device ||
84 [ # # ]: 0 : f->cis_device == (u16) SDIO_ANY_ID) &&
85 [ # # ]: 0 : rev >= f->rev_start && rev <= f->rev_end) {
86 : : dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
87 : 0 : f->vendor_fixup(card, f->data);
88 : : }
89 : : }
90 : 0 : }
91 : : EXPORT_SYMBOL(mmc_fixup_device);
|