diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pci.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 191 |
1 files changed, 58 insertions, 133 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 8f753811fc7a..0955777b6c7e 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -27,79 +27,8 @@ | |||
27 | #include <linux/mmc/sdhci-pci-data.h> | 27 | #include <linux/mmc/sdhci-pci-data.h> |
28 | 28 | ||
29 | #include "sdhci.h" | 29 | #include "sdhci.h" |
30 | 30 | #include "sdhci-pci.h" | |
31 | /* | 31 | #include "sdhci-pci-o2micro.h" |
32 | * PCI device IDs | ||
33 | */ | ||
34 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO0 0x8809 | ||
35 | #define PCI_DEVICE_ID_INTEL_PCH_SDIO1 0x880a | ||
36 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC 0x0f14 | ||
37 | #define PCI_DEVICE_ID_INTEL_BYT_SDIO 0x0f15 | ||
38 | #define PCI_DEVICE_ID_INTEL_BYT_SD 0x0f16 | ||
39 | #define PCI_DEVICE_ID_INTEL_BYT_EMMC2 0x0f50 | ||
40 | #define PCI_DEVICE_ID_INTEL_MRFL_MMC 0x1190 | ||
41 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO0 0x08f9 | ||
42 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO1 0x08fa | ||
43 | #define PCI_DEVICE_ID_INTEL_CLV_SDIO2 0x08fb | ||
44 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC0 0x08e5 | ||
45 | #define PCI_DEVICE_ID_INTEL_CLV_EMMC1 0x08e6 | ||
46 | |||
47 | /* | ||
48 | * PCI registers | ||
49 | */ | ||
50 | |||
51 | #define PCI_SDHCI_IFPIO 0x00 | ||
52 | #define PCI_SDHCI_IFDMA 0x01 | ||
53 | #define PCI_SDHCI_IFVENDOR 0x02 | ||
54 | |||
55 | #define PCI_SLOT_INFO 0x40 /* 8 bits */ | ||
56 | #define PCI_SLOT_INFO_SLOTS(x) ((x >> 4) & 7) | ||
57 | #define PCI_SLOT_INFO_FIRST_BAR_MASK 0x07 | ||
58 | |||
59 | #define MAX_SLOTS 8 | ||
60 | |||
61 | struct sdhci_pci_chip; | ||
62 | struct sdhci_pci_slot; | ||
63 | |||
64 | struct sdhci_pci_fixes { | ||
65 | unsigned int quirks; | ||
66 | unsigned int quirks2; | ||
67 | bool allow_runtime_pm; | ||
68 | |||
69 | int (*probe) (struct sdhci_pci_chip *); | ||
70 | |||
71 | int (*probe_slot) (struct sdhci_pci_slot *); | ||
72 | void (*remove_slot) (struct sdhci_pci_slot *, int); | ||
73 | |||
74 | int (*suspend) (struct sdhci_pci_chip *); | ||
75 | int (*resume) (struct sdhci_pci_chip *); | ||
76 | }; | ||
77 | |||
78 | struct sdhci_pci_slot { | ||
79 | struct sdhci_pci_chip *chip; | ||
80 | struct sdhci_host *host; | ||
81 | struct sdhci_pci_data *data; | ||
82 | |||
83 | int pci_bar; | ||
84 | int rst_n_gpio; | ||
85 | int cd_gpio; | ||
86 | int cd_irq; | ||
87 | |||
88 | void (*hw_reset)(struct sdhci_host *host); | ||
89 | }; | ||
90 | |||
91 | struct sdhci_pci_chip { | ||
92 | struct pci_dev *pdev; | ||
93 | |||
94 | unsigned int quirks; | ||
95 | unsigned int quirks2; | ||
96 | bool allow_runtime_pm; | ||
97 | const struct sdhci_pci_fixes *fixes; | ||
98 | |||
99 | int num_slots; /* Slots on controller */ | ||
100 | struct sdhci_pci_slot *slots[MAX_SLOTS]; /* Pointers to host slots */ | ||
101 | }; | ||
102 | |||
103 | 32 | ||
104 | /*****************************************************************************\ | 33 | /*****************************************************************************\ |
105 | * * | 34 | * * |
@@ -296,6 +225,7 @@ static const struct sdhci_pci_fixes sdhci_intel_mrst_hc1_hc2 = { | |||
296 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { | 225 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sd = { |
297 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 226 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
298 | .allow_runtime_pm = true, | 227 | .allow_runtime_pm = true, |
228 | .own_cd_for_runtime_pm = true, | ||
299 | }; | 229 | }; |
300 | 230 | ||
301 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { | 231 | static const struct sdhci_pci_fixes sdhci_intel_mfd_sdio = { |
@@ -360,6 +290,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = { | |||
360 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { | 290 | static const struct sdhci_pci_fixes sdhci_intel_byt_sd = { |
361 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, | 291 | .quirks2 = SDHCI_QUIRK2_CARD_ON_NEEDS_BUS_ON, |
362 | .allow_runtime_pm = true, | 292 | .allow_runtime_pm = true, |
293 | .own_cd_for_runtime_pm = true, | ||
363 | }; | 294 | }; |
364 | 295 | ||
365 | /* Define Host controllers for Intel Merrifield platform */ | 296 | /* Define Host controllers for Intel Merrifield platform */ |
@@ -381,6 +312,7 @@ static int intel_mrfl_mmc_probe_slot(struct sdhci_pci_slot *slot) | |||
381 | 312 | ||
382 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | 313 | static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { |
383 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 314 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
315 | .quirks2 = SDHCI_QUIRK2_BROKEN_HS200, | ||
384 | .probe_slot = intel_mrfl_mmc_probe_slot, | 316 | .probe_slot = intel_mrfl_mmc_probe_slot, |
385 | }; | 317 | }; |
386 | 318 | ||
@@ -393,65 +325,6 @@ static const struct sdhci_pci_fixes sdhci_intel_mrfl_mmc = { | |||
393 | #define O2_SD_ADMA2 0xE7 | 325 | #define O2_SD_ADMA2 0xE7 |
394 | #define O2_SD_INF_MOD 0xF1 | 326 | #define O2_SD_INF_MOD 0xF1 |
395 | 327 | ||
396 | static int o2_probe(struct sdhci_pci_chip *chip) | ||
397 | { | ||
398 | int ret; | ||
399 | u8 scratch; | ||
400 | |||
401 | switch (chip->pdev->device) { | ||
402 | case PCI_DEVICE_ID_O2_8220: | ||
403 | case PCI_DEVICE_ID_O2_8221: | ||
404 | case PCI_DEVICE_ID_O2_8320: | ||
405 | case PCI_DEVICE_ID_O2_8321: | ||
406 | /* This extra setup is required due to broken ADMA. */ | ||
407 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
408 | if (ret) | ||
409 | return ret; | ||
410 | scratch &= 0x7f; | ||
411 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
412 | |||
413 | /* Set Multi 3 to VCC3V# */ | ||
414 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | ||
415 | |||
416 | /* Disable CLK_REQ# support after media DET */ | ||
417 | ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch); | ||
418 | if (ret) | ||
419 | return ret; | ||
420 | scratch |= 0x20; | ||
421 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | ||
422 | |||
423 | /* Choose capabilities, enable SDMA. We have to write 0x01 | ||
424 | * to the capabilities register first to unlock it. | ||
425 | */ | ||
426 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | ||
427 | if (ret) | ||
428 | return ret; | ||
429 | scratch |= 0x01; | ||
430 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | ||
431 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | ||
432 | |||
433 | /* Disable ADMA1/2 */ | ||
434 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | ||
435 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | ||
436 | |||
437 | /* Disable the infinite transfer mode */ | ||
438 | ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch); | ||
439 | if (ret) | ||
440 | return ret; | ||
441 | scratch |= 0x08; | ||
442 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | ||
443 | |||
444 | /* Lock WP */ | ||
445 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
446 | if (ret) | ||
447 | return ret; | ||
448 | scratch |= 0x80; | ||
449 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
450 | } | ||
451 | |||
452 | return 0; | ||
453 | } | ||
454 | |||
455 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) | 328 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) |
456 | { | 329 | { |
457 | u8 scratch; | 330 | u8 scratch; |
@@ -642,7 +515,10 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) | |||
642 | } | 515 | } |
643 | 516 | ||
644 | static const struct sdhci_pci_fixes sdhci_o2 = { | 517 | static const struct sdhci_pci_fixes sdhci_o2 = { |
645 | .probe = o2_probe, | 518 | .probe = sdhci_pci_o2_probe, |
519 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | ||
520 | .probe_slot = sdhci_pci_o2_probe_slot, | ||
521 | .resume = sdhci_pci_o2_resume, | ||
646 | }; | 522 | }; |
647 | 523 | ||
648 | static const struct sdhci_pci_fixes sdhci_jmicron = { | 524 | static const struct sdhci_pci_fixes sdhci_jmicron = { |
@@ -1055,6 +931,46 @@ static const struct pci_device_id pci_ids[] = { | |||
1055 | .driver_data = (kernel_ulong_t)&sdhci_o2, | 931 | .driver_data = (kernel_ulong_t)&sdhci_o2, |
1056 | }, | 932 | }, |
1057 | 933 | ||
934 | { | ||
935 | .vendor = PCI_VENDOR_ID_O2, | ||
936 | .device = PCI_DEVICE_ID_O2_FUJIN2, | ||
937 | .subvendor = PCI_ANY_ID, | ||
938 | .subdevice = PCI_ANY_ID, | ||
939 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
940 | }, | ||
941 | |||
942 | { | ||
943 | .vendor = PCI_VENDOR_ID_O2, | ||
944 | .device = PCI_DEVICE_ID_O2_SDS0, | ||
945 | .subvendor = PCI_ANY_ID, | ||
946 | .subdevice = PCI_ANY_ID, | ||
947 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
948 | }, | ||
949 | |||
950 | { | ||
951 | .vendor = PCI_VENDOR_ID_O2, | ||
952 | .device = PCI_DEVICE_ID_O2_SDS1, | ||
953 | .subvendor = PCI_ANY_ID, | ||
954 | .subdevice = PCI_ANY_ID, | ||
955 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
956 | }, | ||
957 | |||
958 | { | ||
959 | .vendor = PCI_VENDOR_ID_O2, | ||
960 | .device = PCI_DEVICE_ID_O2_SEABIRD0, | ||
961 | .subvendor = PCI_ANY_ID, | ||
962 | .subdevice = PCI_ANY_ID, | ||
963 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
964 | }, | ||
965 | |||
966 | { | ||
967 | .vendor = PCI_VENDOR_ID_O2, | ||
968 | .device = PCI_DEVICE_ID_O2_SEABIRD1, | ||
969 | .subvendor = PCI_ANY_ID, | ||
970 | .subdevice = PCI_ANY_ID, | ||
971 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
972 | }, | ||
973 | |||
1058 | { /* Generic SD host controller */ | 974 | { /* Generic SD host controller */ |
1059 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 975 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
1060 | }, | 976 | }, |
@@ -1457,6 +1373,15 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot( | |||
1457 | 1373 | ||
1458 | sdhci_pci_add_own_cd(slot); | 1374 | sdhci_pci_add_own_cd(slot); |
1459 | 1375 | ||
1376 | /* | ||
1377 | * Check if the chip needs a separate GPIO for card detect to wake up | ||
1378 | * from runtime suspend. If it is not there, don't allow runtime PM. | ||
1379 | * Note sdhci_pci_add_own_cd() sets slot->cd_gpio to -EINVAL on failure. | ||
1380 | */ | ||
1381 | if (chip->fixes && chip->fixes->own_cd_for_runtime_pm && | ||
1382 | !gpio_is_valid(slot->cd_gpio)) | ||
1383 | chip->allow_runtime_pm = false; | ||
1384 | |||
1460 | return slot; | 1385 | return slot; |
1461 | 1386 | ||
1462 | remove: | 1387 | remove: |