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 | |
| 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')
| -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 |
