diff options
Diffstat (limited to 'drivers/mmc/host/sdhci-pci.c')
-rw-r--r-- | drivers/mmc/host/sdhci-pci.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index e0356644d1aa..5c3a1767770a 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -285,6 +285,73 @@ static const struct sdhci_pci_fixes sdhci_jmicron = { | |||
285 | .resume = jmicron_resume, | 285 | .resume = jmicron_resume, |
286 | }; | 286 | }; |
287 | 287 | ||
288 | /* SysKonnect CardBus2SDIO extra registers */ | ||
289 | #define SYSKT_CTRL 0x200 | ||
290 | #define SYSKT_RDFIFO_STAT 0x204 | ||
291 | #define SYSKT_WRFIFO_STAT 0x208 | ||
292 | #define SYSKT_POWER_DATA 0x20c | ||
293 | #define SYSKT_POWER_330 0xef | ||
294 | #define SYSKT_POWER_300 0xf8 | ||
295 | #define SYSKT_POWER_184 0xcc | ||
296 | #define SYSKT_POWER_CMD 0x20d | ||
297 | #define SYSKT_POWER_START (1 << 7) | ||
298 | #define SYSKT_POWER_STATUS 0x20e | ||
299 | #define SYSKT_POWER_STATUS_OK (1 << 0) | ||
300 | #define SYSKT_BOARD_REV 0x210 | ||
301 | #define SYSKT_CHIP_REV 0x211 | ||
302 | #define SYSKT_CONF_DATA 0x212 | ||
303 | #define SYSKT_CONF_DATA_1V8 (1 << 2) | ||
304 | #define SYSKT_CONF_DATA_2V5 (1 << 1) | ||
305 | #define SYSKT_CONF_DATA_3V3 (1 << 0) | ||
306 | |||
307 | static int syskt_probe(struct sdhci_pci_chip *chip) | ||
308 | { | ||
309 | if ((chip->pdev->class & 0x0000FF) == PCI_SDHCI_IFVENDOR) { | ||
310 | chip->pdev->class &= ~0x0000FF; | ||
311 | chip->pdev->class |= PCI_SDHCI_IFDMA; | ||
312 | } | ||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | static int syskt_probe_slot(struct sdhci_pci_slot *slot) | ||
317 | { | ||
318 | int tm, ps; | ||
319 | |||
320 | u8 board_rev = readb(slot->host->ioaddr + SYSKT_BOARD_REV); | ||
321 | u8 chip_rev = readb(slot->host->ioaddr + SYSKT_CHIP_REV); | ||
322 | dev_info(&slot->chip->pdev->dev, "SysKonnect CardBus2SDIO, " | ||
323 | "board rev %d.%d, chip rev %d.%d\n", | ||
324 | board_rev >> 4, board_rev & 0xf, | ||
325 | chip_rev >> 4, chip_rev & 0xf); | ||
326 | if (chip_rev >= 0x20) | ||
327 | slot->host->quirks |= SDHCI_QUIRK_FORCE_DMA; | ||
328 | |||
329 | writeb(SYSKT_POWER_330, slot->host->ioaddr + SYSKT_POWER_DATA); | ||
330 | writeb(SYSKT_POWER_START, slot->host->ioaddr + SYSKT_POWER_CMD); | ||
331 | udelay(50); | ||
332 | tm = 10; /* Wait max 1 ms */ | ||
333 | do { | ||
334 | ps = readw(slot->host->ioaddr + SYSKT_POWER_STATUS); | ||
335 | if (ps & SYSKT_POWER_STATUS_OK) | ||
336 | break; | ||
337 | udelay(100); | ||
338 | } while (--tm); | ||
339 | if (!tm) { | ||
340 | dev_err(&slot->chip->pdev->dev, | ||
341 | "power regulator never stabilized"); | ||
342 | writeb(0, slot->host->ioaddr + SYSKT_POWER_CMD); | ||
343 | return -ENODEV; | ||
344 | } | ||
345 | |||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static const struct sdhci_pci_fixes sdhci_syskt = { | ||
350 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER, | ||
351 | .probe = syskt_probe, | ||
352 | .probe_slot = syskt_probe_slot, | ||
353 | }; | ||
354 | |||
288 | static int via_probe(struct sdhci_pci_chip *chip) | 355 | static int via_probe(struct sdhci_pci_chip *chip) |
289 | { | 356 | { |
290 | if (chip->pdev->revision == 0x10) | 357 | if (chip->pdev->revision == 0x10) |
@@ -363,6 +430,14 @@ static const struct pci_device_id pci_ids[] __devinitdata = { | |||
363 | }, | 430 | }, |
364 | 431 | ||
365 | { | 432 | { |
433 | .vendor = PCI_VENDOR_ID_SYSKONNECT, | ||
434 | .device = 0x8000, | ||
435 | .subvendor = PCI_ANY_ID, | ||
436 | .subdevice = PCI_ANY_ID, | ||
437 | .driver_data = (kernel_ulong_t)&sdhci_syskt, | ||
438 | }, | ||
439 | |||
440 | { | ||
366 | .vendor = PCI_VENDOR_ID_VIA, | 441 | .vendor = PCI_VENDOR_ID_VIA, |
367 | .device = 0x95d0, | 442 | .device = 0x95d0, |
368 | .subvendor = PCI_ANY_ID, | 443 | .subvendor = PCI_ANY_ID, |