diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pci.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 161 |
1 files changed, 155 insertions, 6 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index 3d9c2460d437..0dc905b20eee 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -176,6 +176,74 @@ static const struct sdhci_pci_fixes sdhci_intel_mfd_emmc_sdio = { | |||
176 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, | 176 | .quirks = SDHCI_QUIRK_NO_ENDATTR_IN_NOPDESC, |
177 | }; | 177 | }; |
178 | 178 | ||
179 | /* O2Micro extra registers */ | ||
180 | #define O2_SD_LOCK_WP 0xD3 | ||
181 | #define O2_SD_MULTI_VCC3V 0xEE | ||
182 | #define O2_SD_CLKREQ 0xEC | ||
183 | #define O2_SD_CAPS 0xE0 | ||
184 | #define O2_SD_ADMA1 0xE2 | ||
185 | #define O2_SD_ADMA2 0xE7 | ||
186 | #define O2_SD_INF_MOD 0xF1 | ||
187 | |||
188 | static int o2_probe(struct sdhci_pci_chip *chip) | ||
189 | { | ||
190 | int ret; | ||
191 | u8 scratch; | ||
192 | |||
193 | switch (chip->pdev->device) { | ||
194 | case PCI_DEVICE_ID_O2_8220: | ||
195 | case PCI_DEVICE_ID_O2_8221: | ||
196 | case PCI_DEVICE_ID_O2_8320: | ||
197 | case PCI_DEVICE_ID_O2_8321: | ||
198 | /* This extra setup is required due to broken ADMA. */ | ||
199 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
200 | if (ret) | ||
201 | return ret; | ||
202 | scratch &= 0x7f; | ||
203 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
204 | |||
205 | /* Set Multi 3 to VCC3V# */ | ||
206 | pci_write_config_byte(chip->pdev, O2_SD_MULTI_VCC3V, 0x08); | ||
207 | |||
208 | /* Disable CLK_REQ# support after media DET */ | ||
209 | ret = pci_read_config_byte(chip->pdev, O2_SD_CLKREQ, &scratch); | ||
210 | if (ret) | ||
211 | return ret; | ||
212 | scratch |= 0x20; | ||
213 | pci_write_config_byte(chip->pdev, O2_SD_CLKREQ, scratch); | ||
214 | |||
215 | /* Choose capabilities, enable SDMA. We have to write 0x01 | ||
216 | * to the capabilities register first to unlock it. | ||
217 | */ | ||
218 | ret = pci_read_config_byte(chip->pdev, O2_SD_CAPS, &scratch); | ||
219 | if (ret) | ||
220 | return ret; | ||
221 | scratch |= 0x01; | ||
222 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, scratch); | ||
223 | pci_write_config_byte(chip->pdev, O2_SD_CAPS, 0x73); | ||
224 | |||
225 | /* Disable ADMA1/2 */ | ||
226 | pci_write_config_byte(chip->pdev, O2_SD_ADMA1, 0x39); | ||
227 | pci_write_config_byte(chip->pdev, O2_SD_ADMA2, 0x08); | ||
228 | |||
229 | /* Disable the infinite transfer mode */ | ||
230 | ret = pci_read_config_byte(chip->pdev, O2_SD_INF_MOD, &scratch); | ||
231 | if (ret) | ||
232 | return ret; | ||
233 | scratch |= 0x08; | ||
234 | pci_write_config_byte(chip->pdev, O2_SD_INF_MOD, scratch); | ||
235 | |||
236 | /* Lock WP */ | ||
237 | ret = pci_read_config_byte(chip->pdev, O2_SD_LOCK_WP, &scratch); | ||
238 | if (ret) | ||
239 | return ret; | ||
240 | scratch |= 0x80; | ||
241 | pci_write_config_byte(chip->pdev, O2_SD_LOCK_WP, scratch); | ||
242 | } | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
179 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) | 247 | static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) |
180 | { | 248 | { |
181 | u8 scratch; | 249 | u8 scratch; |
@@ -204,6 +272,7 @@ static int jmicron_pmos(struct sdhci_pci_chip *chip, int on) | |||
204 | static int jmicron_probe(struct sdhci_pci_chip *chip) | 272 | static int jmicron_probe(struct sdhci_pci_chip *chip) |
205 | { | 273 | { |
206 | int ret; | 274 | int ret; |
275 | u16 mmcdev = 0; | ||
207 | 276 | ||
208 | if (chip->pdev->revision == 0) { | 277 | if (chip->pdev->revision == 0) { |
209 | chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR | | 278 | chip->quirks |= SDHCI_QUIRK_32BIT_DMA_ADDR | |
@@ -225,12 +294,17 @@ static int jmicron_probe(struct sdhci_pci_chip *chip) | |||
225 | * 2. The MMC interface has a lower subfunction number | 294 | * 2. The MMC interface has a lower subfunction number |
226 | * than the SD interface. | 295 | * than the SD interface. |
227 | */ | 296 | */ |
228 | if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD) { | 297 | if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_SD) |
298 | mmcdev = PCI_DEVICE_ID_JMICRON_JMB38X_MMC; | ||
299 | else if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_SD) | ||
300 | mmcdev = PCI_DEVICE_ID_JMICRON_JMB388_ESD; | ||
301 | |||
302 | if (mmcdev) { | ||
229 | struct pci_dev *sd_dev; | 303 | struct pci_dev *sd_dev; |
230 | 304 | ||
231 | sd_dev = NULL; | 305 | sd_dev = NULL; |
232 | while ((sd_dev = pci_get_device(PCI_VENDOR_ID_JMICRON, | 306 | while ((sd_dev = pci_get_device(PCI_VENDOR_ID_JMICRON, |
233 | PCI_DEVICE_ID_JMICRON_JMB38X_MMC, sd_dev)) != NULL) { | 307 | mmcdev, sd_dev)) != NULL) { |
234 | if ((PCI_SLOT(chip->pdev->devfn) == | 308 | if ((PCI_SLOT(chip->pdev->devfn) == |
235 | PCI_SLOT(sd_dev->devfn)) && | 309 | PCI_SLOT(sd_dev->devfn)) && |
236 | (chip->pdev->bus == sd_dev->bus)) | 310 | (chip->pdev->bus == sd_dev->bus)) |
@@ -290,13 +364,25 @@ static int jmicron_probe_slot(struct sdhci_pci_slot *slot) | |||
290 | slot->host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; | 364 | slot->host->quirks |= SDHCI_QUIRK_BROKEN_ADMA; |
291 | } | 365 | } |
292 | 366 | ||
367 | /* JM388 MMC doesn't support 1.8V while SD supports it */ | ||
368 | if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) { | ||
369 | slot->host->ocr_avail_sd = MMC_VDD_32_33 | MMC_VDD_33_34 | | ||
370 | MMC_VDD_29_30 | MMC_VDD_30_31 | | ||
371 | MMC_VDD_165_195; /* allow 1.8V */ | ||
372 | slot->host->ocr_avail_mmc = MMC_VDD_32_33 | MMC_VDD_33_34 | | ||
373 | MMC_VDD_29_30 | MMC_VDD_30_31; /* no 1.8V for MMC */ | ||
374 | } | ||
375 | |||
293 | /* | 376 | /* |
294 | * The secondary interface requires a bit set to get the | 377 | * The secondary interface requires a bit set to get the |
295 | * interrupts. | 378 | * interrupts. |
296 | */ | 379 | */ |
297 | if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) | 380 | if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC || |
381 | slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) | ||
298 | jmicron_enable_mmc(slot->host, 1); | 382 | jmicron_enable_mmc(slot->host, 1); |
299 | 383 | ||
384 | slot->host->mmc->caps |= MMC_CAP_BUS_WIDTH_TEST; | ||
385 | |||
300 | return 0; | 386 | return 0; |
301 | } | 387 | } |
302 | 388 | ||
@@ -305,7 +391,8 @@ static void jmicron_remove_slot(struct sdhci_pci_slot *slot, int dead) | |||
305 | if (dead) | 391 | if (dead) |
306 | return; | 392 | return; |
307 | 393 | ||
308 | if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) | 394 | if (slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC || |
395 | slot->chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) | ||
309 | jmicron_enable_mmc(slot->host, 0); | 396 | jmicron_enable_mmc(slot->host, 0); |
310 | } | 397 | } |
311 | 398 | ||
@@ -313,7 +400,8 @@ static int jmicron_suspend(struct sdhci_pci_chip *chip, pm_message_t state) | |||
313 | { | 400 | { |
314 | int i; | 401 | int i; |
315 | 402 | ||
316 | if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) { | 403 | if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC || |
404 | chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) { | ||
317 | for (i = 0;i < chip->num_slots;i++) | 405 | for (i = 0;i < chip->num_slots;i++) |
318 | jmicron_enable_mmc(chip->slots[i]->host, 0); | 406 | jmicron_enable_mmc(chip->slots[i]->host, 0); |
319 | } | 407 | } |
@@ -325,7 +413,8 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) | |||
325 | { | 413 | { |
326 | int ret, i; | 414 | int ret, i; |
327 | 415 | ||
328 | if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC) { | 416 | if (chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB38X_MMC || |
417 | chip->pdev->device == PCI_DEVICE_ID_JMICRON_JMB388_ESD) { | ||
329 | for (i = 0;i < chip->num_slots;i++) | 418 | for (i = 0;i < chip->num_slots;i++) |
330 | jmicron_enable_mmc(chip->slots[i]->host, 1); | 419 | jmicron_enable_mmc(chip->slots[i]->host, 1); |
331 | } | 420 | } |
@@ -339,6 +428,10 @@ static int jmicron_resume(struct sdhci_pci_chip *chip) | |||
339 | return 0; | 428 | return 0; |
340 | } | 429 | } |
341 | 430 | ||
431 | static const struct sdhci_pci_fixes sdhci_o2 = { | ||
432 | .probe = o2_probe, | ||
433 | }; | ||
434 | |||
342 | static const struct sdhci_pci_fixes sdhci_jmicron = { | 435 | static const struct sdhci_pci_fixes sdhci_jmicron = { |
343 | .probe = jmicron_probe, | 436 | .probe = jmicron_probe, |
344 | 437 | ||
@@ -510,6 +603,22 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
510 | }, | 603 | }, |
511 | 604 | ||
512 | { | 605 | { |
606 | .vendor = PCI_VENDOR_ID_JMICRON, | ||
607 | .device = PCI_DEVICE_ID_JMICRON_JMB388_SD, | ||
608 | .subvendor = PCI_ANY_ID, | ||
609 | .subdevice = PCI_ANY_ID, | ||
610 | .driver_data = (kernel_ulong_t)&sdhci_jmicron, | ||
611 | }, | ||
612 | |||
613 | { | ||
614 | .vendor = PCI_VENDOR_ID_JMICRON, | ||
615 | .device = PCI_DEVICE_ID_JMICRON_JMB388_ESD, | ||
616 | .subvendor = PCI_ANY_ID, | ||
617 | .subdevice = PCI_ANY_ID, | ||
618 | .driver_data = (kernel_ulong_t)&sdhci_jmicron, | ||
619 | }, | ||
620 | |||
621 | { | ||
513 | .vendor = PCI_VENDOR_ID_SYSKONNECT, | 622 | .vendor = PCI_VENDOR_ID_SYSKONNECT, |
514 | .device = 0x8000, | 623 | .device = 0x8000, |
515 | .subvendor = PCI_ANY_ID, | 624 | .subvendor = PCI_ANY_ID, |
@@ -589,6 +698,46 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
589 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio, | 698 | .driver_data = (kernel_ulong_t)&sdhci_intel_mfd_emmc_sdio, |
590 | }, | 699 | }, |
591 | 700 | ||
701 | { | ||
702 | .vendor = PCI_VENDOR_ID_O2, | ||
703 | .device = PCI_DEVICE_ID_O2_8120, | ||
704 | .subvendor = PCI_ANY_ID, | ||
705 | .subdevice = PCI_ANY_ID, | ||
706 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
707 | }, | ||
708 | |||
709 | { | ||
710 | .vendor = PCI_VENDOR_ID_O2, | ||
711 | .device = PCI_DEVICE_ID_O2_8220, | ||
712 | .subvendor = PCI_ANY_ID, | ||
713 | .subdevice = PCI_ANY_ID, | ||
714 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
715 | }, | ||
716 | |||
717 | { | ||
718 | .vendor = PCI_VENDOR_ID_O2, | ||
719 | .device = PCI_DEVICE_ID_O2_8221, | ||
720 | .subvendor = PCI_ANY_ID, | ||
721 | .subdevice = PCI_ANY_ID, | ||
722 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
723 | }, | ||
724 | |||
725 | { | ||
726 | .vendor = PCI_VENDOR_ID_O2, | ||
727 | .device = PCI_DEVICE_ID_O2_8320, | ||
728 | .subvendor = PCI_ANY_ID, | ||
729 | .subdevice = PCI_ANY_ID, | ||
730 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
731 | }, | ||
732 | |||
733 | { | ||
734 | .vendor = PCI_VENDOR_ID_O2, | ||
735 | .device = PCI_DEVICE_ID_O2_8321, | ||
736 | .subvendor = PCI_ANY_ID, | ||
737 | .subdevice = PCI_ANY_ID, | ||
738 | .driver_data = (kernel_ulong_t)&sdhci_o2, | ||
739 | }, | ||
740 | |||
592 | { /* Generic SD host controller */ | 741 | { /* Generic SD host controller */ |
593 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) | 742 | PCI_DEVICE_CLASS((PCI_CLASS_SYSTEM_SDHCI << 8), 0xFFFF00) |
594 | }, | 743 | }, |