aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPierre Ossman <drzeus@drzeus.cx>2008-03-23 14:33:23 -0400
committerPierre Ossman <drzeus@drzeus.cx>2008-07-15 08:14:39 -0400
commit22606405894a3ca5796eb4454a4b83af611fd201 (patch)
tree00349f16c75184bd7bd11bd22e87176883f65805 /drivers
parent3815a0ebab678c20d0d9c66af5ee9e68807b6681 (diff)
sdhci: more complex quirks handling
Extend the quirks handling in the PCI driver to be able to have callbacks and not just flags. Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mmc/host/sdhci-pci.c129
1 files changed, 86 insertions, 43 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c
index 51798ec56446..5094fe805764 100644
--- a/drivers/mmc/host/sdhci-pci.c
+++ b/drivers/mmc/host/sdhci-pci.c
@@ -38,21 +38,82 @@
38 38
39#define MAX_SLOTS 8 39#define MAX_SLOTS 8
40 40
41static const struct pci_device_id pci_ids[] __devinitdata = { 41struct sdhci_pci_chip;
42 { 42
43 .vendor = PCI_VENDOR_ID_RICOH, 43struct sdhci_pci_fixes {
44 .device = PCI_DEVICE_ID_RICOH_R5C822, 44 unsigned int quirks;
45 .subvendor = PCI_VENDOR_ID_IBM, 45
46 .subdevice = PCI_ANY_ID, 46 int (*probe)(struct sdhci_pci_chip*);
47 .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET, 47};
48 }, 48
49struct sdhci_pci_slot {
50 struct sdhci_pci_chip *chip;
51 struct sdhci_host *host;
49 52
53 int pci_bar;
54};
55
56struct sdhci_pci_chip {
57 struct pci_dev *pdev;
58
59 unsigned int quirks;
60 const struct sdhci_pci_fixes *fixes;
61
62 int num_slots; /* Slots on controller */
63 struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */
64};
65
66
67/*****************************************************************************\
68 * *
69 * Hardware specific quirk handling *
70 * *
71\*****************************************************************************/
72
73static int ricoh_probe(struct sdhci_pci_chip *chip)
74{
75 if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
76 chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET;
77
78 if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)
79 chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET;
80
81 return 0;
82}
83
84static const struct sdhci_pci_fixes sdhci_ricoh = {
85 .probe = ricoh_probe,
86};
87
88static const struct sdhci_pci_fixes sdhci_ene_712 = {
89 .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
90 SDHCI_QUIRK_BROKEN_DMA,
91};
92
93static const struct sdhci_pci_fixes sdhci_ene_714 = {
94 .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
95 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
96 SDHCI_QUIRK_BROKEN_DMA,
97};
98
99static const struct sdhci_pci_fixes sdhci_cafe = {
100 .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
101 SDHCI_QUIRK_INCR_TIMEOUT_CONTROL,
102};
103
104static const struct sdhci_pci_fixes sdhci_jmicron = {
105 .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
106 SDHCI_QUIRK_32BIT_DMA_SIZE |
107 SDHCI_QUIRK_RESET_AFTER_REQUEST,
108};
109
110static const struct pci_device_id pci_ids[] __devinitdata = {
50 { 111 {
51 .vendor = PCI_VENDOR_ID_RICOH, 112 .vendor = PCI_VENDOR_ID_RICOH,
52 .device = PCI_DEVICE_ID_RICOH_R5C822, 113 .device = PCI_DEVICE_ID_RICOH_R5C822,
53 .subvendor = PCI_VENDOR_ID_SAMSUNG, 114 .subvendor = PCI_ANY_ID,
54 .subdevice = PCI_ANY_ID, 115 .subdevice = PCI_ANY_ID,
55 .driver_data = SDHCI_QUIRK_NO_CARD_NO_RESET, 116 .driver_data = (kernel_ulong_t)&sdhci_ricoh,
56 }, 117 },
57 118
58 { 119 {
@@ -60,8 +121,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
60 .device = PCI_DEVICE_ID_ENE_CB712_SD, 121 .device = PCI_DEVICE_ID_ENE_CB712_SD,
61 .subvendor = PCI_ANY_ID, 122 .subvendor = PCI_ANY_ID,
62 .subdevice = PCI_ANY_ID, 123 .subdevice = PCI_ANY_ID,
63 .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | 124 .driver_data = (kernel_ulong_t)&sdhci_ene_712,
64 SDHCI_QUIRK_BROKEN_DMA,
65 }, 125 },
66 126
67 { 127 {
@@ -69,8 +129,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
69 .device = PCI_DEVICE_ID_ENE_CB712_SD_2, 129 .device = PCI_DEVICE_ID_ENE_CB712_SD_2,
70 .subvendor = PCI_ANY_ID, 130 .subvendor = PCI_ANY_ID,
71 .subdevice = PCI_ANY_ID, 131 .subdevice = PCI_ANY_ID,
72 .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | 132 .driver_data = (kernel_ulong_t)&sdhci_ene_712,
73 SDHCI_QUIRK_BROKEN_DMA,
74 }, 133 },
75 134
76 { 135 {
@@ -78,9 +137,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
78 .device = PCI_DEVICE_ID_ENE_CB714_SD, 137 .device = PCI_DEVICE_ID_ENE_CB714_SD,
79 .subvendor = PCI_ANY_ID, 138 .subvendor = PCI_ANY_ID,
80 .subdevice = PCI_ANY_ID, 139 .subdevice = PCI_ANY_ID,
81 .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | 140 .driver_data = (kernel_ulong_t)&sdhci_ene_714,
82 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
83 SDHCI_QUIRK_BROKEN_DMA,
84 }, 141 },
85 142
86 { 143 {
@@ -88,9 +145,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
88 .device = PCI_DEVICE_ID_ENE_CB714_SD_2, 145 .device = PCI_DEVICE_ID_ENE_CB714_SD_2,
89 .subvendor = PCI_ANY_ID, 146 .subvendor = PCI_ANY_ID,
90 .subdevice = PCI_ANY_ID, 147 .subdevice = PCI_ANY_ID,
91 .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | 148 .driver_data = (kernel_ulong_t)&sdhci_ene_714,
92 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
93 SDHCI_QUIRK_BROKEN_DMA,
94 }, 149 },
95 150
96 { 151 {
@@ -98,8 +153,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
98 .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, 153 .device = PCI_DEVICE_ID_MARVELL_CAFE_SD,
99 .subvendor = PCI_ANY_ID, 154 .subvendor = PCI_ANY_ID,
100 .subdevice = PCI_ANY_ID, 155 .subdevice = PCI_ANY_ID,
101 .driver_data = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | 156 .driver_data = (kernel_ulong_t)&sdhci_cafe,
102 SDHCI_QUIRK_INCR_TIMEOUT_CONTROL,
103 }, 157 },
104 158
105 { 159 {
@@ -107,9 +161,7 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
107 .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD, 161 .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
108 .subvendor = PCI_ANY_ID, 162 .subvendor = PCI_ANY_ID,
109 .subdevice = PCI_ANY_ID, 163 .subdevice = PCI_ANY_ID,
110 .driver_data = SDHCI_QUIRK_32BIT_DMA_ADDR | 164 .driver_data = (kernel_ulong_t)&sdhci_jmicron,
111 SDHCI_QUIRK_32BIT_DMA_SIZE |
112 SDHCI_QUIRK_RESET_AFTER_REQUEST,
113 }, 165 },
114 166
115 { /* Generic SD host controller */ 167 { /* Generic SD host controller */
@@ -121,23 +173,6 @@ static const struct pci_device_id pci_ids[] __devinitdata = {
121 173
122MODULE_DEVICE_TABLE(pci, pci_ids); 174MODULE_DEVICE_TABLE(pci, pci_ids);
123 175
124struct sdhci_pci_chip;
125
126struct sdhci_pci_slot {
127 struct sdhci_pci_chip *chip;
128 struct sdhci_host *host;
129
130 int pci_bar;
131};
132
133struct sdhci_pci_chip {
134 struct pci_dev *pdev;
135 unsigned int quirks;
136
137 int num_slots; /* Slots on controller */
138 struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */
139};
140
141/*****************************************************************************\ 176/*****************************************************************************\
142 * * 177 * *
143 * SDHCI core callbacks * 178 * SDHCI core callbacks *
@@ -389,11 +424,19 @@ static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
389 } 424 }
390 425
391 chip->pdev = pdev; 426 chip->pdev = pdev;
392 chip->quirks = ent->driver_data; 427 chip->fixes = (const struct sdhci_pci_fixes*)ent->driver_data;
428 if (chip->fixes)
429 chip->quirks = chip->fixes->quirks;
393 chip->num_slots = slots; 430 chip->num_slots = slots;
394 431
395 pci_set_drvdata(pdev, chip); 432 pci_set_drvdata(pdev, chip);
396 433
434 if (chip->fixes && chip->fixes->probe) {
435 ret = chip->fixes->probe(chip);
436 if (ret)
437 goto free;
438 }
439
397 for (i = 0;i < slots;i++) { 440 for (i = 0;i < slots;i++) {
398 slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); 441 slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
399 if (IS_ERR(slot)) { 442 if (IS_ERR(slot)) {