1 /*
2 * Copyright (C) 2017 ALLWINNERTECH TECHNOLOGY CO., LTD. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the
12 * distribution.
13 * 3. Neither the name of ALLWINNERTECH TECHNOLOGY CO., LTD. nor the names of
14 * its contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 #include "string.h" /* for strncmp() */
31
32 #include "card.h"
33
34 #include "_core.h"
35
36 #ifdef CONFIG_USE_MMC_QUIRK
37
38 #ifndef SDIO_VENDOR_ID_TI
39 #define SDIO_VENDOR_ID_TI 0x0097
40 #endif
41
42 #ifndef SDIO_DEVICE_ID_TI_WL1271
43 #define SDIO_DEVICE_ID_TI_WL1271 0x4076
44 #endif
45
46 #ifndef SDIO_VENDOR_ID_XR
47 #define SDIO_VENDOR_ID_XR 0x0020
48 #endif
49
50 #ifndef SDIO_DEVICE_ID_XRADIO
51 #define SDIO_DEVICE_ID_XRADIO 0x2281
52 #endif
53
54 static const struct mmc_fixup mmc_fixup_methods[] = {
55 /* by default sdio devices are considered CLK_GATING broken */
56 /* good cards will be whitelisted as they are tested */
57 SDIO_FIXUP(SDIO_ANY_ID, SDIO_ANY_ID, add_quirk_for_sdio_devices,
58 MMC_QUIRK_BROKEN_CLK_GATING),
59
60 SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
61 remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING),
62
63 SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
64 add_quirk, MMC_QUIRK_NONSTD_FUNC_IF),
65
66 SDIO_FIXUP(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
67 add_quirk, MMC_QUIRK_DISABLE_CD),
68
69 SDIO_FIXUP(SDIO_VENDOR_ID_XR, SDIO_DEVICE_ID_XRADIO,
70 add_quirk, MMC_QUIRK_BROKEN_BYTE_MODE_512),
71
72 END_FIXUP
73 };
74
mmc_fixup_device(struct mmc_card * card,const struct mmc_fixup * table)75 void mmc_fixup_device(struct mmc_card *card, const struct mmc_fixup *table)
76 {
77 const struct mmc_fixup *f;
78 uint64_t rev = cid_rev_card(card);
79
80 /* Non-core specific workarounds. */
81 if (!table)
82 table = mmc_fixup_methods;
83
84 for (f = table; f->vendor_fixup; f++) {
85 if ((f->manfid == CID_MANFID_ANY ||
86 f->manfid == card->cid.manfid) &&
87 (f->oemid == CID_OEMID_ANY ||
88 f->oemid == card->cid.oemid) &&
89 (f->name == CID_NAME_ANY ||
90 !strncmp(f->name, card->cid.prod_name,
91 sizeof(card->cid.prod_name))) &&
92 (f->cis_vendor == card->cis.vendor ||
93 f->cis_vendor == (uint16_t) SDIO_ANY_ID) &&
94 (f->cis_device == card->cis.device ||
95 f->cis_device == (uint16_t) SDIO_ANY_ID) &&
96 rev >= f->rev_start && rev <= f->rev_end) {
97 SD_LOGD("%s calling %pF\n", __func__, f->vendor_fixup);
98 f->vendor_fixup(card, f->data);
99 }
100 }
101 }
102 #endif
103