1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0-only */
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * Private header for the mmc subsystem
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2016 Linaro Ltd
6*4882a593Smuzhiyun *
7*4882a593Smuzhiyun * Author: Ulf Hansson <ulf.hansson@linaro.org>
8*4882a593Smuzhiyun */
9*4882a593Smuzhiyun
10*4882a593Smuzhiyun #ifndef _MMC_CORE_CARD_H
11*4882a593Smuzhiyun #define _MMC_CORE_CARD_H
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun #include <linux/mmc/card.h>
14*4882a593Smuzhiyun
15*4882a593Smuzhiyun #define mmc_card_name(c) ((c)->cid.prod_name)
16*4882a593Smuzhiyun #define mmc_card_id(c) (dev_name(&(c)->dev))
17*4882a593Smuzhiyun #define mmc_dev_to_card(d) container_of(d, struct mmc_card, dev)
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun /* Card states */
20*4882a593Smuzhiyun #define MMC_STATE_PRESENT (1<<0) /* present in sysfs */
21*4882a593Smuzhiyun #define MMC_STATE_READONLY (1<<1) /* card is read-only */
22*4882a593Smuzhiyun #define MMC_STATE_BLOCKADDR (1<<2) /* card uses block-addressing */
23*4882a593Smuzhiyun #define MMC_CARD_SDXC (1<<3) /* card is SDXC */
24*4882a593Smuzhiyun #define MMC_CARD_REMOVED (1<<4) /* card has been removed */
25*4882a593Smuzhiyun #define MMC_STATE_SUSPENDED (1<<5) /* card is suspended */
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #define mmc_card_present(c) ((c)->state & MMC_STATE_PRESENT)
28*4882a593Smuzhiyun #define mmc_card_readonly(c) ((c)->state & MMC_STATE_READONLY)
29*4882a593Smuzhiyun #define mmc_card_blockaddr(c) ((c)->state & MMC_STATE_BLOCKADDR)
30*4882a593Smuzhiyun #define mmc_card_ext_capacity(c) ((c)->state & MMC_CARD_SDXC)
31*4882a593Smuzhiyun #define mmc_card_removed(c) ((c) && ((c)->state & MMC_CARD_REMOVED))
32*4882a593Smuzhiyun #define mmc_card_suspended(c) ((c)->state & MMC_STATE_SUSPENDED)
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun #define mmc_card_set_present(c) ((c)->state |= MMC_STATE_PRESENT)
35*4882a593Smuzhiyun #define mmc_card_set_readonly(c) ((c)->state |= MMC_STATE_READONLY)
36*4882a593Smuzhiyun #define mmc_card_set_blockaddr(c) ((c)->state |= MMC_STATE_BLOCKADDR)
37*4882a593Smuzhiyun #define mmc_card_set_ext_capacity(c) ((c)->state |= MMC_CARD_SDXC)
38*4882a593Smuzhiyun #define mmc_card_set_removed(c) ((c)->state |= MMC_CARD_REMOVED)
39*4882a593Smuzhiyun #define mmc_card_set_suspended(c) ((c)->state |= MMC_STATE_SUSPENDED)
40*4882a593Smuzhiyun #define mmc_card_clr_suspended(c) ((c)->state &= ~MMC_STATE_SUSPENDED)
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun /*
43*4882a593Smuzhiyun * The world is not perfect and supplies us with broken mmc/sdio devices.
44*4882a593Smuzhiyun * For at least some of these bugs we need a work-around.
45*4882a593Smuzhiyun */
46*4882a593Smuzhiyun struct mmc_fixup {
47*4882a593Smuzhiyun /* CID-specific fields. */
48*4882a593Smuzhiyun const char *name;
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* Valid revision range */
51*4882a593Smuzhiyun u64 rev_start, rev_end;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun unsigned int manfid;
54*4882a593Smuzhiyun unsigned short oemid;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun /* SDIO-specific fields. You can use SDIO_ANY_ID here of course */
57*4882a593Smuzhiyun u16 cis_vendor, cis_device;
58*4882a593Smuzhiyun
59*4882a593Smuzhiyun /* for MMC cards */
60*4882a593Smuzhiyun unsigned int ext_csd_rev;
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun void (*vendor_fixup)(struct mmc_card *card, int data);
63*4882a593Smuzhiyun int data;
64*4882a593Smuzhiyun };
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun #define CID_MANFID_ANY (-1u)
67*4882a593Smuzhiyun #define CID_OEMID_ANY ((unsigned short) -1)
68*4882a593Smuzhiyun #define CID_NAME_ANY (NULL)
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun #define EXT_CSD_REV_ANY (-1u)
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun #define CID_MANFID_SANDISK 0x2
73*4882a593Smuzhiyun #define CID_MANFID_SANDISK_SD 0x3
74*4882a593Smuzhiyun #define CID_MANFID_ATP 0x9
75*4882a593Smuzhiyun #define CID_MANFID_TOSHIBA 0x11
76*4882a593Smuzhiyun #define CID_MANFID_MICRON 0x13
77*4882a593Smuzhiyun #define CID_MANFID_SAMSUNG 0x15
78*4882a593Smuzhiyun #define CID_MANFID_APACER 0x27
79*4882a593Smuzhiyun #define CID_MANFID_KINGSTON 0x70
80*4882a593Smuzhiyun #define CID_MANFID_HYNIX 0x90
81*4882a593Smuzhiyun #define CID_MANFID_DH 0xAD
82*4882a593Smuzhiyun #define CID_MANFID_NUMONYX 0xFE
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun #define END_FIXUP { NULL }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun #define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \
87*4882a593Smuzhiyun _cis_vendor, _cis_device, \
88*4882a593Smuzhiyun _fixup, _data, _ext_csd_rev) \
89*4882a593Smuzhiyun { \
90*4882a593Smuzhiyun .name = (_name), \
91*4882a593Smuzhiyun .manfid = (_manfid), \
92*4882a593Smuzhiyun .oemid = (_oemid), \
93*4882a593Smuzhiyun .rev_start = (_rev_start), \
94*4882a593Smuzhiyun .rev_end = (_rev_end), \
95*4882a593Smuzhiyun .cis_vendor = (_cis_vendor), \
96*4882a593Smuzhiyun .cis_device = (_cis_device), \
97*4882a593Smuzhiyun .vendor_fixup = (_fixup), \
98*4882a593Smuzhiyun .data = (_data), \
99*4882a593Smuzhiyun .ext_csd_rev = (_ext_csd_rev), \
100*4882a593Smuzhiyun }
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun #define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \
103*4882a593Smuzhiyun _fixup, _data, _ext_csd_rev) \
104*4882a593Smuzhiyun _FIXUP_EXT(_name, _manfid, \
105*4882a593Smuzhiyun _oemid, _rev_start, _rev_end, \
106*4882a593Smuzhiyun SDIO_ANY_ID, SDIO_ANY_ID, \
107*4882a593Smuzhiyun _fixup, _data, _ext_csd_rev) \
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun #define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \
110*4882a593Smuzhiyun MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data, \
111*4882a593Smuzhiyun EXT_CSD_REV_ANY)
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun #define MMC_FIXUP_EXT_CSD_REV(_name, _manfid, _oemid, _fixup, _data, \
114*4882a593Smuzhiyun _ext_csd_rev) \
115*4882a593Smuzhiyun MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data, \
116*4882a593Smuzhiyun _ext_csd_rev)
117*4882a593Smuzhiyun
118*4882a593Smuzhiyun #define SDIO_FIXUP(_vendor, _device, _fixup, _data) \
119*4882a593Smuzhiyun _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \
120*4882a593Smuzhiyun CID_OEMID_ANY, 0, -1ull, \
121*4882a593Smuzhiyun _vendor, _device, \
122*4882a593Smuzhiyun _fixup, _data, EXT_CSD_REV_ANY) \
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun #define cid_rev(hwrev, fwrev, year, month) \
125*4882a593Smuzhiyun (((u64) hwrev) << 40 | \
126*4882a593Smuzhiyun ((u64) fwrev) << 32 | \
127*4882a593Smuzhiyun ((u64) year) << 16 | \
128*4882a593Smuzhiyun ((u64) month))
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun #define cid_rev_card(card) \
131*4882a593Smuzhiyun cid_rev(card->cid.hwrev, \
132*4882a593Smuzhiyun card->cid.fwrev, \
133*4882a593Smuzhiyun card->cid.year, \
134*4882a593Smuzhiyun card->cid.month)
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun /*
137*4882a593Smuzhiyun * Unconditionally quirk add/remove.
138*4882a593Smuzhiyun */
add_quirk(struct mmc_card * card,int data)139*4882a593Smuzhiyun static inline void __maybe_unused add_quirk(struct mmc_card *card, int data)
140*4882a593Smuzhiyun {
141*4882a593Smuzhiyun card->quirks |= data;
142*4882a593Smuzhiyun }
143*4882a593Smuzhiyun
remove_quirk(struct mmc_card * card,int data)144*4882a593Smuzhiyun static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun card->quirks &= ~data;
147*4882a593Smuzhiyun }
148*4882a593Smuzhiyun
add_limit_rate_quirk(struct mmc_card * card,int data)149*4882a593Smuzhiyun static inline void __maybe_unused add_limit_rate_quirk(struct mmc_card *card,
150*4882a593Smuzhiyun int data)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun card->quirk_max_rate = data;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun /*
156*4882a593Smuzhiyun * Quirk add/remove for MMC products.
157*4882a593Smuzhiyun */
add_quirk_mmc(struct mmc_card * card,int data)158*4882a593Smuzhiyun static inline void __maybe_unused add_quirk_mmc(struct mmc_card *card, int data)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun if (mmc_card_mmc(card))
161*4882a593Smuzhiyun card->quirks |= data;
162*4882a593Smuzhiyun }
163*4882a593Smuzhiyun
remove_quirk_mmc(struct mmc_card * card,int data)164*4882a593Smuzhiyun static inline void __maybe_unused remove_quirk_mmc(struct mmc_card *card,
165*4882a593Smuzhiyun int data)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun if (mmc_card_mmc(card))
168*4882a593Smuzhiyun card->quirks &= ~data;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun /*
172*4882a593Smuzhiyun * Quirk add/remove for SD products.
173*4882a593Smuzhiyun */
add_quirk_sd(struct mmc_card * card,int data)174*4882a593Smuzhiyun static inline void __maybe_unused add_quirk_sd(struct mmc_card *card, int data)
175*4882a593Smuzhiyun {
176*4882a593Smuzhiyun if (mmc_card_sd(card))
177*4882a593Smuzhiyun card->quirks |= data;
178*4882a593Smuzhiyun }
179*4882a593Smuzhiyun
remove_quirk_sd(struct mmc_card * card,int data)180*4882a593Smuzhiyun static inline void __maybe_unused remove_quirk_sd(struct mmc_card *card,
181*4882a593Smuzhiyun int data)
182*4882a593Smuzhiyun {
183*4882a593Smuzhiyun if (mmc_card_sd(card))
184*4882a593Smuzhiyun card->quirks &= ~data;
185*4882a593Smuzhiyun }
186*4882a593Smuzhiyun
mmc_card_lenient_fn0(const struct mmc_card * c)187*4882a593Smuzhiyun static inline int mmc_card_lenient_fn0(const struct mmc_card *c)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_LENIENT_FN0;
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
mmc_blksz_for_byte_mode(const struct mmc_card * c)192*4882a593Smuzhiyun static inline int mmc_blksz_for_byte_mode(const struct mmc_card *c)
193*4882a593Smuzhiyun {
194*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
mmc_card_disable_cd(const struct mmc_card * c)197*4882a593Smuzhiyun static inline int mmc_card_disable_cd(const struct mmc_card *c)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_DISABLE_CD;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun
mmc_card_nonstd_func_interface(const struct mmc_card * c)202*4882a593Smuzhiyun static inline int mmc_card_nonstd_func_interface(const struct mmc_card *c)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_NONSTD_FUNC_IF;
205*4882a593Smuzhiyun }
206*4882a593Smuzhiyun
mmc_card_broken_byte_mode_512(const struct mmc_card * c)207*4882a593Smuzhiyun static inline int mmc_card_broken_byte_mode_512(const struct mmc_card *c)
208*4882a593Smuzhiyun {
209*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_BROKEN_BYTE_MODE_512;
210*4882a593Smuzhiyun }
211*4882a593Smuzhiyun
mmc_card_long_read_time(const struct mmc_card * c)212*4882a593Smuzhiyun static inline int mmc_card_long_read_time(const struct mmc_card *c)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_LONG_READ_TIME;
215*4882a593Smuzhiyun }
216*4882a593Smuzhiyun
mmc_card_broken_irq_polling(const struct mmc_card * c)217*4882a593Smuzhiyun static inline int mmc_card_broken_irq_polling(const struct mmc_card *c)
218*4882a593Smuzhiyun {
219*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_BROKEN_IRQ_POLLING;
220*4882a593Smuzhiyun }
221*4882a593Smuzhiyun
mmc_card_broken_hpi(const struct mmc_card * c)222*4882a593Smuzhiyun static inline int mmc_card_broken_hpi(const struct mmc_card *c)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_BROKEN_HPI;
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
mmc_card_broken_sd_discard(const struct mmc_card * c)227*4882a593Smuzhiyun static inline int mmc_card_broken_sd_discard(const struct mmc_card *c)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun return c->quirks & MMC_QUIRK_BROKEN_SD_DISCARD;
230*4882a593Smuzhiyun }
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun #endif
233