diff options
-rw-r--r-- | drivers/mmc/host/Kconfig | 19 | ||||
-rw-r--r-- | drivers/mmc/host/Makefile | 1 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 486 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 499 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 82 |
5 files changed, 651 insertions, 436 deletions
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index dead61754ad7..f9cbcb891e99 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -26,18 +26,31 @@ config MMC_PXA | |||
26 | 26 | ||
27 | config MMC_SDHCI | 27 | config MMC_SDHCI |
28 | tristate "Secure Digital Host Controller Interface support" | 28 | tristate "Secure Digital Host Controller Interface support" |
29 | depends on PCI | 29 | depends on HAS_DMA |
30 | help | 30 | help |
31 | This select the generic Secure Digital Host Controller Interface. | 31 | This selects the generic Secure Digital Host Controller Interface. |
32 | It is used by manufacturers such as Texas Instruments(R), Ricoh(R) | 32 | It is used by manufacturers such as Texas Instruments(R), Ricoh(R) |
33 | and Toshiba(R). Most controllers found in laptops are of this type. | 33 | and Toshiba(R). Most controllers found in laptops are of this type. |
34 | |||
35 | If you have a controller with this interface, say Y or M here. You | ||
36 | also need to enable an appropriate bus interface. | ||
37 | |||
38 | If unsure, say N. | ||
39 | |||
40 | config MMC_SDHCI_PCI | ||
41 | tristate "SDHCI support on PCI bus" | ||
42 | depends on MMC_SDHCI && PCI | ||
43 | help | ||
44 | This selects the PCI Secure Digital Host Controller Interface. | ||
45 | Most controllers found today are PCI devices. | ||
46 | |||
34 | If you have a controller with this interface, say Y or M here. | 47 | If you have a controller with this interface, say Y or M here. |
35 | 48 | ||
36 | If unsure, say N. | 49 | If unsure, say N. |
37 | 50 | ||
38 | config MMC_RICOH_MMC | 51 | config MMC_RICOH_MMC |
39 | tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)" | 52 | tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)" |
40 | depends on PCI && EXPERIMENTAL && MMC_SDHCI | 53 | depends on MMC_SDHCI_PCI |
41 | help | 54 | help |
42 | This selects the disabler for the Ricoh MMC Controller. This | 55 | This selects the disabler for the Ricoh MMC Controller. This |
43 | proprietary controller is unnecessary because the SDHCI driver | 56 | proprietary controller is unnecessary because the SDHCI driver |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 3877c87e6da2..3027250b8555 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_MMC_ARMMMCI) += mmci.o | |||
10 | obj-$(CONFIG_MMC_PXA) += pxamci.o | 10 | obj-$(CONFIG_MMC_PXA) += pxamci.o |
11 | obj-$(CONFIG_MMC_IMX) += imxmmc.o | 11 | obj-$(CONFIG_MMC_IMX) += imxmmc.o |
12 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o | 12 | obj-$(CONFIG_MMC_SDHCI) += sdhci.o |
13 | obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o | ||
13 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o | 14 | obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o |
14 | obj-$(CONFIG_MMC_WBSD) += wbsd.o | 15 | obj-$(CONFIG_MMC_WBSD) += wbsd.o |
15 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o | 16 | obj-$(CONFIG_MMC_AU1X) += au1xmmc.o |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c new file mode 100644 index 000000000000..2a3dd6cc7bf7 --- /dev/null +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -0,0 +1,486 @@ | |||
1 | /* linux/drivers/mmc/host/sdhci-pci.c - SDHCI on PCI bus interface | ||
2 | * | ||
3 | * Copyright (C) 2005-2008 Pierre Ossman, All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License as published by | ||
7 | * the Free Software Foundation; either version 2 of the License, or (at | ||
8 | * your option) any later version. | ||
9 | * | ||
10 | * Thanks to the following companies for their support: | ||
11 | * | ||
12 | * - JMicron (hardware and technical support) | ||
13 | */ | ||
14 | |||
15 | #include <linux/delay.h> | ||
16 | #include <linux/highmem.h> | ||
17 | #include <linux/pci.h> | ||
18 | #include <linux/dma-mapping.h> | ||
19 | |||
20 | #include <linux/mmc/host.h> | ||
21 | |||
22 | #include <asm/scatterlist.h> | ||
23 | #include <asm/io.h> | ||
24 | |||
25 | #include "sdhci.h" | ||
26 | |||
27 | /* | ||
28 | * PCI registers | ||
29 | */ | ||
30 | |||
31 | #define PCI_SDHCI_IFPIO 0x00 | ||
32 | #define PCI_SDHCI_IFDMA 0x01 | ||
33 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
34 | |||
35 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
36 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
37 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
38 | |||
39 | #define MAX_SLOTS 8 | ||
40 | |||
41 | static const struct pci_device_id pci_ids[] __devinitdata = { | ||
42 | { | ||
43 | .vendor = PCI_VENDOR_ID_RICOH, | ||
44 | .device = PCI_DEVICE_ID_RICOH_R5C822, | ||
45 | .subvendor = PCI_VENDOR_ID_IBM, | ||
46 | .subdevice = PCI_ANY_ID, | ||
47 | .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET | | ||
48 | SDHCI_QUIRK_FORCE_DMA, | ||
49 | }, | ||
50 | |||
51 | { | ||
52 | .vendor = PCI_VENDOR_ID_RICOH, | ||
53 | .device = PCI_DEVICE_ID_RICOH_R5C822, | ||
54 | .subvendor = PCI_VENDOR_ID_SAMSUNG, | ||
55 | .subdevice = PCI_ANY_ID, | ||
56 | .driver_data = SDHCI_QUIRK_FORCE_DMA | | ||
57 | SDHCI_QUIRK_NO_CARD_NO_RESET, | ||
58 | }, | ||
59 | |||
60 | { | ||
61 | .vendor = PCI_VENDOR_ID_RICOH, | ||
62 | .device = PCI_DEVICE_ID_RICOH_R5C822, | ||
63 | .subvendor = PCI_ANY_ID, | ||
64 | .subdevice = PCI_ANY_ID, | ||
65 | .driver_data = SDHCI_QUIRK_FORCE_DMA, | ||
66 | }, | ||
67 | |||
68 | { | ||
69 | .vendor = PCI_VENDOR_ID_TI, | ||
70 | .device = PCI_DEVICE_ID_TI_XX21_XX11_SD, | ||
71 | .subvendor = PCI_ANY_ID, | ||
72 | .subdevice = PCI_ANY_ID, | ||
73 | .driver_data = SDHCI_QUIRK_FORCE_DMA, | ||
74 | }, | ||
75 | |||
76 | { | ||
77 | .vendor = PCI_VENDOR_ID_ENE, | ||
78 | .device = PCI_DEVICE_ID_ENE_CB712_SD, | ||
79 | .subvendor = PCI_ANY_ID, | ||
80 | .subdevice = PCI_ANY_ID, | ||
81 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
82 | SDHCI_QUIRK_BROKEN_DMA, | ||
83 | }, | ||
84 | |||
85 | { | ||
86 | .vendor = PCI_VENDOR_ID_ENE, | ||
87 | .device = PCI_DEVICE_ID_ENE_CB712_SD_2, | ||
88 | .subvendor = PCI_ANY_ID, | ||
89 | .subdevice = PCI_ANY_ID, | ||
90 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
91 | SDHCI_QUIRK_BROKEN_DMA, | ||
92 | }, | ||
93 | |||
94 | { | ||
95 | .vendor = PCI_VENDOR_ID_ENE, | ||
96 | .device = PCI_DEVICE_ID_ENE_CB714_SD, | ||
97 | .subvendor = PCI_ANY_ID, | ||
98 | .subdevice = PCI_ANY_ID, | ||
99 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
100 | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | | ||
101 | SDHCI_QUIRK_BROKEN_DMA, | ||
102 | }, | ||
103 | |||
104 | { | ||
105 | .vendor = PCI_VENDOR_ID_ENE, | ||
106 | .device = PCI_DEVICE_ID_ENE_CB714_SD_2, | ||
107 | .subvendor = PCI_ANY_ID, | ||
108 | .subdevice = PCI_ANY_ID, | ||
109 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
110 | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | | ||
111 | SDHCI_QUIRK_BROKEN_DMA, | ||
112 | }, | ||
113 | |||
114 | { | ||
115 | .vendor = PCI_VENDOR_ID_MARVELL, | ||
116 | .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, | ||
117 | .subvendor = PCI_ANY_ID, | ||
118 | .subdevice = PCI_ANY_ID, | ||
119 | .driver_data = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | ||
120 | SDHCI_QUIRK_INCR_TIMEOUT_CONTROL, | ||
121 | }, | ||
122 | |||
123 | { | ||
124 | .vendor = PCI_VENDOR_ID_JMICRON, | ||
125 | .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD, | ||
126 | .subvendor = PCI_ANY_ID, | ||
127 | .subdevice = PCI_ANY_ID, | ||
128 | .driver_data = SDHCI_QUIRK_32BIT_DMA_ADDR | | ||
129 | SDHCI_QUIRK_32BIT_DMA_SIZE | | ||
130 | SDHCI_QUIRK_RESET_AFTER_REQUEST, | ||
131 | }, | ||
132 | |||
133 | { /* Generic SD host controller */ | ||
134 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | ||
135 | }, | ||
136 | |||
137 | { /* end: all zeroes */ }, | ||
138 | }; | ||
139 | |||
140 | MODULE_DEVICE_TABLE(pci, pci_ids); | ||
141 | |||
142 | struct sdhci_pci_chip; | ||
143 | |||
144 | struct sdhci_pci_slot { | ||
145 | struct sdhci_pci_chip *chip; | ||
146 | struct sdhci_host *host; | ||
147 | |||
148 | int pci_bar; | ||
149 | }; | ||
150 | |||
151 | struct sdhci_pci_chip { | ||
152 | struct pci_dev *pdev; | ||
153 | unsigned int quirks; | ||
154 | |||
155 | int num_slots; /* Slots on controller */ | ||
156 | struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ | ||
157 | }; | ||
158 | |||
159 | /*****************************************************************************\ | ||
160 | * * | ||
161 | * SDHCI core callbacks * | ||
162 | * * | ||
163 | \*****************************************************************************/ | ||
164 | |||
165 | static int sdhci_pci_enable_dma(struct sdhci_host *host) | ||
166 | { | ||
167 | struct sdhci_pci_slot *slot; | ||
168 | struct pci_dev *pdev; | ||
169 | int ret; | ||
170 | |||
171 | slot = sdhci_priv(host); | ||
172 | pdev = slot->chip->pdev; | ||
173 | |||
174 | if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) && | ||
175 | ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) && | ||
176 | (host->flags & SDHCI_USE_DMA)) { | ||
177 | dev_warn(&pdev->dev, "Will use DMA mode even though HW " | ||
178 | "doesn't fully claim to support it.\n"); | ||
179 | } | ||
180 | |||
181 | ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | |||
185 | pci_set_master(pdev); | ||
186 | |||
187 | return 0; | ||
188 | } | ||
189 | |||
190 | static struct sdhci_ops sdhci_pci_ops = { | ||
191 | .enable_dma = sdhci_pci_enable_dma, | ||
192 | }; | ||
193 | |||
194 | /*****************************************************************************\ | ||
195 | * * | ||
196 | * Suspend/resume * | ||
197 | * * | ||
198 | \*****************************************************************************/ | ||
199 | |||
200 | #ifdef CONFIG_PM | ||
201 | |||
202 | static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state) | ||
203 | { | ||
204 | struct sdhci_pci_chip *chip; | ||
205 | struct sdhci_pci_slot *slot; | ||
206 | int i, ret; | ||
207 | |||
208 | chip = pci_get_drvdata(pdev); | ||
209 | if (!chip) | ||
210 | return 0; | ||
211 | |||
212 | for (i = 0;i < chip->num_slots;i++) { | ||
213 | slot = chip->slots[i]; | ||
214 | if (!slot) | ||
215 | continue; | ||
216 | |||
217 | ret = sdhci_suspend_host(slot->host, state); | ||
218 | |||
219 | if (ret) { | ||
220 | for (i--;i >= 0;i--) | ||
221 | sdhci_resume_host(chip->slots[i]->host); | ||
222 | return ret; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | pci_save_state(pdev); | ||
227 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
228 | pci_disable_device(pdev); | ||
229 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static int sdhci_pci_resume (struct pci_dev *pdev) | ||
235 | { | ||
236 | struct sdhci_pci_chip *chip; | ||
237 | struct sdhci_pci_slot *slot; | ||
238 | int i, ret; | ||
239 | |||
240 | chip = pci_get_drvdata(pdev); | ||
241 | if (!chip) | ||
242 | return 0; | ||
243 | |||
244 | pci_set_power_state(pdev, PCI_D0); | ||
245 | pci_restore_state(pdev); | ||
246 | ret = pci_enable_device(pdev); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | for (i = 0;i < chip->num_slots;i++) { | ||
251 | slot = chip->slots[i]; | ||
252 | if (!slot) | ||
253 | continue; | ||
254 | |||
255 | ret = sdhci_resume_host(slot->host); | ||
256 | if (ret) | ||
257 | return ret; | ||
258 | } | ||
259 | |||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | #else /* CONFIG_PM */ | ||
264 | |||
265 | #define sdhci_pci_suspend NULL | ||
266 | #define sdhci_pci_resume NULL | ||
267 | |||
268 | #endif /* CONFIG_PM */ | ||
269 | |||
270 | /*****************************************************************************\ | ||
271 | * * | ||
272 | * Device probing/removal * | ||
273 | * * | ||
274 | \*****************************************************************************/ | ||
275 | |||
276 | static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot( | ||
277 | struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar) | ||
278 | { | ||
279 | struct sdhci_pci_slot *slot; | ||
280 | struct sdhci_host *host; | ||
281 | |||
282 | resource_size_t addr; | ||
283 | |||
284 | int ret; | ||
285 | |||
286 | if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) { | ||
287 | dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar); | ||
288 | return ERR_PTR(-ENODEV); | ||
289 | } | ||
290 | |||
291 | if (pci_resource_len(pdev, bar) != 0x100) { | ||
292 | dev_err(&pdev->dev, "Invalid iomem size. You may " | ||
293 | "experience problems.\n"); | ||
294 | } | ||
295 | |||
296 | if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { | ||
297 | dev_err(&pdev->dev, "Vendor specific interface. Aborting.\n"); | ||
298 | return ERR_PTR(-ENODEV); | ||
299 | } | ||
300 | |||
301 | if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) { | ||
302 | dev_err(&pdev->dev, "Unknown interface. Aborting.\n"); | ||
303 | return ERR_PTR(-ENODEV); | ||
304 | } | ||
305 | |||
306 | host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot)); | ||
307 | if (IS_ERR(host)) { | ||
308 | ret = PTR_ERR(host); | ||
309 | goto unmap; | ||
310 | } | ||
311 | |||
312 | slot = sdhci_priv(host); | ||
313 | |||
314 | slot->chip = chip; | ||
315 | slot->host = host; | ||
316 | slot->pci_bar = bar; | ||
317 | |||
318 | host->hw_name = "PCI"; | ||
319 | host->ops = &sdhci_pci_ops; | ||
320 | host->quirks = chip->quirks; | ||
321 | |||
322 | host->irq = pdev->irq; | ||
323 | |||
324 | ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc)); | ||
325 | if (ret) { | ||
326 | dev_err(&pdev->dev, "cannot request region\n"); | ||
327 | return ERR_PTR(ret); | ||
328 | } | ||
329 | |||
330 | addr = pci_resource_start(pdev, bar); | ||
331 | host->ioaddr = ioremap_nocache(addr, pci_resource_len(pdev, bar)); | ||
332 | if (!host->ioaddr) { | ||
333 | dev_err(&pdev->dev, "failed to remap registers\n"); | ||
334 | goto release; | ||
335 | } | ||
336 | |||
337 | ret = sdhci_add_host(host); | ||
338 | if (ret) | ||
339 | goto unmap; | ||
340 | |||
341 | return slot; | ||
342 | |||
343 | unmap: | ||
344 | iounmap(host->ioaddr); | ||
345 | |||
346 | release: | ||
347 | pci_release_region(pdev, bar); | ||
348 | sdhci_free_host(host); | ||
349 | |||
350 | return ERR_PTR(ret); | ||
351 | } | ||
352 | |||
353 | static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot) | ||
354 | { | ||
355 | sdhci_remove_host(slot->host); | ||
356 | pci_release_region(slot->chip->pdev, slot->pci_bar); | ||
357 | sdhci_free_host(slot->host); | ||
358 | } | ||
359 | |||
360 | static int __devinit sdhci_pci_probe(struct pci_dev *pdev, | ||
361 | const struct pci_device_id *ent) | ||
362 | { | ||
363 | struct sdhci_pci_chip *chip; | ||
364 | struct sdhci_pci_slot *slot; | ||
365 | |||
366 | u8 slots, rev, first_bar; | ||
367 | int ret, i; | ||
368 | |||
369 | BUG_ON(pdev == NULL); | ||
370 | BUG_ON(ent == NULL); | ||
371 | |||
372 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev); | ||
373 | |||
374 | dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n", | ||
375 | (int)pdev->vendor, (int)pdev->device, (int)rev); | ||
376 | |||
377 | ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots); | ||
378 | if (ret) | ||
379 | return ret; | ||
380 | |||
381 | slots = PCI_SLOT_INFO_SLOTS(slots) + 1; | ||
382 | dev_dbg(&pdev->dev, "found %d slot(s)\n", slots); | ||
383 | if (slots == 0) | ||
384 | return -ENODEV; | ||
385 | |||
386 | BUG_ON(slots > MAX_SLOTS); | ||
387 | |||
388 | ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar); | ||
389 | if (ret) | ||
390 | return ret; | ||
391 | |||
392 | first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK; | ||
393 | |||
394 | if (first_bar > 5) { | ||
395 | dev_err(&pdev->dev, "Invalid first BAR. Aborting.\n"); | ||
396 | return -ENODEV; | ||
397 | } | ||
398 | |||
399 | ret = pci_enable_device(pdev); | ||
400 | if (ret) | ||
401 | return ret; | ||
402 | |||
403 | chip = kzalloc(sizeof(struct sdhci_pci_chip), GFP_KERNEL); | ||
404 | if (!chip) { | ||
405 | ret = -ENOMEM; | ||
406 | goto err; | ||
407 | } | ||
408 | |||
409 | chip->pdev = pdev; | ||
410 | chip->quirks = ent->driver_data; | ||
411 | chip->num_slots = slots; | ||
412 | |||
413 | pci_set_drvdata(pdev, chip); | ||
414 | |||
415 | for (i = 0;i < slots;i++) { | ||
416 | slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i); | ||
417 | if (IS_ERR(slot)) { | ||
418 | for (i--;i >= 0;i--) | ||
419 | sdhci_pci_remove_slot(chip->slots[i]); | ||
420 | ret = PTR_ERR(slot); | ||
421 | goto free; | ||
422 | } | ||
423 | |||
424 | chip->slots[i] = slot; | ||
425 | } | ||
426 | |||
427 | return 0; | ||
428 | |||
429 | free: | ||
430 | pci_set_drvdata(pdev, NULL); | ||
431 | kfree(chip); | ||
432 | |||
433 | err: | ||
434 | pci_disable_device(pdev); | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | static void __devexit sdhci_pci_remove(struct pci_dev *pdev) | ||
439 | { | ||
440 | int i; | ||
441 | struct sdhci_pci_chip *chip; | ||
442 | |||
443 | chip = pci_get_drvdata(pdev); | ||
444 | |||
445 | if (chip) { | ||
446 | for (i = 0;i < chip->num_slots; i++) | ||
447 | sdhci_pci_remove_slot(chip->slots[i]); | ||
448 | |||
449 | pci_set_drvdata(pdev, NULL); | ||
450 | kfree(chip); | ||
451 | } | ||
452 | |||
453 | pci_disable_device(pdev); | ||
454 | } | ||
455 | |||
456 | static struct pci_driver sdhci_driver = { | ||
457 | .name = "sdhci-pci", | ||
458 | .id_table = pci_ids, | ||
459 | .probe = sdhci_pci_probe, | ||
460 | .remove = __devexit_p(sdhci_pci_remove), | ||
461 | .suspend = sdhci_pci_suspend, | ||
462 | .resume = sdhci_pci_resume, | ||
463 | }; | ||
464 | |||
465 | /*****************************************************************************\ | ||
466 | * * | ||
467 | * Driver init/exit * | ||
468 | * * | ||
469 | \*****************************************************************************/ | ||
470 | |||
471 | static int __init sdhci_drv_init(void) | ||
472 | { | ||
473 | return pci_register_driver(&sdhci_driver); | ||
474 | } | ||
475 | |||
476 | static void __exit sdhci_drv_exit(void) | ||
477 | { | ||
478 | pci_unregister_driver(&sdhci_driver); | ||
479 | } | ||
480 | |||
481 | module_init(sdhci_drv_init); | ||
482 | module_exit(sdhci_drv_exit); | ||
483 | |||
484 | MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>"); | ||
485 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver"); | ||
486 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 9b06c6042d97..8ce01d434ea8 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -15,7 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/pci.h> | 18 | #include <linux/io.h> |
19 | #include <linux/dma-mapping.h> | 19 | #include <linux/dma-mapping.h> |
20 | #include <linux/scatterlist.h> | 20 | #include <linux/scatterlist.h> |
21 | 21 | ||
@@ -32,135 +32,6 @@ | |||
32 | 32 | ||
33 | static unsigned int debug_quirks = 0; | 33 | static unsigned int debug_quirks = 0; |
34 | 34 | ||
35 | /* | ||
36 | * Different quirks to handle when the hardware deviates from a strict | ||
37 | * interpretation of the SDHCI specification. | ||
38 | */ | ||
39 | |||
40 | /* Controller doesn't honor resets unless we touch the clock register */ | ||
41 | #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) | ||
42 | /* Controller has bad caps bits, but really supports DMA */ | ||
43 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) | ||
44 | /* Controller doesn't like to be reset when there is no card inserted. */ | ||
45 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | ||
46 | /* Controller doesn't like clearing the power reg before a change */ | ||
47 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | ||
48 | /* Controller has flaky internal state so reset it on each ios change */ | ||
49 | #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) | ||
50 | /* Controller has an unusable DMA engine */ | ||
51 | #define SDHCI_QUIRK_BROKEN_DMA (1<<5) | ||
52 | /* Controller can only DMA from 32-bit aligned addresses */ | ||
53 | #define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<6) | ||
54 | /* Controller can only DMA chunk sizes that are a multiple of 32 bits */ | ||
55 | #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<7) | ||
56 | /* Controller needs to be reset after each request to stay stable */ | ||
57 | #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8) | ||
58 | /* Controller needs voltage and power writes to happen separately */ | ||
59 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<9) | ||
60 | /* Controller has an off-by-one issue with timeout value */ | ||
61 | #define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL (1<<10) | ||
62 | |||
63 | static const struct pci_device_id pci_ids[] __devinitdata = { | ||
64 | { | ||
65 | .vendor = PCI_VENDOR_ID_RICOH, | ||
66 | .device = PCI_DEVICE_ID_RICOH_R5C822, | ||
67 | .subvendor = PCI_VENDOR_ID_IBM, | ||
68 | .subdevice = PCI_ANY_ID, | ||
69 | .driver_data = SDHCI_QUIRK_CLOCK_BEFORE_RESET | | ||
70 | SDHCI_QUIRK_FORCE_DMA, | ||
71 | }, | ||
72 | |||
73 | { | ||
74 | .vendor = PCI_VENDOR_ID_RICOH, | ||
75 | .device = PCI_DEVICE_ID_RICOH_R5C822, | ||
76 | .subvendor = PCI_VENDOR_ID_SAMSUNG, | ||
77 | .subdevice = PCI_ANY_ID, | ||
78 | .driver_data = SDHCI_QUIRK_FORCE_DMA | | ||
79 | SDHCI_QUIRK_NO_CARD_NO_RESET, | ||
80 | }, | ||
81 | |||
82 | { | ||
83 | .vendor = PCI_VENDOR_ID_RICOH, | ||
84 | .device = PCI_DEVICE_ID_RICOH_R5C822, | ||
85 | .subvendor = PCI_ANY_ID, | ||
86 | .subdevice = PCI_ANY_ID, | ||
87 | .driver_data = SDHCI_QUIRK_FORCE_DMA, | ||
88 | }, | ||
89 | |||
90 | { | ||
91 | .vendor = PCI_VENDOR_ID_TI, | ||
92 | .device = PCI_DEVICE_ID_TI_XX21_XX11_SD, | ||
93 | .subvendor = PCI_ANY_ID, | ||
94 | .subdevice = PCI_ANY_ID, | ||
95 | .driver_data = SDHCI_QUIRK_FORCE_DMA, | ||
96 | }, | ||
97 | |||
98 | { | ||
99 | .vendor = PCI_VENDOR_ID_ENE, | ||
100 | .device = PCI_DEVICE_ID_ENE_CB712_SD, | ||
101 | .subvendor = PCI_ANY_ID, | ||
102 | .subdevice = PCI_ANY_ID, | ||
103 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
104 | SDHCI_QUIRK_BROKEN_DMA, | ||
105 | }, | ||
106 | |||
107 | { | ||
108 | .vendor = PCI_VENDOR_ID_ENE, | ||
109 | .device = PCI_DEVICE_ID_ENE_CB712_SD_2, | ||
110 | .subvendor = PCI_ANY_ID, | ||
111 | .subdevice = PCI_ANY_ID, | ||
112 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
113 | SDHCI_QUIRK_BROKEN_DMA, | ||
114 | }, | ||
115 | |||
116 | { | ||
117 | .vendor = PCI_VENDOR_ID_ENE, | ||
118 | .device = PCI_DEVICE_ID_ENE_CB714_SD, | ||
119 | .subvendor = PCI_ANY_ID, | ||
120 | .subdevice = PCI_ANY_ID, | ||
121 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
122 | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | | ||
123 | SDHCI_QUIRK_BROKEN_DMA, | ||
124 | }, | ||
125 | |||
126 | { | ||
127 | .vendor = PCI_VENDOR_ID_ENE, | ||
128 | .device = PCI_DEVICE_ID_ENE_CB714_SD_2, | ||
129 | .subvendor = PCI_ANY_ID, | ||
130 | .subdevice = PCI_ANY_ID, | ||
131 | .driver_data = SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
132 | SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS | | ||
133 | SDHCI_QUIRK_BROKEN_DMA, | ||
134 | }, | ||
135 | |||
136 | { | ||
137 | .vendor = PCI_VENDOR_ID_MARVELL, | ||
138 | .device = PCI_DEVICE_ID_MARVELL_CAFE_SD, | ||
139 | .subvendor = PCI_ANY_ID, | ||
140 | .subdevice = PCI_ANY_ID, | ||
141 | .driver_data = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | ||
142 | SDHCI_QUIRK_INCR_TIMEOUT_CONTROL, | ||
143 | }, | ||
144 | |||
145 | { | ||
146 | .vendor = PCI_VENDOR_ID_JMICRON, | ||
147 | .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD, | ||
148 | .subvendor = PCI_ANY_ID, | ||
149 | .subdevice = PCI_ANY_ID, | ||
150 | .driver_data = SDHCI_QUIRK_32BIT_DMA_ADDR | | ||
151 | SDHCI_QUIRK_32BIT_DMA_SIZE | | ||
152 | SDHCI_QUIRK_RESET_AFTER_REQUEST, | ||
153 | }, | ||
154 | |||
155 | { /* Generic SD host controller */ | ||
156 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | ||
157 | }, | ||
158 | |||
159 | { /* end: all zeroes */ }, | ||
160 | }; | ||
161 | |||
162 | MODULE_DEVICE_TABLE(pci, pci_ids); | ||
163 | |||
164 | static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); | 35 | static void sdhci_prepare_data(struct sdhci_host *, struct mmc_data *); |
165 | static void sdhci_finish_data(struct sdhci_host *); | 36 | static void sdhci_finish_data(struct sdhci_host *); |
166 | 37 | ||
@@ -215,7 +86,7 @@ static void sdhci_reset(struct sdhci_host *host, u8 mask) | |||
215 | { | 86 | { |
216 | unsigned long timeout; | 87 | unsigned long timeout; |
217 | 88 | ||
218 | if (host->chip->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { | 89 | if (host->quirks & SDHCI_QUIRK_NO_CARD_NO_RESET) { |
219 | if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & | 90 | if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & |
220 | SDHCI_CARD_PRESENT)) | 91 | SDHCI_CARD_PRESENT)) |
221 | return; | 92 | return; |
@@ -488,7 +359,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
488 | * Compensate for an off-by-one error in the CaFe hardware; otherwise, | 359 | * Compensate for an off-by-one error in the CaFe hardware; otherwise, |
489 | * a too-small count gives us interrupt timeouts. | 360 | * a too-small count gives us interrupt timeouts. |
490 | */ | 361 | */ |
491 | if ((host->chip->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)) | 362 | if ((host->quirks & SDHCI_QUIRK_INCR_TIMEOUT_CONTROL)) |
492 | count++; | 363 | count++; |
493 | 364 | ||
494 | if (count >= 0xF) { | 365 | if (count >= 0xF) { |
@@ -503,7 +374,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
503 | host->flags |= SDHCI_REQ_USE_DMA; | 374 | host->flags |= SDHCI_REQ_USE_DMA; |
504 | 375 | ||
505 | if (unlikely((host->flags & SDHCI_REQ_USE_DMA) && | 376 | if (unlikely((host->flags & SDHCI_REQ_USE_DMA) && |
506 | (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) && | 377 | (host->quirks & SDHCI_QUIRK_32BIT_DMA_SIZE) && |
507 | ((data->blksz * data->blocks) & 0x3))) { | 378 | ((data->blksz * data->blocks) & 0x3))) { |
508 | DBG("Reverting to PIO because of transfer size (%d)\n", | 379 | DBG("Reverting to PIO because of transfer size (%d)\n", |
509 | data->blksz * data->blocks); | 380 | data->blksz * data->blocks); |
@@ -515,7 +386,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
515 | * translation to device address space. | 386 | * translation to device address space. |
516 | */ | 387 | */ |
517 | if (unlikely((host->flags & SDHCI_REQ_USE_DMA) && | 388 | if (unlikely((host->flags & SDHCI_REQ_USE_DMA) && |
518 | (host->chip->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && | 389 | (host->quirks & SDHCI_QUIRK_32BIT_DMA_ADDR) && |
519 | (data->sg->offset & 0x3))) { | 390 | (data->sg->offset & 0x3))) { |
520 | DBG("Reverting to PIO because of bad alignment\n"); | 391 | DBG("Reverting to PIO because of bad alignment\n"); |
521 | host->flags &= ~SDHCI_REQ_USE_DMA; | 392 | host->flags &= ~SDHCI_REQ_USE_DMA; |
@@ -524,11 +395,13 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) | |||
524 | if (host->flags & SDHCI_REQ_USE_DMA) { | 395 | if (host->flags & SDHCI_REQ_USE_DMA) { |
525 | int count; | 396 | int count; |
526 | 397 | ||
527 | count = pci_map_sg(host->chip->pdev, data->sg, data->sg_len, | 398 | count = dma_map_sg(mmc_dev(host->mmc), data->sg, data->sg_len, |
528 | (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); | 399 | (data->flags & MMC_DATA_READ) ? |
529 | BUG_ON(count != 1); | 400 | DMA_FROM_DEVICE : DMA_TO_DEVICE); |
401 | WARN_ON(count != 1); | ||
530 | 402 | ||
531 | writel(sg_dma_address(data->sg), host->ioaddr + SDHCI_DMA_ADDRESS); | 403 | writel(sg_dma_address(data->sg), |
404 | host->ioaddr + SDHCI_DMA_ADDRESS); | ||
532 | } else { | 405 | } else { |
533 | host->cur_sg = data->sg; | 406 | host->cur_sg = data->sg; |
534 | host->num_sg = data->sg_len; | 407 | host->num_sg = data->sg_len; |
@@ -574,8 +447,9 @@ static void sdhci_finish_data(struct sdhci_host *host) | |||
574 | host->data = NULL; | 447 | host->data = NULL; |
575 | 448 | ||
576 | if (host->flags & SDHCI_REQ_USE_DMA) { | 449 | if (host->flags & SDHCI_REQ_USE_DMA) { |
577 | pci_unmap_sg(host->chip->pdev, data->sg, data->sg_len, | 450 | dma_unmap_sg(mmc_dev(host->mmc), data->sg, data->sg_len, |
578 | (data->flags & MMC_DATA_READ)?PCI_DMA_FROMDEVICE:PCI_DMA_TODEVICE); | 451 | (data->flags & MMC_DATA_READ) ? |
452 | DMA_FROM_DEVICE : DMA_TO_DEVICE); | ||
579 | } | 453 | } |
580 | 454 | ||
581 | /* | 455 | /* |
@@ -770,7 +644,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
770 | * Spec says that we should clear the power reg before setting | 644 | * Spec says that we should clear the power reg before setting |
771 | * a new value. Some controllers don't seem to like this though. | 645 | * a new value. Some controllers don't seem to like this though. |
772 | */ | 646 | */ |
773 | if (!(host->chip->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) | 647 | if (!(host->quirks & SDHCI_QUIRK_SINGLE_POWER_WRITE)) |
774 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); | 648 | writeb(0, host->ioaddr + SDHCI_POWER_CONTROL); |
775 | 649 | ||
776 | pwr = SDHCI_POWER_ON; | 650 | pwr = SDHCI_POWER_ON; |
@@ -795,7 +669,7 @@ static void sdhci_set_power(struct sdhci_host *host, unsigned short power) | |||
795 | * At least the CaFe chip gets confused if we set the voltage | 669 | * At least the CaFe chip gets confused if we set the voltage |
796 | * and set turn on power at the same time, so set the voltage first. | 670 | * and set turn on power at the same time, so set the voltage first. |
797 | */ | 671 | */ |
798 | if ((host->chip->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) | 672 | if ((host->quirks & SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER)) |
799 | writeb(pwr & ~SDHCI_POWER_ON, | 673 | writeb(pwr & ~SDHCI_POWER_ON, |
800 | host->ioaddr + SDHCI_POWER_CONTROL); | 674 | host->ioaddr + SDHCI_POWER_CONTROL); |
801 | 675 | ||
@@ -883,7 +757,7 @@ static void sdhci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
883 | * signalling timeout and CRC errors even on CMD0. Resetting | 757 | * signalling timeout and CRC errors even on CMD0. Resetting |
884 | * it on each ios seems to solve the problem. | 758 | * it on each ios seems to solve the problem. |
885 | */ | 759 | */ |
886 | if(host->chip->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) | 760 | if(host->quirks & SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS) |
887 | sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); | 761 | sdhci_reset(host, SDHCI_RESET_CMD | SDHCI_RESET_DATA); |
888 | 762 | ||
889 | mmiowb(); | 763 | mmiowb(); |
@@ -994,10 +868,10 @@ static void sdhci_tasklet_finish(unsigned long param) | |||
994 | if (mrq->cmd->error || | 868 | if (mrq->cmd->error || |
995 | (mrq->data && (mrq->data->error || | 869 | (mrq->data && (mrq->data->error || |
996 | (mrq->data->stop && mrq->data->stop->error))) || | 870 | (mrq->data->stop && mrq->data->stop->error))) || |
997 | (host->chip->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { | 871 | (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST)) { |
998 | 872 | ||
999 | /* Some controllers need this kick or reset won't work here */ | 873 | /* Some controllers need this kick or reset won't work here */ |
1000 | if (host->chip->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { | 874 | if (host->quirks & SDHCI_QUIRK_CLOCK_BEFORE_RESET) { |
1001 | unsigned int clock; | 875 | unsigned int clock; |
1002 | 876 | ||
1003 | /* This is to force an update */ | 877 | /* This is to force an update */ |
@@ -1229,165 +1103,90 @@ out: | |||
1229 | 1103 | ||
1230 | #ifdef CONFIG_PM | 1104 | #ifdef CONFIG_PM |
1231 | 1105 | ||
1232 | static int sdhci_suspend (struct pci_dev *pdev, pm_message_t state) | 1106 | int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state) |
1233 | { | 1107 | { |
1234 | struct sdhci_chip *chip; | 1108 | int ret; |
1235 | int i, ret; | ||
1236 | |||
1237 | chip = pci_get_drvdata(pdev); | ||
1238 | if (!chip) | ||
1239 | return 0; | ||
1240 | |||
1241 | DBG("Suspending...\n"); | ||
1242 | |||
1243 | for (i = 0;i < chip->num_slots;i++) { | ||
1244 | if (!chip->hosts[i]) | ||
1245 | continue; | ||
1246 | ret = mmc_suspend_host(chip->hosts[i]->mmc, state); | ||
1247 | if (ret) { | ||
1248 | for (i--;i >= 0;i--) | ||
1249 | mmc_resume_host(chip->hosts[i]->mmc); | ||
1250 | return ret; | ||
1251 | } | ||
1252 | } | ||
1253 | |||
1254 | pci_save_state(pdev); | ||
1255 | pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); | ||
1256 | 1109 | ||
1257 | for (i = 0;i < chip->num_slots;i++) { | 1110 | ret = mmc_suspend_host(host->mmc, state); |
1258 | if (!chip->hosts[i]) | 1111 | if (ret) |
1259 | continue; | 1112 | return ret; |
1260 | free_irq(chip->hosts[i]->irq, chip->hosts[i]); | ||
1261 | } | ||
1262 | 1113 | ||
1263 | pci_disable_device(pdev); | 1114 | free_irq(host->irq, host); |
1264 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | ||
1265 | 1115 | ||
1266 | return 0; | 1116 | return 0; |
1267 | } | 1117 | } |
1268 | 1118 | ||
1269 | static int sdhci_resume (struct pci_dev *pdev) | 1119 | EXPORT_SYMBOL_GPL(sdhci_suspend_host); |
1270 | { | ||
1271 | struct sdhci_chip *chip; | ||
1272 | int i, ret; | ||
1273 | 1120 | ||
1274 | chip = pci_get_drvdata(pdev); | 1121 | int sdhci_resume_host(struct sdhci_host *host) |
1275 | if (!chip) | 1122 | { |
1276 | return 0; | 1123 | int ret; |
1277 | 1124 | ||
1278 | DBG("Resuming...\n"); | 1125 | if (host->flags & SDHCI_USE_DMA) { |
1126 | if (host->ops->enable_dma) | ||
1127 | host->ops->enable_dma(host); | ||
1128 | } | ||
1279 | 1129 | ||
1280 | pci_set_power_state(pdev, PCI_D0); | 1130 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, |
1281 | pci_restore_state(pdev); | 1131 | mmc_hostname(host->mmc), host); |
1282 | ret = pci_enable_device(pdev); | ||
1283 | if (ret) | 1132 | if (ret) |
1284 | return ret; | 1133 | return ret; |
1285 | 1134 | ||
1286 | for (i = 0;i < chip->num_slots;i++) { | 1135 | sdhci_init(host); |
1287 | if (!chip->hosts[i]) | 1136 | mmiowb(); |
1288 | continue; | 1137 | |
1289 | if (chip->hosts[i]->flags & SDHCI_USE_DMA) | 1138 | ret = mmc_resume_host(host->mmc); |
1290 | pci_set_master(pdev); | 1139 | if (ret) |
1291 | ret = request_irq(chip->hosts[i]->irq, sdhci_irq, | 1140 | return ret; |
1292 | IRQF_SHARED, mmc_hostname(chip->hosts[i]->mmc), | ||
1293 | chip->hosts[i]); | ||
1294 | if (ret) | ||
1295 | return ret; | ||
1296 | sdhci_init(chip->hosts[i]); | ||
1297 | mmiowb(); | ||
1298 | ret = mmc_resume_host(chip->hosts[i]->mmc); | ||
1299 | if (ret) | ||
1300 | return ret; | ||
1301 | } | ||
1302 | 1141 | ||
1303 | return 0; | 1142 | return 0; |
1304 | } | 1143 | } |
1305 | 1144 | ||
1306 | #else /* CONFIG_PM */ | 1145 | EXPORT_SYMBOL_GPL(sdhci_resume_host); |
1307 | |||
1308 | #define sdhci_suspend NULL | ||
1309 | #define sdhci_resume NULL | ||
1310 | 1146 | ||
1311 | #endif /* CONFIG_PM */ | 1147 | #endif /* CONFIG_PM */ |
1312 | 1148 | ||
1313 | /*****************************************************************************\ | 1149 | /*****************************************************************************\ |
1314 | * * | 1150 | * * |
1315 | * Device probing/removal * | 1151 | * Device allocation/registration * |
1316 | * * | 1152 | * * |
1317 | \*****************************************************************************/ | 1153 | \*****************************************************************************/ |
1318 | 1154 | ||
1319 | static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | 1155 | struct sdhci_host *sdhci_alloc_host(struct device *dev, |
1156 | size_t priv_size) | ||
1320 | { | 1157 | { |
1321 | int ret; | ||
1322 | unsigned int version; | ||
1323 | struct sdhci_chip *chip; | ||
1324 | struct mmc_host *mmc; | 1158 | struct mmc_host *mmc; |
1325 | struct sdhci_host *host; | 1159 | struct sdhci_host *host; |
1326 | 1160 | ||
1327 | u8 first_bar; | 1161 | WARN_ON(dev == NULL); |
1328 | unsigned int caps; | ||
1329 | |||
1330 | chip = pci_get_drvdata(pdev); | ||
1331 | BUG_ON(!chip); | ||
1332 | |||
1333 | ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar); | ||
1334 | if (ret) | ||
1335 | return ret; | ||
1336 | |||
1337 | first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK; | ||
1338 | 1162 | ||
1339 | if (first_bar > 5) { | 1163 | mmc = mmc_alloc_host(sizeof(struct sdhci_host) + priv_size, dev); |
1340 | printk(KERN_ERR DRIVER_NAME ": Invalid first BAR. Aborting.\n"); | ||
1341 | return -ENODEV; | ||
1342 | } | ||
1343 | |||
1344 | if (!(pci_resource_flags(pdev, first_bar + slot) & IORESOURCE_MEM)) { | ||
1345 | printk(KERN_ERR DRIVER_NAME ": BAR is not iomem. Aborting.\n"); | ||
1346 | return -ENODEV; | ||
1347 | } | ||
1348 | |||
1349 | if (pci_resource_len(pdev, first_bar + slot) != 0x100) { | ||
1350 | printk(KERN_ERR DRIVER_NAME ": Invalid iomem size. " | ||
1351 | "You may experience problems.\n"); | ||
1352 | } | ||
1353 | |||
1354 | if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { | ||
1355 | printk(KERN_ERR DRIVER_NAME ": Vendor specific interface. Aborting.\n"); | ||
1356 | return -ENODEV; | ||
1357 | } | ||
1358 | |||
1359 | if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) { | ||
1360 | printk(KERN_ERR DRIVER_NAME ": Unknown interface. Aborting.\n"); | ||
1361 | return -ENODEV; | ||
1362 | } | ||
1363 | |||
1364 | mmc = mmc_alloc_host(sizeof(struct sdhci_host), &pdev->dev); | ||
1365 | if (!mmc) | 1164 | if (!mmc) |
1366 | return -ENOMEM; | 1165 | return ERR_PTR(-ENOMEM); |
1367 | 1166 | ||
1368 | host = mmc_priv(mmc); | 1167 | host = mmc_priv(mmc); |
1369 | host->mmc = mmc; | 1168 | host->mmc = mmc; |
1370 | 1169 | ||
1371 | host->chip = chip; | 1170 | return host; |
1372 | chip->hosts[slot] = host; | 1171 | } |
1373 | 1172 | ||
1374 | host->bar = first_bar + slot; | 1173 | EXPORT_SYMBOL_GPL(sdhci_alloc_host); |
1375 | 1174 | ||
1376 | host->addr = pci_resource_start(pdev, host->bar); | 1175 | int sdhci_add_host(struct sdhci_host *host) |
1377 | host->irq = pdev->irq; | 1176 | { |
1177 | struct mmc_host *mmc; | ||
1178 | unsigned int caps; | ||
1179 | unsigned int version; | ||
1180 | int ret; | ||
1378 | 1181 | ||
1379 | DBG("slot %d at 0x%08lx, irq %d\n", slot, host->addr, host->irq); | 1182 | WARN_ON(host == NULL); |
1183 | if (host == NULL) | ||
1184 | return -EINVAL; | ||
1380 | 1185 | ||
1381 | ret = pci_request_region(pdev, host->bar, mmc_hostname(mmc)); | 1186 | mmc = host->mmc; |
1382 | if (ret) | ||
1383 | goto free; | ||
1384 | 1187 | ||
1385 | host->ioaddr = ioremap_nocache(host->addr, | 1188 | if (debug_quirks) |
1386 | pci_resource_len(pdev, host->bar)); | 1189 | host->quirks = debug_quirks; |
1387 | if (!host->ioaddr) { | ||
1388 | ret = -ENOMEM; | ||
1389 | goto release; | ||
1390 | } | ||
1391 | 1190 | ||
1392 | sdhci_reset(host, SDHCI_RESET_ALL); | 1191 | sdhci_reset(host, SDHCI_RESET_ALL); |
1393 | 1192 | ||
@@ -1401,46 +1200,40 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1401 | 1200 | ||
1402 | caps = readl(host->ioaddr + SDHCI_CAPABILITIES); | 1201 | caps = readl(host->ioaddr + SDHCI_CAPABILITIES); |
1403 | 1202 | ||
1404 | if (chip->quirks & SDHCI_QUIRK_FORCE_DMA) | 1203 | if (host->quirks & SDHCI_QUIRK_FORCE_DMA) |
1405 | host->flags |= SDHCI_USE_DMA; | 1204 | host->flags |= SDHCI_USE_DMA; |
1406 | else if (!(caps & SDHCI_CAN_DO_DMA)) | 1205 | else if (!(caps & SDHCI_CAN_DO_DMA)) |
1407 | DBG("Controller doesn't have DMA capability\n"); | 1206 | DBG("Controller doesn't have DMA capability\n"); |
1408 | else | 1207 | else |
1409 | host->flags |= SDHCI_USE_DMA; | 1208 | host->flags |= SDHCI_USE_DMA; |
1410 | 1209 | ||
1411 | if ((chip->quirks & SDHCI_QUIRK_BROKEN_DMA) && | 1210 | if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && |
1412 | (host->flags & SDHCI_USE_DMA)) { | 1211 | (host->flags & SDHCI_USE_DMA)) { |
1413 | DBG("Disabling DMA as it is marked broken\n"); | 1212 | DBG("Disabling DMA as it is marked broken\n"); |
1414 | host->flags &= ~SDHCI_USE_DMA; | 1213 | host->flags &= ~SDHCI_USE_DMA; |
1415 | } | 1214 | } |
1416 | 1215 | ||
1417 | if (((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) && | ||
1418 | (host->flags & SDHCI_USE_DMA)) { | ||
1419 | printk(KERN_WARNING "%s: Will use DMA " | ||
1420 | "mode even though HW doesn't fully " | ||
1421 | "claim to support it.\n", mmc_hostname(mmc)); | ||
1422 | } | ||
1423 | |||
1424 | if (host->flags & SDHCI_USE_DMA) { | 1216 | if (host->flags & SDHCI_USE_DMA) { |
1425 | if (pci_set_dma_mask(pdev, DMA_32BIT_MASK)) { | 1217 | if (host->ops->enable_dma) { |
1426 | printk(KERN_WARNING "%s: No suitable DMA available. " | 1218 | if (host->ops->enable_dma(host)) { |
1427 | "Falling back to PIO.\n", mmc_hostname(mmc)); | 1219 | printk(KERN_WARNING "%s: No suitable DMA " |
1428 | host->flags &= ~SDHCI_USE_DMA; | 1220 | "available. Falling back to PIO.\n", |
1221 | mmc_hostname(mmc)); | ||
1222 | host->flags &= ~SDHCI_USE_DMA; | ||
1223 | } | ||
1429 | } | 1224 | } |
1430 | } | 1225 | } |
1431 | 1226 | ||
1432 | if (host->flags & SDHCI_USE_DMA) | 1227 | /* XXX: Hack to get MMC layer to avoid highmem */ |
1433 | pci_set_master(pdev); | 1228 | if (!(host->flags & SDHCI_USE_DMA)) |
1434 | else /* XXX: Hack to get MMC layer to avoid highmem */ | 1229 | mmc_dev(host->mmc)->dma_mask = 0; |
1435 | pdev->dma_mask = 0; | ||
1436 | 1230 | ||
1437 | host->max_clk = | 1231 | host->max_clk = |
1438 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; | 1232 | (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT; |
1439 | if (host->max_clk == 0) { | 1233 | if (host->max_clk == 0) { |
1440 | printk(KERN_ERR "%s: Hardware doesn't specify base clock " | 1234 | printk(KERN_ERR "%s: Hardware doesn't specify base clock " |
1441 | "frequency.\n", mmc_hostname(mmc)); | 1235 | "frequency.\n", mmc_hostname(mmc)); |
1442 | ret = -ENODEV; | 1236 | return -ENODEV; |
1443 | goto unmap; | ||
1444 | } | 1237 | } |
1445 | host->max_clk *= 1000000; | 1238 | host->max_clk *= 1000000; |
1446 | 1239 | ||
@@ -1449,8 +1242,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1449 | if (host->timeout_clk == 0) { | 1242 | if (host->timeout_clk == 0) { |
1450 | printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " | 1243 | printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " |
1451 | "frequency.\n", mmc_hostname(mmc)); | 1244 | "frequency.\n", mmc_hostname(mmc)); |
1452 | ret = -ENODEV; | 1245 | return -ENODEV; |
1453 | goto unmap; | ||
1454 | } | 1246 | } |
1455 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) | 1247 | if (caps & SDHCI_TIMEOUT_CLK_UNIT) |
1456 | host->timeout_clk *= 1000; | 1248 | host->timeout_clk *= 1000; |
@@ -1477,8 +1269,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1477 | if (mmc->ocr_avail == 0) { | 1269 | if (mmc->ocr_avail == 0) { |
1478 | printk(KERN_ERR "%s: Hardware doesn't report any " | 1270 | printk(KERN_ERR "%s: Hardware doesn't report any " |
1479 | "support voltages.\n", mmc_hostname(mmc)); | 1271 | "support voltages.\n", mmc_hostname(mmc)); |
1480 | ret = -ENODEV; | 1272 | return -ENODEV; |
1481 | goto unmap; | ||
1482 | } | 1273 | } |
1483 | 1274 | ||
1484 | spin_lock_init(&host->lock); | 1275 | spin_lock_init(&host->lock); |
@@ -1548,7 +1339,7 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1548 | host->led.default_trigger = mmc_hostname(mmc); | 1339 | host->led.default_trigger = mmc_hostname(mmc); |
1549 | host->led.brightness_set = sdhci_led_control; | 1340 | host->led.brightness_set = sdhci_led_control; |
1550 | 1341 | ||
1551 | ret = led_classdev_register(&pdev->dev, &host->led); | 1342 | ret = led_classdev_register(mmc_dev(mmc), &host->led); |
1552 | if (ret) | 1343 | if (ret) |
1553 | goto reset; | 1344 | goto reset; |
1554 | #endif | 1345 | #endif |
@@ -1557,8 +1348,8 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot) | |||
1557 | 1348 | ||
1558 | mmc_add_host(mmc); | 1349 | mmc_add_host(mmc); |
1559 | 1350 | ||
1560 | printk(KERN_INFO "%s: SDHCI at 0x%08lx irq %d %s\n", | 1351 | printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n", |
1561 | mmc_hostname(mmc), host->addr, host->irq, | 1352 | mmc_hostname(mmc), host->hw_name, mmc_dev(mmc)->bus_id, |
1562 | (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); | 1353 | (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); |
1563 | 1354 | ||
1564 | return 0; | 1355 | return 0; |
@@ -1571,29 +1362,15 @@ reset: | |||
1571 | untasklet: | 1362 | untasklet: |
1572 | tasklet_kill(&host->card_tasklet); | 1363 | tasklet_kill(&host->card_tasklet); |
1573 | tasklet_kill(&host->finish_tasklet); | 1364 | tasklet_kill(&host->finish_tasklet); |
1574 | unmap: | ||
1575 | iounmap(host->ioaddr); | ||
1576 | release: | ||
1577 | pci_release_region(pdev, host->bar); | ||
1578 | free: | ||
1579 | mmc_free_host(mmc); | ||
1580 | 1365 | ||
1581 | return ret; | 1366 | return ret; |
1582 | } | 1367 | } |
1583 | 1368 | ||
1584 | static void sdhci_remove_slot(struct pci_dev *pdev, int slot) | 1369 | EXPORT_SYMBOL_GPL(sdhci_add_host); |
1585 | { | ||
1586 | struct sdhci_chip *chip; | ||
1587 | struct mmc_host *mmc; | ||
1588 | struct sdhci_host *host; | ||
1589 | |||
1590 | chip = pci_get_drvdata(pdev); | ||
1591 | host = chip->hosts[slot]; | ||
1592 | mmc = host->mmc; | ||
1593 | |||
1594 | chip->hosts[slot] = NULL; | ||
1595 | 1370 | ||
1596 | mmc_remove_host(mmc); | 1371 | void sdhci_remove_host(struct sdhci_host *host) |
1372 | { | ||
1373 | mmc_remove_host(host->mmc); | ||
1597 | 1374 | ||
1598 | #ifdef CONFIG_LEDS_CLASS | 1375 | #ifdef CONFIG_LEDS_CLASS |
1599 | led_classdev_unregister(&host->led); | 1376 | led_classdev_unregister(&host->led); |
@@ -1607,107 +1384,16 @@ static void sdhci_remove_slot(struct pci_dev *pdev, int slot) | |||
1607 | 1384 | ||
1608 | tasklet_kill(&host->card_tasklet); | 1385 | tasklet_kill(&host->card_tasklet); |
1609 | tasklet_kill(&host->finish_tasklet); | 1386 | tasklet_kill(&host->finish_tasklet); |
1610 | |||
1611 | iounmap(host->ioaddr); | ||
1612 | |||
1613 | pci_release_region(pdev, host->bar); | ||
1614 | |||
1615 | mmc_free_host(mmc); | ||
1616 | } | 1387 | } |
1617 | 1388 | ||
1618 | static int __devinit sdhci_probe(struct pci_dev *pdev, | 1389 | EXPORT_SYMBOL_GPL(sdhci_remove_host); |
1619 | const struct pci_device_id *ent) | ||
1620 | { | ||
1621 | int ret, i; | ||
1622 | u8 slots, rev; | ||
1623 | struct sdhci_chip *chip; | ||
1624 | |||
1625 | BUG_ON(pdev == NULL); | ||
1626 | BUG_ON(ent == NULL); | ||
1627 | |||
1628 | pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev); | ||
1629 | |||
1630 | printk(KERN_INFO DRIVER_NAME | ||
1631 | ": SDHCI controller found at %s [%04x:%04x] (rev %x)\n", | ||
1632 | pci_name(pdev), (int)pdev->vendor, (int)pdev->device, | ||
1633 | (int)rev); | ||
1634 | |||
1635 | ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots); | ||
1636 | if (ret) | ||
1637 | return ret; | ||
1638 | |||
1639 | slots = PCI_SLOT_INFO_SLOTS(slots) + 1; | ||
1640 | DBG("found %d slot(s)\n", slots); | ||
1641 | if (slots == 0) | ||
1642 | return -ENODEV; | ||
1643 | 1390 | ||
1644 | ret = pci_enable_device(pdev); | 1391 | void sdhci_free_host(struct sdhci_host *host) |
1645 | if (ret) | ||
1646 | return ret; | ||
1647 | |||
1648 | chip = kzalloc(sizeof(struct sdhci_chip) + | ||
1649 | sizeof(struct sdhci_host*) * slots, GFP_KERNEL); | ||
1650 | if (!chip) { | ||
1651 | ret = -ENOMEM; | ||
1652 | goto err; | ||
1653 | } | ||
1654 | |||
1655 | chip->pdev = pdev; | ||
1656 | chip->quirks = ent->driver_data; | ||
1657 | |||
1658 | if (debug_quirks) | ||
1659 | chip->quirks = debug_quirks; | ||
1660 | |||
1661 | chip->num_slots = slots; | ||
1662 | pci_set_drvdata(pdev, chip); | ||
1663 | |||
1664 | for (i = 0;i < slots;i++) { | ||
1665 | ret = sdhci_probe_slot(pdev, i); | ||
1666 | if (ret) { | ||
1667 | for (i--;i >= 0;i--) | ||
1668 | sdhci_remove_slot(pdev, i); | ||
1669 | goto free; | ||
1670 | } | ||
1671 | } | ||
1672 | |||
1673 | return 0; | ||
1674 | |||
1675 | free: | ||
1676 | pci_set_drvdata(pdev, NULL); | ||
1677 | kfree(chip); | ||
1678 | |||
1679 | err: | ||
1680 | pci_disable_device(pdev); | ||
1681 | return ret; | ||
1682 | } | ||
1683 | |||
1684 | static void __devexit sdhci_remove(struct pci_dev *pdev) | ||
1685 | { | 1392 | { |
1686 | int i; | 1393 | mmc_free_host(host->mmc); |
1687 | struct sdhci_chip *chip; | ||
1688 | |||
1689 | chip = pci_get_drvdata(pdev); | ||
1690 | |||
1691 | if (chip) { | ||
1692 | for (i = 0;i < chip->num_slots;i++) | ||
1693 | sdhci_remove_slot(pdev, i); | ||
1694 | |||
1695 | pci_set_drvdata(pdev, NULL); | ||
1696 | |||
1697 | kfree(chip); | ||
1698 | } | ||
1699 | |||
1700 | pci_disable_device(pdev); | ||
1701 | } | 1394 | } |
1702 | 1395 | ||
1703 | static struct pci_driver sdhci_driver = { | 1396 | EXPORT_SYMBOL_GPL(sdhci_free_host); |
1704 | .name = DRIVER_NAME, | ||
1705 | .id_table = pci_ids, | ||
1706 | .probe = sdhci_probe, | ||
1707 | .remove = __devexit_p(sdhci_remove), | ||
1708 | .suspend = sdhci_suspend, | ||
1709 | .resume = sdhci_resume, | ||
1710 | }; | ||
1711 | 1397 | ||
1712 | /*****************************************************************************\ | 1398 | /*****************************************************************************\ |
1713 | * * | 1399 | * * |
@@ -1721,14 +1407,11 @@ static int __init sdhci_drv_init(void) | |||
1721 | ": Secure Digital Host Controller Interface driver\n"); | 1407 | ": Secure Digital Host Controller Interface driver\n"); |
1722 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); | 1408 | printk(KERN_INFO DRIVER_NAME ": Copyright(c) Pierre Ossman\n"); |
1723 | 1409 | ||
1724 | return pci_register_driver(&sdhci_driver); | 1410 | return 0; |
1725 | } | 1411 | } |
1726 | 1412 | ||
1727 | static void __exit sdhci_drv_exit(void) | 1413 | static void __exit sdhci_drv_exit(void) |
1728 | { | 1414 | { |
1729 | DBG("Exiting\n"); | ||
1730 | |||
1731 | pci_unregister_driver(&sdhci_driver); | ||
1732 | } | 1415 | } |
1733 | 1416 | ||
1734 | module_init(sdhci_drv_init); | 1417 | module_init(sdhci_drv_init); |
@@ -1737,7 +1420,7 @@ module_exit(sdhci_drv_exit); | |||
1737 | module_param(debug_quirks, uint, 0444); | 1420 | module_param(debug_quirks, uint, 0444); |
1738 | 1421 | ||
1739 | MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>"); | 1422 | MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>"); |
1740 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface driver"); | 1423 | MODULE_DESCRIPTION("Secure Digital Host Controller Interface core driver"); |
1741 | MODULE_LICENSE("GPL"); | 1424 | MODULE_LICENSE("GPL"); |
1742 | 1425 | ||
1743 | MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); | 1426 | MODULE_PARM_DESC(debug_quirks, "Force certain quirks."); |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 299118de8933..22fc258b12aa 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -10,18 +10,6 @@ | |||
10 | */ | 10 | */ |
11 | 11 | ||
12 | /* | 12 | /* |
13 | * PCI registers | ||
14 | */ | ||
15 | |||
16 | #define PCI_SDHCI_IFPIO 0x00 | ||
17 | #define PCI_SDHCI_IFDMA 0x01 | ||
18 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
19 | |||
20 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
21 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
22 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
23 | |||
24 | /* | ||
25 | * Controller registers | 13 | * Controller registers |
26 | */ | 14 | */ |
27 | 15 | ||
@@ -162,10 +150,43 @@ | |||
162 | #define SDHCI_SPEC_VER_MASK 0x00FF | 150 | #define SDHCI_SPEC_VER_MASK 0x00FF |
163 | #define SDHCI_SPEC_VER_SHIFT 0 | 151 | #define SDHCI_SPEC_VER_SHIFT 0 |
164 | 152 | ||
165 | struct sdhci_chip; | 153 | struct sdhci_ops; |
166 | 154 | ||
167 | struct sdhci_host { | 155 | struct sdhci_host { |
168 | struct sdhci_chip *chip; | 156 | /* Data set by hardware interface driver */ |
157 | const char *hw_name; /* Hardware bus name */ | ||
158 | |||
159 | unsigned int quirks; /* Deviations from spec. */ | ||
160 | |||
161 | /* Controller doesn't honor resets unless we touch the clock register */ | ||
162 | #define SDHCI_QUIRK_CLOCK_BEFORE_RESET (1<<0) | ||
163 | /* Controller has bad caps bits, but really supports DMA */ | ||
164 | #define SDHCI_QUIRK_FORCE_DMA (1<<1) | ||
165 | /* Controller doesn't like to be reset when there is no card inserted. */ | ||
166 | #define SDHCI_QUIRK_NO_CARD_NO_RESET (1<<2) | ||
167 | /* Controller doesn't like clearing the power reg before a change */ | ||
168 | #define SDHCI_QUIRK_SINGLE_POWER_WRITE (1<<3) | ||
169 | /* Controller has flaky internal state so reset it on each ios change */ | ||
170 | #define SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS (1<<4) | ||
171 | /* Controller has an unusable DMA engine */ | ||
172 | #define SDHCI_QUIRK_BROKEN_DMA (1<<5) | ||
173 | /* Controller can only DMA from 32-bit aligned addresses */ | ||
174 | #define SDHCI_QUIRK_32BIT_DMA_ADDR (1<<6) | ||
175 | /* Controller can only DMA chunk sizes that are a multiple of 32 bits */ | ||
176 | #define SDHCI_QUIRK_32BIT_DMA_SIZE (1<<7) | ||
177 | /* Controller needs to be reset after each request to stay stable */ | ||
178 | #define SDHCI_QUIRK_RESET_AFTER_REQUEST (1<<8) | ||
179 | /* Controller needs voltage and power writes to happen separately */ | ||
180 | #define SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER (1<<9) | ||
181 | /* Controller has an off-by-one issue with timeout value */ | ||
182 | #define SDHCI_QUIRK_INCR_TIMEOUT_CONTROL (1<<10) | ||
183 | |||
184 | int irq; /* Device IRQ */ | ||
185 | void __iomem * ioaddr; /* Mapped address */ | ||
186 | |||
187 | const struct sdhci_ops *ops; /* Low level hw interface */ | ||
188 | |||
189 | /* Internal data */ | ||
169 | struct mmc_host *mmc; /* MMC structure */ | 190 | struct mmc_host *mmc; /* MMC structure */ |
170 | 191 | ||
171 | #ifdef CONFIG_LEDS_CLASS | 192 | #ifdef CONFIG_LEDS_CLASS |
@@ -194,22 +215,33 @@ struct sdhci_host { | |||
194 | int offset; /* Offset into current sg */ | 215 | int offset; /* Offset into current sg */ |
195 | int remain; /* Bytes left in current */ | 216 | int remain; /* Bytes left in current */ |
196 | 217 | ||
197 | int irq; /* Device IRQ */ | ||
198 | int bar; /* PCI BAR index */ | ||
199 | unsigned long addr; /* Bus address */ | ||
200 | void __iomem * ioaddr; /* Mapped address */ | ||
201 | |||
202 | struct tasklet_struct card_tasklet; /* Tasklet structures */ | 218 | struct tasklet_struct card_tasklet; /* Tasklet structures */ |
203 | struct tasklet_struct finish_tasklet; | 219 | struct tasklet_struct finish_tasklet; |
204 | 220 | ||
205 | struct timer_list timer; /* Timer for timeouts */ | 221 | struct timer_list timer; /* Timer for timeouts */ |
206 | }; | ||
207 | 222 | ||
208 | struct sdhci_chip { | 223 | unsigned long private[0] ____cacheline_aligned; |
209 | struct pci_dev *pdev; | 224 | }; |
210 | 225 | ||
211 | unsigned long quirks; | ||
212 | 226 | ||
213 | int num_slots; /* Slots on controller */ | 227 | struct sdhci_ops { |
214 | struct sdhci_host *hosts[0]; /* Pointers to hosts */ | 228 | int (*enable_dma)(struct sdhci_host *host); |
215 | }; | 229 | }; |
230 | |||
231 | |||
232 | extern struct sdhci_host *sdhci_alloc_host(struct device *dev, | ||
233 | size_t priv_size); | ||
234 | extern void sdhci_free_host(struct sdhci_host *host); | ||
235 | |||
236 | static inline void *sdhci_priv(struct sdhci_host *host) | ||
237 | { | ||
238 | return (void *)host->private; | ||
239 | } | ||
240 | |||
241 | extern int sdhci_add_host(struct sdhci_host *host); | ||
242 | extern void sdhci_remove_host(struct sdhci_host *host); | ||
243 | |||
244 | #ifdef CONFIG_PM | ||
245 | extern int sdhci_suspend_host(struct sdhci_host *host, pm_message_t state); | ||
246 | extern int sdhci_resume_host(struct sdhci_host *host); | ||
247 | #endif | ||