blob: 2a3dd6cc7bf7deac77d203a41164f49ac062b772 [file] [log] [blame]
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +01001/* 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
41static 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
140MODULE_DEVICE_TABLE(pci, pci_ids);
141
142struct sdhci_pci_chip;
143
144struct sdhci_pci_slot {
145 struct sdhci_pci_chip *chip;
146 struct sdhci_host *host;
147
148 int pci_bar;
149};
150
151struct 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
165static 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
190static 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
202static 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
234static 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
276static 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
343unmap:
344 iounmap(host->ioaddr);
345
346release:
347 pci_release_region(pdev, bar);
348 sdhci_free_host(host);
349
350 return ERR_PTR(ret);
351}
352
353static 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
360static 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
429free:
430 pci_set_drvdata(pdev, NULL);
431 kfree(chip);
432
433err:
434 pci_disable_device(pdev);
435 return ret;
436}
437
438static 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
456static 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
471static int __init sdhci_drv_init(void)
472{
473 return pci_register_driver(&sdhci_driver);
474}
475
476static void __exit sdhci_drv_exit(void)
477{
478 pci_unregister_driver(&sdhci_driver);
479}
480
481module_init(sdhci_drv_init);
482module_exit(sdhci_drv_exit);
483
484MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
485MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
486MODULE_LICENSE("GPL");