aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mmc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mmc')
-rw-r--r--drivers/mmc/core/core.h2
-rw-r--r--drivers/mmc/core/quirks.c93
-rw-r--r--drivers/mmc/core/sdio.c2
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);
61int mmc_attach_sd(struct mmc_host *host); 61int mmc_attach_sd(struct mmc_host *host);
62int mmc_attach_sdio(struct mmc_host *host); 62int mmc_attach_sdio(struct mmc_host *host);
63 63
64void mmc_fixup_device(struct mmc_card *card);
65
66/* Module parameters */ 64/* Module parameters */
67extern int use_spi_crc; 65extern 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
21struct 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 */
30static 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
38static 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
60static const struct mmc_fixup mmc_fixup_methods[] = { 33static 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
74void mmc_fixup_device(struct mmc_card *card) 52void 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);