blob: 8e1020cf73f42dfdeb85c1e9abe0a65f5b2b259f [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
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +010041struct sdhci_pci_chip;
Pierre Ossman44894282008-04-04 19:36:59 +020042struct sdhci_pci_slot;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +010043
Pierre Ossman22606402008-03-23 19:33:23 +010044struct sdhci_pci_fixes {
45 unsigned int quirks;
46
47 int (*probe)(struct sdhci_pci_chip*);
Pierre Ossman45211e22008-03-24 13:09:09 +010048
Pierre Ossman44894282008-04-04 19:36:59 +020049 int (*probe_slot)(struct sdhci_pci_slot*);
Pierre Ossman1e728592008-04-16 19:13:13 +020050 void (*remove_slot)(struct sdhci_pci_slot*, int);
Pierre Ossman44894282008-04-04 19:36:59 +020051
52 int (*suspend)(struct sdhci_pci_chip*,
53 pm_message_t);
Pierre Ossman45211e22008-03-24 13:09:09 +010054 int (*resume)(struct sdhci_pci_chip*);
Pierre Ossman22606402008-03-23 19:33:23 +010055};
56
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +010057struct sdhci_pci_slot {
58 struct sdhci_pci_chip *chip;
59 struct sdhci_host *host;
60
61 int pci_bar;
62};
63
64struct sdhci_pci_chip {
65 struct pci_dev *pdev;
Pierre Ossman22606402008-03-23 19:33:23 +010066
67 unsigned int quirks;
68 const struct sdhci_pci_fixes *fixes;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +010069
70 int num_slots; /* Slots on controller */
71 struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */
72};
73
Pierre Ossman22606402008-03-23 19:33:23 +010074
75/*****************************************************************************\
76 * *
77 * Hardware specific quirk handling *
78 * *
79\*****************************************************************************/
80
81static int ricoh_probe(struct sdhci_pci_chip *chip)
82{
Chris Ballc99436f2009-09-22 16:45:22 -070083 if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG ||
84 chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY)
Pierre Ossman22606402008-03-23 19:33:23 +010085 chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET;
86
87 return 0;
88}
89
90static const struct sdhci_pci_fixes sdhci_ricoh = {
91 .probe = ricoh_probe,
Vasily Khoruzhick84938292010-03-05 13:43:46 -080092 .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
93 SDHCI_QUIRK_FORCE_DMA |
94 SDHCI_QUIRK_CLOCK_BEFORE_RESET,
Pierre Ossman22606402008-03-23 19:33:23 +010095};
96
97static const struct sdhci_pci_fixes sdhci_ene_712 = {
98 .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
99 SDHCI_QUIRK_BROKEN_DMA,
100};
101
102static const struct sdhci_pci_fixes sdhci_ene_714 = {
103 .quirks = SDHCI_QUIRK_SINGLE_POWER_WRITE |
104 SDHCI_QUIRK_RESET_CMD_DATA_ON_IOS |
105 SDHCI_QUIRK_BROKEN_DMA,
106};
107
108static const struct sdhci_pci_fixes sdhci_cafe = {
109 .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER |
Andres Salomona0874892009-03-02 21:48:20 +0100110 SDHCI_QUIRK_NO_BUSY_IRQ |
Pierre Ossmanee53ab52008-07-05 00:25:15 +0200111 SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
Pierre Ossman22606402008-03-23 19:33:23 +0100112};
113
Pierre Ossman45211e22008-03-24 13:09:09 +0100114static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
115{
116 u8 scratch;
117 int ret;
118
119 ret = pci_read_config_byte(chip->pdev, 0xAE, &scratch);
120 if (ret)
121 return ret;
122
123 /*
124 * Turn PMOS on [bit 0], set over current detection to 2.4 V
125 * [bit 1:2] and enable over current debouncing [bit 6].
126 */
127 if (on)
128 scratch |= 0x47;
129 else
130 scratch &= ~0x47;
131
132 ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
133 if (ret)
134 return ret;
135
136 return 0;
137}
138
139static int jmicron_probe(struct sdhci_pci_chip *chip)
140{
141 int ret;
142
Pierre Ossman93fc48c2008-06-28 18:21:41 +0200143 if (chip->pdev->revision == 0) {
144 chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR |
145 SDHCI_QUIRK_32BIT_DMA_SIZE |
Pierre Ossman2134a922008-06-28 18:28:51 +0200146 SDHCI_QUIRK_32BIT_ADMA_SIZE |
Pierre Ossman4a3cba32008-07-29 00:11:16 +0200147 SDHCI_QUIRK_RESET_AFTER_REQUEST |
Pierre Ossman86a6a872009-02-02 21:13:49 +0100148 SDHCI_QUIRK_BROKEN_SMALL_PIO;
Pierre Ossman93fc48c2008-06-28 18:21:41 +0200149 }
150
Pierre Ossman45211e22008-03-24 13:09:09 +0100151 /*
Pierre Ossman44894282008-04-04 19:36:59 +0200152 * JMicron chips can have two interfaces to the same hardware
153 * in order to work around limitations in Microsoft's driver.
154 * We need to make sure we only bind to one of them.
155 *
156 * This code assumes two things:
157 *
158 * 1. The PCI code adds subfunctions in order.
159 *
160 * 2. The MMC interface has a lower subfunction number
161 * than the SD interface.
162 */
163 if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD) {
164 struct pci_dev *sd_dev;
165
166 sd_dev = NULL;
167 while ((sd_dev = pci_get_device(PCI_VENDOR_ID_JMICRON,
168 PCI_DEVICE_ID_JMICRON_JMB38X_MMC, sd_dev)) != NULL) {
169 if ((PCI_SLOT(chip->pdev->devfn) ==
170 PCI_SLOT(sd_dev->devfn)) &&
171 (chip->pdev->bus == sd_dev->bus))
172 break;
173 }
174
175 if (sd_dev) {
176 pci_dev_put(sd_dev);
177 dev_info(&chip->pdev->dev, "Refusing to bind to "
178 "secondary interface.\n");
179 return -ENODEV;
180 }
181 }
182
183 /*
Pierre Ossman45211e22008-03-24 13:09:09 +0100184 * JMicron chips need a bit of a nudge to enable the power
185 * output pins.
186 */
187 ret = jmicron_pmos(chip, 1);
188 if (ret) {
189 dev_err(&chip->pdev->dev, "Failure enabling card power\n");
190 return ret;
191 }
192
193 return 0;
194}
195
Pierre Ossman44894282008-04-04 19:36:59 +0200196static void jmicron_enable_mmc(struct sdhci_host *host, int on)
197{
198 u8 scratch;
199
200 scratch = readb(host->ioaddr + 0xC0);
201
202 if (on)
203 scratch |= 0x01;
204 else
205 scratch &= ~0x01;
206
207 writeb(scratch, host->ioaddr + 0xC0);
208}
209
210static int jmicron_probe_slot(struct sdhci_pci_slot *slot)
211{
Pierre Ossman2134a922008-06-28 18:28:51 +0200212 if (slot->chip->pdev->revision == 0) {
213 u16 version;
214
215 version = readl(slot->host->ioaddr + SDHCI_HOST_VERSION);
216 version = (version & SDHCI_VENDOR_VER_MASK) >>
217 SDHCI_VENDOR_VER_SHIFT;
218
219 /*
220 * Older versions of the chip have lots of nasty glitches
221 * in the ADMA engine. It's best just to avoid it
222 * completely.
223 */
224 if (version < 0xAC)
225 slot->host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
226 }
227
Pierre Ossman44894282008-04-04 19:36:59 +0200228 /*
229 * The secondary interface requires a bit set to get the
230 * interrupts.
231 */
232 if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
233 jmicron_enable_mmc(slot->host, 1);
234
235 return 0;
236}
237
Pierre Ossman1e728592008-04-16 19:13:13 +0200238static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
Pierre Ossman44894282008-04-04 19:36:59 +0200239{
Pierre Ossman1e728592008-04-16 19:13:13 +0200240 if (dead)
241 return;
242
Pierre Ossman44894282008-04-04 19:36:59 +0200243 if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
244 jmicron_enable_mmc(slot->host, 0);
245}
246
247static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state)
248{
249 int i;
250
251 if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
252 for (i = 0;i < chip->num_slots;i++)
253 jmicron_enable_mmc(chip->slots[i]->host, 0);
254 }
255
256 return 0;
257}
258
Pierre Ossman45211e22008-03-24 13:09:09 +0100259static int jmicron_resume(struct sdhci_pci_chip *chip)
260{
Pierre Ossman44894282008-04-04 19:36:59 +0200261 int ret, i;
262
263 if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
264 for (i = 0;i < chip->num_slots;i++)
265 jmicron_enable_mmc(chip->slots[i]->host, 1);
266 }
Pierre Ossman45211e22008-03-24 13:09:09 +0100267
268 ret = jmicron_pmos(chip, 1);
269 if (ret) {
270 dev_err(&chip->pdev->dev, "Failure enabling card power\n");
271 return ret;
272 }
273
274 return 0;
275}
276
Pierre Ossman22606402008-03-23 19:33:23 +0100277static const struct sdhci_pci_fixes sdhci_jmicron = {
Pierre Ossman45211e22008-03-24 13:09:09 +0100278 .probe = jmicron_probe,
279
Pierre Ossman44894282008-04-04 19:36:59 +0200280 .probe_slot = jmicron_probe_slot,
281 .remove_slot = jmicron_remove_slot,
282
283 .suspend = jmicron_suspend,
Pierre Ossman45211e22008-03-24 13:09:09 +0100284 .resume = jmicron_resume,
Pierre Ossman22606402008-03-23 19:33:23 +0100285};
286
Nicolas Pitrea7a61862009-12-14 18:01:26 -0800287/* SysKonnect CardBus2SDIO extra registers */
288#define SYSKT_CTRL 0x200
289#define SYSKT_RDFIFO_STAT 0x204
290#define SYSKT_WRFIFO_STAT 0x208
291#define SYSKT_POWER_DATA 0x20c
292#define SYSKT_POWER_330 0xef
293#define SYSKT_POWER_300 0xf8
294#define SYSKT_POWER_184 0xcc
295#define SYSKT_POWER_CMD 0x20d
296#define SYSKT_POWER_START (1 << 7)
297#define SYSKT_POWER_STATUS 0x20e
298#define SYSKT_POWER_STATUS_OK (1 << 0)
299#define SYSKT_BOARD_REV 0x210
300#define SYSKT_CHIP_REV 0x211
301#define SYSKT_CONF_DATA 0x212
302#define SYSKT_CONF_DATA_1V8 (1 << 2)
303#define SYSKT_CONF_DATA_2V5 (1 << 1)
304#define SYSKT_CONF_DATA_3V3 (1 << 0)
305
306static int syskt_probe(struct sdhci_pci_chip *chip)
307{
308 if ((chip->pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
309 chip->pdev->class &= ~0x0000FF;
310 chip->pdev->class |= PCI_SDHCI_IFDMA;
311 }
312 return 0;
313}
314
315static int syskt_probe_slot(struct sdhci_pci_slot *slot)
316{
317 int tm, ps;
318
319 u8 board_rev = readb(slot->host->ioaddr + SYSKT_BOARD_REV);
320 u8 chip_rev = readb(slot->host->ioaddr + SYSKT_CHIP_REV);
321 dev_info(&slot->chip->pdev->dev, "SysKonnect CardBus2SDIO, "
322 "board rev %d.%d, chip rev %d.%d\n",
323 board_rev >> 4, board_rev & 0xf,
324 chip_rev >> 4, chip_rev & 0xf);
325 if (chip_rev >= 0x20)
326 slot->host->quirks |= SDHCI_QUIRK_FORCE_DMA;
327
328 writeb(SYSKT_POWER_330, slot->host->ioaddr + SYSKT_POWER_DATA);
329 writeb(SYSKT_POWER_START, slot->host->ioaddr + SYSKT_POWER_CMD);
330 udelay(50);
331 tm = 10; /* Wait max 1 ms */
332 do {
333 ps = readw(slot->host->ioaddr + SYSKT_POWER_STATUS);
334 if (ps & SYSKT_POWER_STATUS_OK)
335 break;
336 udelay(100);
337 } while (--tm);
338 if (!tm) {
339 dev_err(&slot->chip->pdev->dev,
340 "power regulator never stabilized");
341 writeb(0, slot->host->ioaddr + SYSKT_POWER_CMD);
342 return -ENODEV;
343 }
344
345 return 0;
346}
347
348static const struct sdhci_pci_fixes sdhci_syskt = {
349 .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER,
350 .probe = syskt_probe,
351 .probe_slot = syskt_probe_slot,
352};
353
Harald Welte557b0692009-06-18 16:53:38 +0200354static int via_probe(struct sdhci_pci_chip *chip)
355{
356 if (chip->pdev->revision == 0x10)
357 chip->quirks |= SDHCI_QUIRK_DELAY_AFTER_POWER;
358
359 return 0;
360}
361
362static const struct sdhci_pci_fixes sdhci_via = {
363 .probe = via_probe,
364};
365
Pierre Ossman22606402008-03-23 19:33:23 +0100366static const struct pci_device_id pci_ids[] __devinitdata = {
367 {
368 .vendor = PCI_VENDOR_ID_RICOH,
369 .device = PCI_DEVICE_ID_RICOH_R5C822,
370 .subvendor = PCI_ANY_ID,
371 .subdevice = PCI_ANY_ID,
372 .driver_data = (kernel_ulong_t)&sdhci_ricoh,
373 },
374
375 {
376 .vendor = PCI_VENDOR_ID_ENE,
377 .device = PCI_DEVICE_ID_ENE_CB712_SD,
378 .subvendor = PCI_ANY_ID,
379 .subdevice = PCI_ANY_ID,
380 .driver_data = (kernel_ulong_t)&sdhci_ene_712,
381 },
382
383 {
384 .vendor = PCI_VENDOR_ID_ENE,
385 .device = PCI_DEVICE_ID_ENE_CB712_SD_2,
386 .subvendor = PCI_ANY_ID,
387 .subdevice = PCI_ANY_ID,
388 .driver_data = (kernel_ulong_t)&sdhci_ene_712,
389 },
390
391 {
392 .vendor = PCI_VENDOR_ID_ENE,
393 .device = PCI_DEVICE_ID_ENE_CB714_SD,
394 .subvendor = PCI_ANY_ID,
395 .subdevice = PCI_ANY_ID,
396 .driver_data = (kernel_ulong_t)&sdhci_ene_714,
397 },
398
399 {
400 .vendor = PCI_VENDOR_ID_ENE,
401 .device = PCI_DEVICE_ID_ENE_CB714_SD_2,
402 .subvendor = PCI_ANY_ID,
403 .subdevice = PCI_ANY_ID,
404 .driver_data = (kernel_ulong_t)&sdhci_ene_714,
405 },
406
407 {
408 .vendor = PCI_VENDOR_ID_MARVELL,
David Woodhouse8c5eb882008-09-03 09:45:57 +0100409 .device = PCI_DEVICE_ID_MARVELL_88ALP01_SD,
Pierre Ossman22606402008-03-23 19:33:23 +0100410 .subvendor = PCI_ANY_ID,
411 .subdevice = PCI_ANY_ID,
412 .driver_data = (kernel_ulong_t)&sdhci_cafe,
413 },
414
415 {
416 .vendor = PCI_VENDOR_ID_JMICRON,
417 .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
418 .subvendor = PCI_ANY_ID,
419 .subdevice = PCI_ANY_ID,
420 .driver_data = (kernel_ulong_t)&sdhci_jmicron,
421 },
422
Pierre Ossman44894282008-04-04 19:36:59 +0200423 {
424 .vendor = PCI_VENDOR_ID_JMICRON,
425 .device = PCI_DEVICE_ID_JMICRON_JMB38X_MMC,
426 .subvendor = PCI_ANY_ID,
427 .subdevice = PCI_ANY_ID,
428 .driver_data = (kernel_ulong_t)&sdhci_jmicron,
429 },
430
Harald Welte557b0692009-06-18 16:53:38 +0200431 {
Nicolas Pitrea7a61862009-12-14 18:01:26 -0800432 .vendor = PCI_VENDOR_ID_SYSKONNECT,
433 .device = 0x8000,
434 .subvendor = PCI_ANY_ID,
435 .subdevice = PCI_ANY_ID,
436 .driver_data = (kernel_ulong_t)&sdhci_syskt,
437 },
438
439 {
Harald Welte557b0692009-06-18 16:53:38 +0200440 .vendor = PCI_VENDOR_ID_VIA,
441 .device = 0x95d0,
442 .subvendor = PCI_ANY_ID,
443 .subdevice = PCI_ANY_ID,
444 .driver_data = (kernel_ulong_t)&sdhci_via,
445 },
446
Pierre Ossman22606402008-03-23 19:33:23 +0100447 { /* Generic SD host controller */
448 PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
449 },
450
451 { /* end: all zeroes */ },
452};
453
454MODULE_DEVICE_TABLE(pci, pci_ids);
455
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100456/*****************************************************************************\
457 * *
458 * SDHCI core callbacks *
459 * *
460\*****************************************************************************/
461
462static int sdhci_pci_enable_dma(struct sdhci_host *host)
463{
464 struct sdhci_pci_slot *slot;
465 struct pci_dev *pdev;
466 int ret;
467
468 slot = sdhci_priv(host);
469 pdev = slot->chip->pdev;
470
471 if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) &&
472 ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) &&
Richard Röjforsa13abc72009-09-22 16:45:30 -0700473 (host->flags & SDHCI_USE_SDMA)) {
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100474 dev_warn(&pdev->dev, "Will use DMA mode even though HW "
475 "doesn't fully claim to support it.\n");
476 }
477
Yang Hongyang284901a2009-04-06 19:01:15 -0700478 ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100479 if (ret)
480 return ret;
481
482 pci_set_master(pdev);
483
484 return 0;
485}
486
487static struct sdhci_ops sdhci_pci_ops = {
488 .enable_dma = sdhci_pci_enable_dma,
489};
490
491/*****************************************************************************\
492 * *
493 * Suspend/resume *
494 * *
495\*****************************************************************************/
496
497#ifdef CONFIG_PM
498
499static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
500{
501 struct sdhci_pci_chip *chip;
502 struct sdhci_pci_slot *slot;
Nicolas Pitre2f4cbb32010-03-05 13:43:32 -0800503 mmc_pm_flag_t pm_flags = 0;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100504 int i, ret;
505
506 chip = pci_get_drvdata(pdev);
507 if (!chip)
508 return 0;
509
510 for (i = 0;i < chip->num_slots;i++) {
511 slot = chip->slots[i];
512 if (!slot)
513 continue;
514
515 ret = sdhci_suspend_host(slot->host, state);
516
517 if (ret) {
518 for (i--;i >= 0;i--)
519 sdhci_resume_host(chip->slots[i]->host);
520 return ret;
521 }
Nicolas Pitre2f4cbb32010-03-05 13:43:32 -0800522
523 pm_flags |= slot->host->mmc->pm_flags;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100524 }
525
Pierre Ossman44894282008-04-04 19:36:59 +0200526 if (chip->fixes && chip->fixes->suspend) {
527 ret = chip->fixes->suspend(chip, state);
528 if (ret) {
529 for (i = chip->num_slots - 1;i >= 0;i--)
530 sdhci_resume_host(chip->slots[i]->host);
531 return ret;
532 }
533 }
534
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100535 pci_save_state(pdev);
Nicolas Pitre2f4cbb32010-03-05 13:43:32 -0800536 if (pm_flags & MMC_PM_KEEP_POWER) {
537 if (pm_flags & MMC_PM_WAKE_SDIO_IRQ)
538 pci_enable_wake(pdev, PCI_D3hot, 1);
539 pci_set_power_state(pdev, PCI_D3hot);
540 } else {
541 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
542 pci_disable_device(pdev);
543 pci_set_power_state(pdev, pci_choose_state(pdev, state));
544 }
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100545
546 return 0;
547}
548
549static int sdhci_pci_resume (struct pci_dev *pdev)
550{
551 struct sdhci_pci_chip *chip;
552 struct sdhci_pci_slot *slot;
553 int i, ret;
554
555 chip = pci_get_drvdata(pdev);
556 if (!chip)
557 return 0;
558
559 pci_set_power_state(pdev, PCI_D0);
560 pci_restore_state(pdev);
561 ret = pci_enable_device(pdev);
562 if (ret)
563 return ret;
564
Pierre Ossman45211e22008-03-24 13:09:09 +0100565 if (chip->fixes && chip->fixes->resume) {
566 ret = chip->fixes->resume(chip);
567 if (ret)
568 return ret;
569 }
570
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100571 for (i = 0;i < chip->num_slots;i++) {
572 slot = chip->slots[i];
573 if (!slot)
574 continue;
575
576 ret = sdhci_resume_host(slot->host);
577 if (ret)
578 return ret;
579 }
580
581 return 0;
582}
583
584#else /* CONFIG_PM */
585
586#define sdhci_pci_suspend NULL
587#define sdhci_pci_resume NULL
588
589#endif /* CONFIG_PM */
590
591/*****************************************************************************\
592 * *
593 * Device probing/removal *
594 * *
595\*****************************************************************************/
596
597static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
598 struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar)
599{
600 struct sdhci_pci_slot *slot;
601 struct sdhci_host *host;
602
603 resource_size_t addr;
604
605 int ret;
606
607 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
608 dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
609 return ERR_PTR(-ENODEV);
610 }
611
612 if (pci_resource_len(pdev, bar) != 0x100) {
613 dev_err(&pdev->dev, "Invalid iomem size. You may "
614 "experience problems.\n");
615 }
616
617 if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
618 dev_err(&pdev->dev, "Vendor specific interface. Aborting.\n");
619 return ERR_PTR(-ENODEV);
620 }
621
622 if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) {
623 dev_err(&pdev->dev, "Unknown interface. Aborting.\n");
624 return ERR_PTR(-ENODEV);
625 }
626
627 host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot));
628 if (IS_ERR(host)) {
Dan Carpenterc60a32c2009-04-10 23:31:10 +0200629 dev_err(&pdev->dev, "cannot allocate host\n");
630 return ERR_PTR(PTR_ERR(host));
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100631 }
632
633 slot = sdhci_priv(host);
634
635 slot->chip = chip;
636 slot->host = host;
637 slot->pci_bar = bar;
638
639 host->hw_name = "PCI";
640 host->ops = &sdhci_pci_ops;
641 host->quirks = chip->quirks;
642
643 host->irq = pdev->irq;
644
645 ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
646 if (ret) {
647 dev_err(&pdev->dev, "cannot request region\n");
Dan Carpenterc60a32c2009-04-10 23:31:10 +0200648 goto free;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100649 }
650
651 addr = pci_resource_start(pdev, bar);
Arjan van de Ven092f82e2008-09-28 16:15:56 -0700652 host->ioaddr = pci_ioremap_bar(pdev, bar);
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100653 if (!host->ioaddr) {
654 dev_err(&pdev->dev, "failed to remap registers\n");
655 goto release;
656 }
657
Pierre Ossman44894282008-04-04 19:36:59 +0200658 if (chip->fixes && chip->fixes->probe_slot) {
659 ret = chip->fixes->probe_slot(slot);
660 if (ret)
661 goto unmap;
662 }
663
Nicolas Pitre2f4cbb32010-03-05 13:43:32 -0800664 host->mmc->pm_caps = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
665
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100666 ret = sdhci_add_host(host);
667 if (ret)
Pierre Ossman44894282008-04-04 19:36:59 +0200668 goto remove;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100669
670 return slot;
671
Pierre Ossman44894282008-04-04 19:36:59 +0200672remove:
673 if (chip->fixes && chip->fixes->remove_slot)
Pierre Ossman1e728592008-04-16 19:13:13 +0200674 chip->fixes->remove_slot(slot, 0);
Pierre Ossman44894282008-04-04 19:36:59 +0200675
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100676unmap:
677 iounmap(host->ioaddr);
678
679release:
680 pci_release_region(pdev, bar);
Dan Carpenterc60a32c2009-04-10 23:31:10 +0200681
682free:
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100683 sdhci_free_host(host);
684
685 return ERR_PTR(ret);
686}
687
688static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
689{
Pierre Ossman1e728592008-04-16 19:13:13 +0200690 int dead;
691 u32 scratch;
692
693 dead = 0;
694 scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
695 if (scratch == (u32)-1)
696 dead = 1;
697
698 sdhci_remove_host(slot->host, dead);
Pierre Ossman44894282008-04-04 19:36:59 +0200699
700 if (slot->chip->fixes && slot->chip->fixes->remove_slot)
Pierre Ossman1e728592008-04-16 19:13:13 +0200701 slot->chip->fixes->remove_slot(slot, dead);
Pierre Ossman44894282008-04-04 19:36:59 +0200702
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100703 pci_release_region(slot->chip->pdev, slot->pci_bar);
Pierre Ossman44894282008-04-04 19:36:59 +0200704
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100705 sdhci_free_host(slot->host);
706}
707
708static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
709 const struct pci_device_id *ent)
710{
711 struct sdhci_pci_chip *chip;
712 struct sdhci_pci_slot *slot;
713
714 u8 slots, rev, first_bar;
715 int ret, i;
716
717 BUG_ON(pdev == NULL);
718 BUG_ON(ent == NULL);
719
720 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
721
722 dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n",
723 (int)pdev->vendor, (int)pdev->device, (int)rev);
724
725 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
726 if (ret)
727 return ret;
728
729 slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
730 dev_dbg(&pdev->dev, "found %d slot(s)\n", slots);
731 if (slots == 0)
732 return -ENODEV;
733
734 BUG_ON(slots > MAX_SLOTS);
735
736 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
737 if (ret)
738 return ret;
739
740 first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
741
742 if (first_bar > 5) {
743 dev_err(&pdev->dev, "Invalid first BAR. Aborting.\n");
744 return -ENODEV;
745 }
746
747 ret = pci_enable_device(pdev);
748 if (ret)
749 return ret;
750
751 chip = kzalloc(sizeof(struct sdhci_pci_chip), GFP_KERNEL);
752 if (!chip) {
753 ret = -ENOMEM;
754 goto err;
755 }
756
757 chip->pdev = pdev;
Pierre Ossman22606402008-03-23 19:33:23 +0100758 chip->fixes = (const struct sdhci_pci_fixes*)ent->driver_data;
759 if (chip->fixes)
760 chip->quirks = chip->fixes->quirks;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100761 chip->num_slots = slots;
762
763 pci_set_drvdata(pdev, chip);
764
Pierre Ossman22606402008-03-23 19:33:23 +0100765 if (chip->fixes && chip->fixes->probe) {
766 ret = chip->fixes->probe(chip);
767 if (ret)
768 goto free;
769 }
770
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100771 for (i = 0;i < slots;i++) {
772 slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
773 if (IS_ERR(slot)) {
774 for (i--;i >= 0;i--)
775 sdhci_pci_remove_slot(chip->slots[i]);
776 ret = PTR_ERR(slot);
777 goto free;
778 }
779
780 chip->slots[i] = slot;
781 }
782
783 return 0;
784
785free:
786 pci_set_drvdata(pdev, NULL);
787 kfree(chip);
788
789err:
790 pci_disable_device(pdev);
791 return ret;
792}
793
794static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
795{
796 int i;
797 struct sdhci_pci_chip *chip;
798
799 chip = pci_get_drvdata(pdev);
800
801 if (chip) {
802 for (i = 0;i < chip->num_slots; i++)
803 sdhci_pci_remove_slot(chip->slots[i]);
804
805 pci_set_drvdata(pdev, NULL);
806 kfree(chip);
807 }
808
809 pci_disable_device(pdev);
810}
811
812static struct pci_driver sdhci_driver = {
813 .name = "sdhci-pci",
814 .id_table = pci_ids,
815 .probe = sdhci_pci_probe,
816 .remove = __devexit_p(sdhci_pci_remove),
817 .suspend = sdhci_pci_suspend,
818 .resume = sdhci_pci_resume,
819};
820
821/*****************************************************************************\
822 * *
823 * Driver init/exit *
824 * *
825\*****************************************************************************/
826
827static int __init sdhci_drv_init(void)
828{
829 return pci_register_driver(&sdhci_driver);
830}
831
832static void __exit sdhci_drv_exit(void)
833{
834 pci_unregister_driver(&sdhci_driver);
835}
836
837module_init(sdhci_drv_init);
838module_exit(sdhci_drv_exit);
839
Pierre Ossman32710e82009-04-08 20:14:54 +0200840MODULE_AUTHOR("Pierre Ossman <pierre@ossman.eu>");
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100841MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
842MODULE_LICENSE("GPL");