diff options
author | Pierre Ossman <drzeus@drzeus.cx> | 2008-03-23 14:33:23 -0400 |
---|---|---|
committer | Pierre Ossman <drzeus@drzeus.cx> | 2008-07-15 08:14:39 -0400 |
commit | 22606405894a3ca5796eb4454a4b83af611fd201 (patch) | |
tree | 00349f16c75184bd7bd11bd22e87176883f65805 /drivers/mmc/host/sdhci-pci.c | |
parent | 3815a0ebab678c20d0d9c66af5ee9e68807b6681 (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/mmc/host/sdhci-pci.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 129 |
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 | ||
41 | static const struct pci_device_id pci_ids[] __devinitdata = { | 41 | struct sdhci_pci_chip; |
42 | { | 42 | |
43 | .vendor = PCI_VENDOR_ID_RICOH, | 43 | struct 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 | |
49 | struct sdhci_pci_slot { | ||
50 | struct sdhci_pci_chip *chip; | ||
51 | struct sdhci_host *host; | ||
49 | 52 | ||
53 | int pci_bar; | ||
54 | }; | ||
55 | |||
56 | struct 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 | |||
73 | static 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 | |||
84 | static const struct sdhci_pci_fixes sdhci_ricoh = { | ||
85 | .probe = ricoh_probe, | ||
86 | }; | ||
87 | |||
88 | static const struct sdhci_pci_fixes sdhci_ene_712 = { | ||
89 | .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
90 | SDHCI_QUIRK_BROKEN_DMA, | ||
91 | }; | ||
92 | |||
93 | static 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 | |||
99 | static const struct sdhci_pci_fixes sdhci_cafe = { | ||
100 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | ||
101 | SDHCI_QUIRK_INCR_TIMEOUT_CONTROL, | ||
102 | }; | ||
103 | |||
104 | static 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 | |||
110 | static 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 | ||
122 | MODULE_DEVICE_TABLE(pci, pci_ids); | 174 | MODULE_DEVICE_TABLE(pci, pci_ids); |
123 | 175 | ||
124 | struct sdhci_pci_chip; | ||
125 | |||
126 | struct sdhci_pci_slot { | ||
127 | struct sdhci_pci_chip *chip; | ||
128 | struct sdhci_host *host; | ||
129 | |||
130 | int pci_bar; | ||
131 | }; | ||
132 | |||
133 | struct 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)) { |