aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux/mmc
diff options
context:
space:
mode:
authorAndrei Warkentin <andreiw@motorola.com>2011-04-11 18:02:15 -0400
committerChris Ball <cjb@laptop.org>2011-05-24 21:00:54 -0400
commit32780cd1350e651e68bdf33b7f5b009d21d5b794 (patch)
treee8e86350a3eca20cca098b488e596d2b76ecaea8 /include/linux/mmc
parentf317dfeb86c83d03304a74ce5426a69422b79547 (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.h91
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
15struct mmc_cid { 16struct 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
160void 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
166struct 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 */
235static 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 */
243static 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 {
218extern int mmc_register_driver(struct mmc_driver *); 304extern int mmc_register_driver(struct mmc_driver *);
219extern void mmc_unregister_driver(struct mmc_driver *); 305extern void mmc_unregister_driver(struct mmc_driver *);
220 306
307extern void mmc_fixup_device(struct mmc_card *card,
308 const struct mmc_fixup *table);
309
221#endif 310#endif