diff options
author | Andrei Warkentin <andreiw@motorola.com> | 2011-04-11 18:02:15 -0400 |
---|---|---|
committer | Chris Ball <cjb@laptop.org> | 2011-05-24 21:00:54 -0400 |
commit | 32780cd1350e651e68bdf33b7f5b009d21d5b794 (patch) | |
tree | e8e86350a3eca20cca098b488e596d2b76ecaea8 /include/linux/mmc | |
parent | f317dfeb86c83d03304a74ce5426a69422b79547 (diff) |
mmc: quirks: Extends card quirks with MMC/SD quirks matching the CID.
The current mechanism is SDIO-only. This allows us to create
function-specific quirks, without creating messy Kconfig dependencies,
or polluting core/ with function-specific code.
Signed-off-by: Andrei Warkentin <andreiw@motorola.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Chris Ball <cjb@laptop.org>
Diffstat (limited to 'include/linux/mmc')
-rw-r--r-- | include/linux/mmc/card.h | 91 |
1 files changed, 90 insertions, 1 deletions
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h index 2a7e54970c93..c6513175f7f1 100644 --- a/include/linux/mmc/card.h +++ b/include/linux/mmc/card.h | |||
@@ -11,6 +11,7 @@ | |||
11 | #define LINUX_MMC_CARD_H | 11 | #define LINUX_MMC_CARD_H |
12 | 12 | ||
13 | #include <linux/mmc/core.h> | 13 | #include <linux/mmc/core.h> |
14 | #include <linux/mod_devicetable.h> | ||
14 | 15 | ||
15 | struct mmc_cid { | 16 | struct mmc_cid { |
16 | unsigned int manfid; | 17 | unsigned int manfid; |
@@ -157,7 +158,92 @@ struct mmc_card { | |||
157 | struct dentry *debugfs_root; | 158 | struct dentry *debugfs_root; |
158 | }; | 159 | }; |
159 | 160 | ||
160 | void mmc_fixup_device(struct mmc_card *dev); | 161 | /* |
162 | * The world is not perfect and supplies us with broken mmc/sdio devices. | ||
163 | * For at least some of these bugs we need a work-around. | ||
164 | */ | ||
165 | |||
166 | struct mmc_fixup { | ||
167 | /* CID-specific fields. */ | ||
168 | const char *name; | ||
169 | |||
170 | /* Valid revision range */ | ||
171 | u64 rev_start, rev_end; | ||
172 | |||
173 | unsigned int manfid; | ||
174 | unsigned short oemid; | ||
175 | |||
176 | /* SDIO-specfic fields. You can use SDIO_ANY_ID here of course */ | ||
177 | u16 cis_vendor, cis_device; | ||
178 | |||
179 | void (*vendor_fixup)(struct mmc_card *card, int data); | ||
180 | int data; | ||
181 | }; | ||
182 | |||
183 | #define CID_MANFID_ANY (-1ul) | ||
184 | #define CID_OEMID_ANY ((unsigned short) -1) | ||
185 | #define CID_NAME_ANY (NULL) | ||
186 | |||
187 | #define END_FIXUP { 0 } | ||
188 | |||
189 | #define _FIXUP_EXT(_name, _manfid, _oemid, _rev_start, _rev_end, \ | ||
190 | _cis_vendor, _cis_device, \ | ||
191 | _fixup, _data) \ | ||
192 | { \ | ||
193 | .name = (_name), \ | ||
194 | .manfid = (_manfid), \ | ||
195 | .oemid = (_oemid), \ | ||
196 | .rev_start = (_rev_start), \ | ||
197 | .rev_end = (_rev_end), \ | ||
198 | .cis_vendor = (_cis_vendor), \ | ||
199 | .cis_device = (_cis_device), \ | ||
200 | .vendor_fixup = (_fixup), \ | ||
201 | .data = (_data), \ | ||
202 | } | ||
203 | |||
204 | #define MMC_FIXUP_REV(_name, _manfid, _oemid, _rev_start, _rev_end, \ | ||
205 | _fixup, _data) \ | ||
206 | _FIXUP_EXT(_name, _manfid, \ | ||
207 | _oemid, _rev_start, _rev_end, \ | ||
208 | SDIO_ANY_ID, SDIO_ANY_ID, \ | ||
209 | _fixup, _data) \ | ||
210 | |||
211 | #define MMC_FIXUP(_name, _manfid, _oemid, _fixup, _data) \ | ||
212 | MMC_FIXUP_REV(_name, _manfid, _oemid, 0, -1ull, _fixup, _data) | ||
213 | |||
214 | #define SDIO_FIXUP(_vendor, _device, _fixup, _data) \ | ||
215 | _FIXUP_EXT(CID_NAME_ANY, CID_MANFID_ANY, \ | ||
216 | CID_OEMID_ANY, 0, -1ull, \ | ||
217 | _vendor, _device, \ | ||
218 | _fixup, _data) \ | ||
219 | |||
220 | #define cid_rev(hwrev, fwrev, year, month) \ | ||
221 | (((u64) hwrev) << 40 | \ | ||
222 | ((u64) fwrev) << 32 | \ | ||
223 | ((u64) year) << 16 | \ | ||
224 | ((u64) month)) | ||
225 | |||
226 | #define cid_rev_card(card) \ | ||
227 | cid_rev(card->cid.hwrev, \ | ||
228 | card->cid.fwrev, \ | ||
229 | card->cid.year, \ | ||
230 | card->cid.month) | ||
231 | |||
232 | /* | ||
233 | * This hook just adds a quirk unconditionally. | ||
234 | */ | ||
235 | static inline void __maybe_unused add_quirk(struct mmc_card *card, int data) | ||
236 | { | ||
237 | card->quirks |= data; | ||
238 | } | ||
239 | |||
240 | /* | ||
241 | * This hook just removes a quirk unconditionally. | ||
242 | */ | ||
243 | static inline void __maybe_unused remove_quirk(struct mmc_card *card, int data) | ||
244 | { | ||
245 | card->quirks &= ~data; | ||
246 | } | ||
161 | 247 | ||
162 | #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) | 248 | #define mmc_card_mmc(c) ((c)->type == MMC_TYPE_MMC) |
163 | #define mmc_card_sd(c) ((c)->type == MMC_TYPE_SD) | 249 | #define mmc_card_sd(c) ((c)->type == MMC_TYPE_SD) |
@@ -218,4 +304,7 @@ struct mmc_driver { | |||
218 | extern int mmc_register_driver(struct mmc_driver *); | 304 | extern int mmc_register_driver(struct mmc_driver *); |
219 | extern void mmc_unregister_driver(struct mmc_driver *); | 305 | extern void mmc_unregister_driver(struct mmc_driver *); |
220 | 306 | ||
307 | extern void mmc_fixup_device(struct mmc_card *card, | ||
308 | const struct mmc_fixup *table); | ||
309 | |||
221 | #endif | 310 | #endif |