quirks.c 2.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. /*
  2. * This file contains work-arounds for many known sdio hardware
  3. * bugs.
  4. *
  5. * Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com>
  6. * Inspired from pci fixup code:
  7. * Copyright (c) 1999 Martin Mares <mj@ucw.cz>
  8. *
  9. */
  10. #include <linux/types.h>
  11. #include <linux/kernel.h>
  12. #include <linux/mmc/card.h>
  13. #include <linux/mod_devicetable.h>
  14. /*
  15. * The world is not perfect and supplies us with broken mmc/sdio devices.
  16. * For at least a part of these bugs we need a work-around
  17. */
  18. struct mmc_fixup {
  19. u16 vendor, device; /* You can use SDIO_ANY_ID here of course */
  20. void (*vendor_fixup)(struct mmc_card *card, int data);
  21. int data;
  22. };
  23. /*
  24. * This hook just adds a quirk unconditionnally
  25. */
  26. static void __maybe_unused add_quirk(struct mmc_card *card, int data)
  27. {
  28. card->quirks |= data;
  29. }
  30. /*
  31. * This hook just removes a quirk unconditionnally
  32. */
  33. static void __maybe_unused remove_quirk(struct mmc_card *card, int data)
  34. {
  35. card->quirks &= ~data;
  36. }
  37. /*
  38. * This hook just adds a quirk for all sdio devices
  39. */
  40. static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
  41. {
  42. if (mmc_card_sdio(card))
  43. card->quirks |= data;
  44. }
  45. #ifndef SDIO_VENDOR_ID_TI
  46. #define SDIO_VENDOR_ID_TI 0x0097
  47. #endif
  48. #ifndef SDIO_DEVICE_ID_TI_WL1271
  49. #define SDIO_DEVICE_ID_TI_WL1271 0x4076
  50. #endif
  51. static const struct mmc_fixup mmc_fixup_methods[] = {
  52. /* by default sdio devices are considered CLK_GATING broken */
  53. /* good cards will be whitelisted as they are tested */
  54. { SDIO_ANY_ID, SDIO_ANY_ID,
  55. add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING },
  56. { SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
  57. remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING },
  58. { 0 }
  59. };
  60. void mmc_fixup_device(struct mmc_card *card)
  61. {
  62. const struct mmc_fixup *f;
  63. for (f = mmc_fixup_methods; f->vendor_fixup; f++) {
  64. if ((f->vendor == card->cis.vendor
  65. || f->vendor == (u16) SDIO_ANY_ID) &&
  66. (f->device == card->cis.device
  67. || f->device == (u16) SDIO_ANY_ID)) {
  68. dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
  69. f->vendor_fixup(card, f->data);
  70. }
  71. }
  72. }
  73. EXPORT_SYMBOL(mmc_fixup_device);