blob: c0fbf48d9b4529be7baff025032a7bc2722bcde9 [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{
83 if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM)
84 chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET;
85
86 if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG)
87 chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET;
88
89 return 0;
90}
91
92static const struct sdhci_pci_fixes sdhci_ricoh = {
93 .probe = ricoh_probe,
Pierre Ossman309d9732008-05-28 09:54:50 +020094 .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR,
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 |
Pierre Ossmanee53ab52008-07-05 00:25:15 +0200110 SDHCI_QUIRK_BROKEN_TIMEOUT_VAL,
Pierre Ossman22606402008-03-23 19:33:23 +0100111};
112
Pierre Ossman45211e22008-03-24 13:09:09 +0100113static int jmicron_pmos(struct sdhci_pci_chip *chip, int on)
114{
115 u8 scratch;
116 int ret;
117
118 ret = pci_read_config_byte(chip->pdev, 0xAE, &scratch);
119 if (ret)
120 return ret;
121
122 /*
123 * Turn PMOS on [bit 0], set over current detection to 2.4 V
124 * [bit 1:2] and enable over current debouncing [bit 6].
125 */
126 if (on)
127 scratch |= 0x47;
128 else
129 scratch &= ~0x47;
130
131 ret = pci_write_config_byte(chip->pdev, 0xAE, scratch);
132 if (ret)
133 return ret;
134
135 return 0;
136}
137
138static int jmicron_probe(struct sdhci_pci_chip *chip)
139{
140 int ret;
141
142 /*
Pierre Ossman44894282008-04-04 19:36:59 +0200143 * JMicron chips can have two interfaces to the same hardware
144 * in order to work around limitations in Microsoft's driver.
145 * We need to make sure we only bind to one of them.
146 *
147 * This code assumes two things:
148 *
149 * 1. The PCI code adds subfunctions in order.
150 *
151 * 2. The MMC interface has a lower subfunction number
152 * than the SD interface.
153 */
154 if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD) {
155 struct pci_dev *sd_dev;
156
157 sd_dev = NULL;
158 while ((sd_dev = pci_get_device(PCI_VENDOR_ID_JMICRON,
159 PCI_DEVICE_ID_JMICRON_JMB38X_MMC, sd_dev)) != NULL) {
160 if ((PCI_SLOT(chip->pdev->devfn) ==
161 PCI_SLOT(sd_dev->devfn)) &&
162 (chip->pdev->bus == sd_dev->bus))
163 break;
164 }
165
166 if (sd_dev) {
167 pci_dev_put(sd_dev);
168 dev_info(&chip->pdev->dev, "Refusing to bind to "
169 "secondary interface.\n");
170 return -ENODEV;
171 }
172 }
173
174 /*
Pierre Ossman45211e22008-03-24 13:09:09 +0100175 * JMicron chips need a bit of a nudge to enable the power
176 * output pins.
177 */
178 ret = jmicron_pmos(chip, 1);
179 if (ret) {
180 dev_err(&chip->pdev->dev, "Failure enabling card power\n");
181 return ret;
182 }
183
184 return 0;
185}
186
Pierre Ossman44894282008-04-04 19:36:59 +0200187static void jmicron_enable_mmc(struct sdhci_host *host, int on)
188{
189 u8 scratch;
190
191 scratch = readb(host->ioaddr + 0xC0);
192
193 if (on)
194 scratch |= 0x01;
195 else
196 scratch &= ~0x01;
197
198 writeb(scratch, host->ioaddr + 0xC0);
199}
200
201static int jmicron_probe_slot(struct sdhci_pci_slot *slot)
202{
203 /*
204 * The secondary interface requires a bit set to get the
205 * interrupts.
206 */
207 if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
208 jmicron_enable_mmc(slot->host, 1);
209
210 return 0;
211}
212
Pierre Ossman1e728592008-04-16 19:13:13 +0200213static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead)
Pierre Ossman44894282008-04-04 19:36:59 +0200214{
Pierre Ossman1e728592008-04-16 19:13:13 +0200215 if (dead)
216 return;
217
Pierre Ossman44894282008-04-04 19:36:59 +0200218 if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC)
219 jmicron_enable_mmc(slot->host, 0);
220}
221
222static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state)
223{
224 int i;
225
226 if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
227 for (i = 0;i < chip->num_slots;i++)
228 jmicron_enable_mmc(chip->slots[i]->host, 0);
229 }
230
231 return 0;
232}
233
Pierre Ossman45211e22008-03-24 13:09:09 +0100234static int jmicron_resume(struct sdhci_pci_chip *chip)
235{
Pierre Ossman44894282008-04-04 19:36:59 +0200236 int ret, i;
237
238 if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) {
239 for (i = 0;i < chip->num_slots;i++)
240 jmicron_enable_mmc(chip->slots[i]->host, 1);
241 }
Pierre Ossman45211e22008-03-24 13:09:09 +0100242
243 ret = jmicron_pmos(chip, 1);
244 if (ret) {
245 dev_err(&chip->pdev->dev, "Failure enabling card power\n");
246 return ret;
247 }
248
249 return 0;
250}
251
Pierre Ossman22606402008-03-23 19:33:23 +0100252static const struct sdhci_pci_fixes sdhci_jmicron = {
253 .quirks = SDHCI_QUIRK_32BIT_DMA_ADDR |
254 SDHCI_QUIRK_32BIT_DMA_SIZE |
255 SDHCI_QUIRK_RESET_AFTER_REQUEST,
Pierre Ossman45211e22008-03-24 13:09:09 +0100256
257 .probe = jmicron_probe,
258
Pierre Ossman44894282008-04-04 19:36:59 +0200259 .probe_slot = jmicron_probe_slot,
260 .remove_slot = jmicron_remove_slot,
261
262 .suspend = jmicron_suspend,
Pierre Ossman45211e22008-03-24 13:09:09 +0100263 .resume = jmicron_resume,
Pierre Ossman22606402008-03-23 19:33:23 +0100264};
265
266static const struct pci_device_id pci_ids[] __devinitdata = {
267 {
268 .vendor = PCI_VENDOR_ID_RICOH,
269 .device = PCI_DEVICE_ID_RICOH_R5C822,
270 .subvendor = PCI_ANY_ID,
271 .subdevice = PCI_ANY_ID,
272 .driver_data = (kernel_ulong_t)&sdhci_ricoh,
273 },
274
275 {
276 .vendor = PCI_VENDOR_ID_ENE,
277 .device = PCI_DEVICE_ID_ENE_CB712_SD,
278 .subvendor = PCI_ANY_ID,
279 .subdevice = PCI_ANY_ID,
280 .driver_data = (kernel_ulong_t)&sdhci_ene_712,
281 },
282
283 {
284 .vendor = PCI_VENDOR_ID_ENE,
285 .device = PCI_DEVICE_ID_ENE_CB712_SD_2,
286 .subvendor = PCI_ANY_ID,
287 .subdevice = PCI_ANY_ID,
288 .driver_data = (kernel_ulong_t)&sdhci_ene_712,
289 },
290
291 {
292 .vendor = PCI_VENDOR_ID_ENE,
293 .device = PCI_DEVICE_ID_ENE_CB714_SD,
294 .subvendor = PCI_ANY_ID,
295 .subdevice = PCI_ANY_ID,
296 .driver_data = (kernel_ulong_t)&sdhci_ene_714,
297 },
298
299 {
300 .vendor = PCI_VENDOR_ID_ENE,
301 .device = PCI_DEVICE_ID_ENE_CB714_SD_2,
302 .subvendor = PCI_ANY_ID,
303 .subdevice = PCI_ANY_ID,
304 .driver_data = (kernel_ulong_t)&sdhci_ene_714,
305 },
306
307 {
308 .vendor = PCI_VENDOR_ID_MARVELL,
309 .device = PCI_DEVICE_ID_MARVELL_CAFE_SD,
310 .subvendor = PCI_ANY_ID,
311 .subdevice = PCI_ANY_ID,
312 .driver_data = (kernel_ulong_t)&sdhci_cafe,
313 },
314
315 {
316 .vendor = PCI_VENDOR_ID_JMICRON,
317 .device = PCI_DEVICE_ID_JMICRON_JMB38X_SD,
318 .subvendor = PCI_ANY_ID,
319 .subdevice = PCI_ANY_ID,
320 .driver_data = (kernel_ulong_t)&sdhci_jmicron,
321 },
322
Pierre Ossman44894282008-04-04 19:36:59 +0200323 {
324 .vendor = PCI_VENDOR_ID_JMICRON,
325 .device = PCI_DEVICE_ID_JMICRON_JMB38X_MMC,
326 .subvendor = PCI_ANY_ID,
327 .subdevice = PCI_ANY_ID,
328 .driver_data = (kernel_ulong_t)&sdhci_jmicron,
329 },
330
Pierre Ossman22606402008-03-23 19:33:23 +0100331 { /* Generic SD host controller */
332 PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00)
333 },
334
335 { /* end: all zeroes */ },
336};
337
338MODULE_DEVICE_TABLE(pci, pci_ids);
339
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100340/*****************************************************************************\
341 * *
342 * SDHCI core callbacks *
343 * *
344\*****************************************************************************/
345
346static int sdhci_pci_enable_dma(struct sdhci_host *host)
347{
348 struct sdhci_pci_slot *slot;
349 struct pci_dev *pdev;
350 int ret;
351
352 slot = sdhci_priv(host);
353 pdev = slot->chip->pdev;
354
355 if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) &&
356 ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) &&
357 (host->flags & SDHCI_USE_DMA)) {
358 dev_warn(&pdev->dev, "Will use DMA mode even though HW "
359 "doesn't fully claim to support it.\n");
360 }
361
362 ret = pci_set_dma_mask(pdev, DMA_32BIT_MASK);
363 if (ret)
364 return ret;
365
366 pci_set_master(pdev);
367
368 return 0;
369}
370
371static struct sdhci_ops sdhci_pci_ops = {
372 .enable_dma = sdhci_pci_enable_dma,
373};
374
375/*****************************************************************************\
376 * *
377 * Suspend/resume *
378 * *
379\*****************************************************************************/
380
381#ifdef CONFIG_PM
382
383static int sdhci_pci_suspend (struct pci_dev *pdev, pm_message_t state)
384{
385 struct sdhci_pci_chip *chip;
386 struct sdhci_pci_slot *slot;
387 int i, ret;
388
389 chip = pci_get_drvdata(pdev);
390 if (!chip)
391 return 0;
392
393 for (i = 0;i < chip->num_slots;i++) {
394 slot = chip->slots[i];
395 if (!slot)
396 continue;
397
398 ret = sdhci_suspend_host(slot->host, state);
399
400 if (ret) {
401 for (i--;i >= 0;i--)
402 sdhci_resume_host(chip->slots[i]->host);
403 return ret;
404 }
405 }
406
Pierre Ossman44894282008-04-04 19:36:59 +0200407 if (chip->fixes && chip->fixes->suspend) {
408 ret = chip->fixes->suspend(chip, state);
409 if (ret) {
410 for (i = chip->num_slots - 1;i >= 0;i--)
411 sdhci_resume_host(chip->slots[i]->host);
412 return ret;
413 }
414 }
415
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100416 pci_save_state(pdev);
417 pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
418 pci_disable_device(pdev);
419 pci_set_power_state(pdev, pci_choose_state(pdev, state));
420
421 return 0;
422}
423
424static int sdhci_pci_resume (struct pci_dev *pdev)
425{
426 struct sdhci_pci_chip *chip;
427 struct sdhci_pci_slot *slot;
428 int i, ret;
429
430 chip = pci_get_drvdata(pdev);
431 if (!chip)
432 return 0;
433
434 pci_set_power_state(pdev, PCI_D0);
435 pci_restore_state(pdev);
436 ret = pci_enable_device(pdev);
437 if (ret)
438 return ret;
439
Pierre Ossman45211e22008-03-24 13:09:09 +0100440 if (chip->fixes && chip->fixes->resume) {
441 ret = chip->fixes->resume(chip);
442 if (ret)
443 return ret;
444 }
445
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100446 for (i = 0;i < chip->num_slots;i++) {
447 slot = chip->slots[i];
448 if (!slot)
449 continue;
450
451 ret = sdhci_resume_host(slot->host);
452 if (ret)
453 return ret;
454 }
455
456 return 0;
457}
458
459#else /* CONFIG_PM */
460
461#define sdhci_pci_suspend NULL
462#define sdhci_pci_resume NULL
463
464#endif /* CONFIG_PM */
465
466/*****************************************************************************\
467 * *
468 * Device probing/removal *
469 * *
470\*****************************************************************************/
471
472static struct sdhci_pci_slot * __devinit sdhci_pci_probe_slot(
473 struct pci_dev *pdev, struct sdhci_pci_chip *chip, int bar)
474{
475 struct sdhci_pci_slot *slot;
476 struct sdhci_host *host;
477
478 resource_size_t addr;
479
480 int ret;
481
482 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
483 dev_err(&pdev->dev, "BAR %d is not iomem. Aborting.\n", bar);
484 return ERR_PTR(-ENODEV);
485 }
486
487 if (pci_resource_len(pdev, bar) != 0x100) {
488 dev_err(&pdev->dev, "Invalid iomem size. You may "
489 "experience problems.\n");
490 }
491
492 if ((pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) {
493 dev_err(&pdev->dev, "Vendor specific interface. Aborting.\n");
494 return ERR_PTR(-ENODEV);
495 }
496
497 if ((pdev->class & 0x0000FF) > PCI_SDHCI_IFVENDOR) {
498 dev_err(&pdev->dev, "Unknown interface. Aborting.\n");
499 return ERR_PTR(-ENODEV);
500 }
501
502 host = sdhci_alloc_host(&pdev->dev, sizeof(struct sdhci_pci_slot));
503 if (IS_ERR(host)) {
504 ret = PTR_ERR(host);
505 goto unmap;
506 }
507
508 slot = sdhci_priv(host);
509
510 slot->chip = chip;
511 slot->host = host;
512 slot->pci_bar = bar;
513
514 host->hw_name = "PCI";
515 host->ops = &sdhci_pci_ops;
516 host->quirks = chip->quirks;
517
518 host->irq = pdev->irq;
519
520 ret = pci_request_region(pdev, bar, mmc_hostname(host->mmc));
521 if (ret) {
522 dev_err(&pdev->dev, "cannot request region\n");
523 return ERR_PTR(ret);
524 }
525
526 addr = pci_resource_start(pdev, bar);
527 host->ioaddr = ioremap_nocache(addr, pci_resource_len(pdev, bar));
528 if (!host->ioaddr) {
529 dev_err(&pdev->dev, "failed to remap registers\n");
530 goto release;
531 }
532
Pierre Ossman44894282008-04-04 19:36:59 +0200533 if (chip->fixes && chip->fixes->probe_slot) {
534 ret = chip->fixes->probe_slot(slot);
535 if (ret)
536 goto unmap;
537 }
538
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100539 ret = sdhci_add_host(host);
540 if (ret)
Pierre Ossman44894282008-04-04 19:36:59 +0200541 goto remove;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100542
543 return slot;
544
Pierre Ossman44894282008-04-04 19:36:59 +0200545remove:
546 if (chip->fixes && chip->fixes->remove_slot)
Pierre Ossman1e728592008-04-16 19:13:13 +0200547 chip->fixes->remove_slot(slot, 0);
Pierre Ossman44894282008-04-04 19:36:59 +0200548
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100549unmap:
550 iounmap(host->ioaddr);
551
552release:
553 pci_release_region(pdev, bar);
554 sdhci_free_host(host);
555
556 return ERR_PTR(ret);
557}
558
559static void sdhci_pci_remove_slot(struct sdhci_pci_slot *slot)
560{
Pierre Ossman1e728592008-04-16 19:13:13 +0200561 int dead;
562 u32 scratch;
563
564 dead = 0;
565 scratch = readl(slot->host->ioaddr + SDHCI_INT_STATUS);
566 if (scratch == (u32)-1)
567 dead = 1;
568
569 sdhci_remove_host(slot->host, dead);
Pierre Ossman44894282008-04-04 19:36:59 +0200570
571 if (slot->chip->fixes && slot->chip->fixes->remove_slot)
Pierre Ossman1e728592008-04-16 19:13:13 +0200572 slot->chip->fixes->remove_slot(slot, dead);
Pierre Ossman44894282008-04-04 19:36:59 +0200573
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100574 pci_release_region(slot->chip->pdev, slot->pci_bar);
Pierre Ossman44894282008-04-04 19:36:59 +0200575
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100576 sdhci_free_host(slot->host);
577}
578
579static int __devinit sdhci_pci_probe(struct pci_dev *pdev,
580 const struct pci_device_id *ent)
581{
582 struct sdhci_pci_chip *chip;
583 struct sdhci_pci_slot *slot;
584
585 u8 slots, rev, first_bar;
586 int ret, i;
587
588 BUG_ON(pdev == NULL);
589 BUG_ON(ent == NULL);
590
591 pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
592
593 dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n",
594 (int)pdev->vendor, (int)pdev->device, (int)rev);
595
596 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
597 if (ret)
598 return ret;
599
600 slots = PCI_SLOT_INFO_SLOTS(slots) + 1;
601 dev_dbg(&pdev->dev, "found %d slot(s)\n", slots);
602 if (slots == 0)
603 return -ENODEV;
604
605 BUG_ON(slots > MAX_SLOTS);
606
607 ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &first_bar);
608 if (ret)
609 return ret;
610
611 first_bar &= PCI_SLOT_INFO_FIRST_BAR_MASK;
612
613 if (first_bar > 5) {
614 dev_err(&pdev->dev, "Invalid first BAR. Aborting.\n");
615 return -ENODEV;
616 }
617
618 ret = pci_enable_device(pdev);
619 if (ret)
620 return ret;
621
622 chip = kzalloc(sizeof(struct sdhci_pci_chip), GFP_KERNEL);
623 if (!chip) {
624 ret = -ENOMEM;
625 goto err;
626 }
627
628 chip->pdev = pdev;
Pierre Ossman22606402008-03-23 19:33:23 +0100629 chip->fixes = (const struct sdhci_pci_fixes*)ent->driver_data;
630 if (chip->fixes)
631 chip->quirks = chip->fixes->quirks;
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100632 chip->num_slots = slots;
633
634 pci_set_drvdata(pdev, chip);
635
Pierre Ossman22606402008-03-23 19:33:23 +0100636 if (chip->fixes && chip->fixes->probe) {
637 ret = chip->fixes->probe(chip);
638 if (ret)
639 goto free;
640 }
641
Pierre Ossmanb8c86fc2008-03-18 17:35:49 +0100642 for (i = 0;i < slots;i++) {
643 slot = sdhci_pci_probe_slot(pdev, chip, first_bar + i);
644 if (IS_ERR(slot)) {
645 for (i--;i >= 0;i--)
646 sdhci_pci_remove_slot(chip->slots[i]);
647 ret = PTR_ERR(slot);
648 goto free;
649 }
650
651 chip->slots[i] = slot;
652 }
653
654 return 0;
655
656free:
657 pci_set_drvdata(pdev, NULL);
658 kfree(chip);
659
660err:
661 pci_disable_device(pdev);
662 return ret;
663}
664
665static void __devexit sdhci_pci_remove(struct pci_dev *pdev)
666{
667 int i;
668 struct sdhci_pci_chip *chip;
669
670 chip = pci_get_drvdata(pdev);
671
672 if (chip) {
673 for (i = 0;i < chip->num_slots; i++)
674 sdhci_pci_remove_slot(chip->slots[i]);
675
676 pci_set_drvdata(pdev, NULL);
677 kfree(chip);
678 }
679
680 pci_disable_device(pdev);
681}
682
683static struct pci_driver sdhci_driver = {
684 .name = "sdhci-pci",
685 .id_table = pci_ids,
686 .probe = sdhci_pci_probe,
687 .remove = __devexit_p(sdhci_pci_remove),
688 .suspend = sdhci_pci_suspend,
689 .resume = sdhci_pci_resume,
690};
691
692/*****************************************************************************\
693 * *
694 * Driver init/exit *
695 * *
696\*****************************************************************************/
697
698static int __init sdhci_drv_init(void)
699{
700 return pci_register_driver(&sdhci_driver);
701}
702
703static void __exit sdhci_drv_exit(void)
704{
705 pci_unregister_driver(&sdhci_driver);
706}
707
708module_init(sdhci_drv_init);
709module_exit(sdhci_drv_exit);
710
711MODULE_AUTHOR("Pierre Ossman <drzeus@drzeus.cx>");
712MODULE_DESCRIPTION("Secure Digital Host Controller Interface PCI driver");
713MODULE_LICENSE("GPL");