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 : : #include <linux/mmc/sdio_ids.h>
17 : :
18 : : #ifndef SDIO_VENDOR_ID_TI
19 : : #define SDIO_VENDOR_ID_TI 0x0097
20 : : #endif
21 : :
22 : : #ifndef SDIO_DEVICE_ID_TI_WL1271
23 : : #define SDIO_DEVICE_ID_TI_WL1271 0x4076
24 : : #endif
25 : :
26 : : #ifndef SDIO_VENDOR_ID_STE
27 : : #define SDIO_VENDOR_ID_STE 0x0020
28 : : #endif
29 : :
30 : : #ifndef SDIO_DEVICE_ID_STE_CW1200
31 : : #define SDIO_DEVICE_ID_STE_CW1200 0x2280
32 : : #endif
33 : :
34 : : #ifndef SDIO_DEVICE_ID_MARVELL_8797_F0
35 : : #define SDIO_DEVICE_ID_MARVELL_8797_F0 0x9128
36 : : #endif
37 : :
38 : : /*
39 : : * This hook just adds a quirk for all sdio devices
40 : : */
41 : 0 : static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
42 : : {
43 [ # # ]: 0 : if (mmc_card_sdio(card))
44 : 0 : card->quirks |= data;
45 : 0 : }
46 : :
47 : : static const struct mmc_fixup mmc_fixup_methods[] = {
48 : : /* by default sdio devices are considered CLK_GATING broken */
49 : : /* good cards will be whitelisted as they are tested */
50 : : SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID,
51 : : add_quirk_for_sdio_devices,
52 : : MMC_QUIRK_BROKEN_CLK_GATING),
53 : :
54 : : SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
55 : : remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),
56 : :
57 : : SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
58 : : add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
59 : :
60 : : SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
61 : : add_quirk, MMC_QUIRK_DISABLE_CD),
62 : :
63 : : SDIO_FIXUP(SDIO_VENDOR_ID_STE, SDIO_DEVICE_ID_STE_CW1200,
64 : : add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512),
65 : :
66 : : SDIO_FIXUP(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797_F0,
67 : : add_quirk, MMC_QUIRK_BROKEN_IRQ_POLLING),
68 : :
69 : : END_FIXUP
70 : : };
71 : :
72 : 0 : void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
73 : : {
74 : : const struct mmc_fixup *f;
75 : 0 : u64 rev = cid_rev_card(card);
76 : :
77 : : /* Non-core specific workarounds. */
78 [ # # ]: 0 : if (!table)
79 : : table = mmc_fixup_methods;
80 : :
81 [ # # ]: 0 : for (f = table; f->vendor_fixup; f++) {
82 [ # # ][ # # ]: 0 : if ((f->manfid == CID_MANFID_ANY ||
83 [ # # ]: 0 : f->manfid == card->cid.manfid) &&
84 [ # # ]: 0 : (f->oemid == CID_OEMID_ANY ||
85 [ # # ]: 0 : f->oemid == card->cid.oemid) &&
86 [ # # ]: 0 : (f->name == CID_NAME_ANY ||
87 : 0 : !strncmp(f->name, card->cid.prod_name,
88 [ # # ]: 0 : sizeof(card->cid.prod_name))) &&
89 [ # # ]: 0 : (f->cis_vendor == card->cis.vendor ||
90 [ # # ]: 0 : f->cis_vendor == (u16) SDIO_ANY_ID) &&
91 [ # # ]: 0 : (f->cis_device == card->cis.device ||
92 [ # # ]: 0 : f->cis_device == (u16) SDIO_ANY_ID) &&
93 [ # # ]: 0 : rev >= f->rev_start && rev <= f->rev_end) {
94 : : dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
95 : 0 : f->vendor_fixup(card, f->data);
96 : : }
97 : : }
98 : 0 : }
99 : : EXPORT_SYMBOL(mmc_fixup_device);
|