diff options
Diffstat (limited to 'drivers/mmc')
-rw-r--r-- | drivers/mmc/core/core.h | 2 | ||||
-rw-r--r-- | drivers/mmc/core/quirks.c | 93 | ||||
-rw-r--r-- | drivers/mmc/core/sdio.c | 2 |
3 files changed, 43 insertions, 54 deletions
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 20b1c0831eac..ca1fdde29df6 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
@@ -61,8 +61,6 @@ int mmc_attach_mmc(struct mmc_host *host); | |||
61 | int mmc_attach_sd(struct mmc_host *host); | 61 | int mmc_attach_sd(struct mmc_host *host); |
62 | int mmc_attach_sdio(struct mmc_host *host); | 62 | int mmc_attach_sdio(struct mmc_host *host); |
63 | 63 | ||
64 | void mmc_fixup_device(struct mmc_card *card); | ||
65 | |||
66 | /* Module parameters */ | 64 | /* Module parameters */ |
67 | extern int use_spi_crc; | 65 | extern int use_spi_crc; |
68 | 66 | ||
diff --git a/drivers/mmc/core/quirks.c b/drivers/mmc/core/quirks.c index a4c42edc6cb3..3a596217029e 100644 --- a/drivers/mmc/core/quirks.c +++ b/drivers/mmc/core/quirks.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * This file contains work-arounds for many known sdio hardware | 2 | * This file contains work-arounds for many known SD/MMC |
3 | * bugs. | 3 | * and SDIO hardware bugs. |
4 | * | 4 | * |
5 | * Copyright (c) 2011 Andrei Warkentin <andreiw@motorola.com> | ||
5 | * Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com> | 6 | * Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com> |
6 | * Inspired from pci fixup code: | 7 | * Inspired from pci fixup code: |
7 | * Copyright (c) 1999 Martin Mares <mj@ucw.cz> | 8 | * Copyright (c) 1999 Martin Mares <mj@ucw.cz> |
@@ -11,34 +12,14 @@ | |||
11 | #include <linux/types.h> | 12 | #include <linux/types.h> |
12 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
13 | #include <linux/mmc/card.h> | 14 | #include <linux/mmc/card.h> |
14 | #include <linux/mod_devicetable.h> | ||
15 | 15 | ||
16 | /* | 16 | #ifndef SDIO_VENDOR_ID_TI |
17 | * The world is not perfect and supplies us with broken mmc/sdio devices. | 17 | #define SDIO_VENDOR_ID_TI 0x0097 |
18 | * For at least a part of these bugs we need a work-around | 18 | #endif |
19 | */ | ||
20 | |||
21 | struct mmc_fixup { | ||
22 | u16 vendor, device; /* You can use SDIO_ANY_ID here of course */ | ||
23 | void (*vendor_fixup)(struct mmc_card *card, int data); | ||
24 | int data; | ||
25 | }; | ||
26 | |||
27 | /* | ||
28 | * This hook just adds a quirk unconditionnally | ||
29 | */ | ||
30 | static void __maybe_unused add_quirk(struct mmc_card *card, int data) | ||
31 | { | ||
32 | card->quirks |= data; | ||
33 | } | ||
34 | 19 | ||
35 | /* | 20 | #ifndef SDIO_DEVICE_ID_TI_WL1271 |
36 | * This hook just removes a quirk unconditionnally | 21 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 |
37 | */ | 22 | #endif |
38 | static void __maybe_unused remove_quirk(struct mmc_card *card, int data) | ||
39 | { | ||
40 | card->quirks &= ~data; | ||
41 | } | ||
42 | 23 | ||
43 | /* | 24 | /* |
44 | * This hook just adds a quirk for all sdio devices | 25 | * This hook just adds a quirk for all sdio devices |
@@ -49,37 +30,47 @@ static void add_quirk_for_sdio_devices(struct mmc_card *card, int data) | |||
49 | card->quirks |= data; | 30 | card->quirks |= data; |
50 | } | 31 | } |
51 | 32 | ||
52 | #ifndef SDIO_VENDOR_ID_TI | ||
53 | #define SDIO_VENDOR_ID_TI 0x0097 | ||
54 | #endif | ||
55 | |||
56 | #ifndef SDIO_DEVICE_ID_TI_WL1271 | ||
57 | #define SDIO_DEVICE_ID_TI_WL1271 0x4076 | ||
58 | #endif | ||
59 | |||
60 | static const struct mmc_fixup mmc_fixup_methods[] = { | 33 | static const struct mmc_fixup mmc_fixup_methods[] = { |
61 | /* by default sdio devices are considered CLK_GATING broken */ | 34 | /* by default sdio devices are considered CLK_GATING broken */ |
62 | /* good cards will be whitelisted as they are tested */ | 35 | /* good cards will be whitelisted as they are tested */ |
63 | { SDIO_ANY_ID, SDIO_ANY_ID, | 36 | SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID, |
64 | add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING }, | 37 | add_quirk_for_sdio_devices, |
65 | { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, | 38 | MMC_QUIRK_BROKEN_CLK_GATING), |
66 | remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING }, | 39 | |
67 | { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, | 40 | SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, |
68 | add_quirk, MMC_QUIRK_NONSTD_FUNC_IF }, | 41 | remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING), |
69 | { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, | 42 | |
70 | add_quirk, MMC_QUIRK_DISABLE_CD }, | 43 | SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, |
71 | { 0 } | 44 | add_quirk, MMC_QUIRK_NONSTD_FUNC_IF), |
45 | |||
46 | SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271, | ||
47 | add_quirk, MMC_QUIRK_DISABLE_CD), | ||
48 | |||
49 | END_FIXUP | ||
72 | }; | 50 | }; |
73 | 51 | ||
74 | void mmc_fixup_device(struct mmc_card *card) | 52 | void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table) |
75 | { | 53 | { |
76 | const struct mmc_fixup *f; | 54 | const struct mmc_fixup *f; |
55 | u64 rev = cid_rev_card(card); | ||
56 | |||
57 | /* Non-core specific workarounds. */ | ||
58 | if (!table) | ||
59 | table = mmc_fixup_methods; | ||
77 | 60 | ||
78 | for (f = mmc_fixup_methods; f->vendor_fixup; f++) { | 61 | for (f = table; f->vendor_fixup; f++) { |
79 | if ((f->vendor == card->cis.vendor | 62 | if ((f->manfid == CID_MANFID_ANY || |
80 | || f->vendor == (u16) SDIO_ANY_ID) && | 63 | f->manfid == card->cid.manfid) && |
81 | (f->device == card->cis.device | 64 | (f->oemid == CID_OEMID_ANY || |
82 | || f->device == (u16) SDIO_ANY_ID)) { | 65 | f->oemid == card->cid.oemid) && |
66 | (f->name == CID_NAME_ANY || | ||
67 | !strncmp(f->name, card->cid.prod_name, | ||
68 | sizeof(card->cid.prod_name))) && | ||
69 | (f->cis_vendor == card->cis.vendor || | ||
70 | f->cis_vendor == (u16) SDIO_ANY_ID) && | ||
71 | (f->cis_device == card->cis.device || | ||
72 | f->cis_device == (u16) SDIO_ANY_ID) && | ||
73 | rev >= f->rev_start && rev <= f->rev_end) { | ||
83 | dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup); | 74 | dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup); |
84 | f->vendor_fixup(card, f->data); | 75 | f->vendor_fixup(card, f->data); |
85 | } | 76 | } |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index a5840c0de2e4..1e6095961500 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -472,7 +472,7 @@ static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, | |||
472 | 472 | ||
473 | card = oldcard; | 473 | card = oldcard; |
474 | } | 474 | } |
475 | mmc_fixup_device(card); | 475 | mmc_fixup_device(card, NULL); |
476 | 476 | ||
477 | if (card->type == MMC_TYPE_SD_COMBO) { | 477 | if (card->type == MMC_TYPE_SD_COMBO) { |
478 | err = mmc_sd_setup_card(host, card, oldcard != NULL); | 478 | err = mmc_sd_setup_card(host, card, oldcard != NULL); |