diff options
Diffstat (limited to 'drivers')
31 files changed, 3796 insertions, 490 deletions
diff --git a/drivers/mfd/sh_mobile_sdhi.c b/drivers/mfd/sh_mobile_sdhi.c index f1714f93af9d..0a7df44a93c0 100644 --- a/drivers/mfd/sh_mobile_sdhi.c +++ b/drivers/mfd/sh_mobile_sdhi.c | |||
| @@ -131,11 +131,17 @@ static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev) | |||
| 131 | */ | 131 | */ |
| 132 | mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES; | 132 | mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES; |
| 133 | 133 | ||
| 134 | /* | ||
| 135 | * All SDHI blocks support SDIO IRQ signalling. | ||
| 136 | */ | ||
| 137 | mmc_data->flags |= TMIO_MMC_SDIO_IRQ; | ||
| 138 | |||
| 134 | if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { | 139 | if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) { |
| 135 | priv->param_tx.slave_id = p->dma_slave_tx; | 140 | priv->param_tx.slave_id = p->dma_slave_tx; |
| 136 | priv->param_rx.slave_id = p->dma_slave_rx; | 141 | priv->param_rx.slave_id = p->dma_slave_rx; |
| 137 | priv->dma_priv.chan_priv_tx = &priv->param_tx; | 142 | priv->dma_priv.chan_priv_tx = &priv->param_tx; |
| 138 | priv->dma_priv.chan_priv_rx = &priv->param_rx; | 143 | priv->dma_priv.chan_priv_rx = &priv->param_rx; |
| 144 | priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */ | ||
| 139 | mmc_data->dma = &priv->dma_priv; | 145 | mmc_data->dma = &priv->dma_priv; |
| 140 | } | 146 | } |
| 141 | 147 | ||
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index 57e4416b9ef0..2a876c4099cd 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig | |||
| @@ -16,6 +16,7 @@ config MMC_BLOCK | |||
| 16 | 16 | ||
| 17 | config MMC_BLOCK_MINORS | 17 | config MMC_BLOCK_MINORS |
| 18 | int "Number of minors per block device" | 18 | int "Number of minors per block device" |
| 19 | depends on MMC_BLOCK | ||
| 19 | range 4 256 | 20 | range 4 256 |
| 20 | default 8 | 21 | default 8 |
| 21 | help | 22 | help |
diff --git a/drivers/mmc/core/Kconfig b/drivers/mmc/core/Kconfig index bb22ffd76ef8..ef103871517f 100644 --- a/drivers/mmc/core/Kconfig +++ b/drivers/mmc/core/Kconfig | |||
| @@ -16,3 +16,14 @@ config MMC_UNSAFE_RESUME | |||
| 16 | 16 | ||
| 17 | This option sets a default which can be overridden by the | 17 | This option sets a default which can be overridden by the |
| 18 | module parameter "removable=0" or "removable=1". | 18 | module parameter "removable=0" or "removable=1". |
| 19 | |||
| 20 | config MMC_CLKGATE | ||
| 21 | bool "MMC host clock gating (EXPERIMENTAL)" | ||
| 22 | depends on EXPERIMENTAL | ||
| 23 | help | ||
| 24 | This will attempt to aggressively gate the clock to the MMC card. | ||
| 25 | This is done to save power due to gating off the logic and bus | ||
| 26 | noise when the MMC card is not in use. Your host driver has to | ||
| 27 | support handling this in order for it to be of any use. | ||
| 28 | |||
| 29 | If unsure, say N. | ||
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c index af8dc6a2a317..63667a8f140c 100644 --- a/drivers/mmc/core/bus.c +++ b/drivers/mmc/core/bus.c | |||
| @@ -303,14 +303,14 @@ int mmc_add_card(struct mmc_card *card) | |||
| 303 | type, card->rca); | 303 | type, card->rca); |
| 304 | } | 304 | } |
| 305 | 305 | ||
| 306 | ret = device_add(&card->dev); | ||
| 307 | if (ret) | ||
| 308 | return ret; | ||
| 309 | |||
| 310 | #ifdef CONFIG_DEBUG_FS | 306 | #ifdef CONFIG_DEBUG_FS |
| 311 | mmc_add_card_debugfs(card); | 307 | mmc_add_card_debugfs(card); |
| 312 | #endif | 308 | #endif |
| 313 | 309 | ||
| 310 | ret = device_add(&card->dev); | ||
| 311 | if (ret) | ||
| 312 | return ret; | ||
| 313 | |||
| 314 | mmc_card_set_present(card); | 314 | mmc_card_set_present(card); |
| 315 | 315 | ||
| 316 | return 0; | 316 | return 0; |
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c index a3a780faf85a..6625c057be05 100644 --- a/drivers/mmc/core/core.c +++ b/drivers/mmc/core/core.c | |||
| @@ -22,6 +22,7 @@ | |||
| 22 | #include <linux/scatterlist.h> | 22 | #include <linux/scatterlist.h> |
| 23 | #include <linux/log2.h> | 23 | #include <linux/log2.h> |
| 24 | #include <linux/regulator/consumer.h> | 24 | #include <linux/regulator/consumer.h> |
| 25 | #include <linux/pm_runtime.h> | ||
| 25 | 26 | ||
| 26 | #include <linux/mmc/card.h> | 27 | #include <linux/mmc/card.h> |
| 27 | #include <linux/mmc/host.h> | 28 | #include <linux/mmc/host.h> |
| @@ -130,6 +131,8 @@ void mmc_request_done(struct mmc_host *host, struct mmc_request *mrq) | |||
| 130 | 131 | ||
| 131 | if (mrq->done) | 132 | if (mrq->done) |
| 132 | mrq->done(mrq); | 133 | mrq->done(mrq); |
| 134 | |||
| 135 | mmc_host_clk_gate(host); | ||
| 133 | } | 136 | } |
| 134 | } | 137 | } |
| 135 | 138 | ||
| @@ -190,6 +193,7 @@ mmc_start_request(struct mmc_host *host, struct mmc_request *mrq) | |||
| 190 | mrq->stop->mrq = mrq; | 193 | mrq->stop->mrq = mrq; |
| 191 | } | 194 | } |
| 192 | } | 195 | } |
| 196 | mmc_host_clk_ungate(host); | ||
| 193 | host->ops->request(host, mrq); | 197 | host->ops->request(host, mrq); |
| 194 | } | 198 | } |
| 195 | 199 | ||
| @@ -295,8 +299,9 @@ void mmc_set_data_timeout(struct mmc_data *data, const struct mmc_card *card) | |||
| 295 | unsigned int timeout_us, limit_us; | 299 | unsigned int timeout_us, limit_us; |
| 296 | 300 | ||
| 297 | timeout_us = data->timeout_ns / 1000; | 301 | timeout_us = data->timeout_ns / 1000; |
| 298 | timeout_us += data->timeout_clks * 1000 / | 302 | if (mmc_host_clk_rate(card->host)) |
| 299 | (card->host->ios.clock / 1000); | 303 | timeout_us += data->timeout_clks * 1000 / |
| 304 | (mmc_host_clk_rate(card->host) / 1000); | ||
| 300 | 305 | ||
| 301 | if (data->flags & MMC_DATA_WRITE) | 306 | if (data->flags & MMC_DATA_WRITE) |
| 302 | /* | 307 | /* |
| @@ -614,6 +619,8 @@ static inline void mmc_set_ios(struct mmc_host *host) | |||
| 614 | ios->power_mode, ios->chip_select, ios->vdd, | 619 | ios->power_mode, ios->chip_select, ios->vdd, |
| 615 | ios->bus_width, ios->timing); | 620 | ios->bus_width, ios->timing); |
| 616 | 621 | ||
| 622 | if (ios->clock > 0) | ||
| 623 | mmc_set_ungated(host); | ||
| 617 | host->ops->set_ios(host, ios); | 624 | host->ops->set_ios(host, ios); |
| 618 | } | 625 | } |
| 619 | 626 | ||
| @@ -641,6 +648,61 @@ void mmc_set_clock(struct mmc_host *host, unsigned int hz) | |||
| 641 | mmc_set_ios(host); | 648 | mmc_set_ios(host); |
| 642 | } | 649 | } |
| 643 | 650 | ||
| 651 | #ifdef CONFIG_MMC_CLKGATE | ||
| 652 | /* | ||
| 653 | * This gates the clock by setting it to 0 Hz. | ||
| 654 | */ | ||
| 655 | void mmc_gate_clock(struct mmc_host *host) | ||
| 656 | { | ||
| 657 | unsigned long flags; | ||
| 658 | |||
| 659 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 660 | host->clk_old = host->ios.clock; | ||
| 661 | host->ios.clock = 0; | ||
| 662 | host->clk_gated = true; | ||
| 663 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 664 | mmc_set_ios(host); | ||
| 665 | } | ||
| 666 | |||
| 667 | /* | ||
| 668 | * This restores the clock from gating by using the cached | ||
| 669 | * clock value. | ||
| 670 | */ | ||
| 671 | void mmc_ungate_clock(struct mmc_host *host) | ||
| 672 | { | ||
| 673 | /* | ||
| 674 | * We should previously have gated the clock, so the clock shall | ||
| 675 | * be 0 here! The clock may however be 0 during initialization, | ||
| 676 | * when some request operations are performed before setting | ||
| 677 | * the frequency. When ungate is requested in that situation | ||
| 678 | * we just ignore the call. | ||
| 679 | */ | ||
| 680 | if (host->clk_old) { | ||
| 681 | BUG_ON(host->ios.clock); | ||
| 682 | /* This call will also set host->clk_gated to false */ | ||
| 683 | mmc_set_clock(host, host->clk_old); | ||
| 684 | } | ||
| 685 | } | ||
| 686 | |||
| 687 | void mmc_set_ungated(struct mmc_host *host) | ||
| 688 | { | ||
| 689 | unsigned long flags; | ||
| 690 | |||
| 691 | /* | ||
| 692 | * We've been given a new frequency while the clock is gated, | ||
| 693 | * so make sure we regard this as ungating it. | ||
| 694 | */ | ||
| 695 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 696 | host->clk_gated = false; | ||
| 697 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 698 | } | ||
| 699 | |||
| 700 | #else | ||
| 701 | void mmc_set_ungated(struct mmc_host *host) | ||
| 702 | { | ||
| 703 | } | ||
| 704 | #endif | ||
| 705 | |||
| 644 | /* | 706 | /* |
| 645 | * Change the bus mode (open drain/push-pull) of a host. | 707 | * Change the bus mode (open drain/push-pull) of a host. |
| 646 | */ | 708 | */ |
| @@ -1424,35 +1486,57 @@ int mmc_set_blocklen(struct mmc_card *card, unsigned int blocklen) | |||
| 1424 | } | 1486 | } |
| 1425 | EXPORT_SYMBOL(mmc_set_blocklen); | 1487 | EXPORT_SYMBOL(mmc_set_blocklen); |
| 1426 | 1488 | ||
| 1489 | static int mmc_rescan_try_freq(struct mmc_host *host, unsigned freq) | ||
| 1490 | { | ||
| 1491 | host->f_init = freq; | ||
| 1492 | |||
| 1493 | #ifdef CONFIG_MMC_DEBUG | ||
| 1494 | pr_info("%s: %s: trying to init card at %u Hz\n", | ||
| 1495 | mmc_hostname(host), __func__, host->f_init); | ||
| 1496 | #endif | ||
| 1497 | mmc_power_up(host); | ||
| 1498 | sdio_reset(host); | ||
| 1499 | mmc_go_idle(host); | ||
| 1500 | |||
| 1501 | mmc_send_if_cond(host, host->ocr_avail); | ||
| 1502 | |||
| 1503 | /* Order's important: probe SDIO, then SD, then MMC */ | ||
| 1504 | if (!mmc_attach_sdio(host)) | ||
| 1505 | return 0; | ||
| 1506 | if (!mmc_attach_sd(host)) | ||
| 1507 | return 0; | ||
| 1508 | if (!mmc_attach_mmc(host)) | ||
| 1509 | return 0; | ||
| 1510 | |||
| 1511 | mmc_power_off(host); | ||
| 1512 | return -EIO; | ||
| 1513 | } | ||
| 1514 | |||
| 1427 | void mmc_rescan(struct work_struct *work) | 1515 | void mmc_rescan(struct work_struct *work) |
| 1428 | { | 1516 | { |
| 1517 | static const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; | ||
| 1429 | struct mmc_host *host = | 1518 | struct mmc_host *host = |
| 1430 | container_of(work, struct mmc_host, detect.work); | 1519 | container_of(work, struct mmc_host, detect.work); |
| 1431 | u32 ocr; | ||
| 1432 | int err; | ||
| 1433 | unsigned long flags; | ||
| 1434 | int i; | 1520 | int i; |
| 1435 | const unsigned freqs[] = { 400000, 300000, 200000, 100000 }; | ||
| 1436 | |||
| 1437 | spin_lock_irqsave(&host->lock, flags); | ||
| 1438 | 1521 | ||
| 1439 | if (host->rescan_disable) { | 1522 | if (host->rescan_disable) |
| 1440 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 1441 | return; | 1523 | return; |
| 1442 | } | ||
| 1443 | |||
| 1444 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 1445 | |||
| 1446 | 1524 | ||
| 1447 | mmc_bus_get(host); | 1525 | mmc_bus_get(host); |
| 1448 | 1526 | ||
| 1449 | /* if there is a card registered, check whether it is still present */ | 1527 | /* |
| 1450 | if ((host->bus_ops != NULL) && host->bus_ops->detect && !host->bus_dead) | 1528 | * if there is a _removable_ card registered, check whether it is |
| 1529 | * still present | ||
| 1530 | */ | ||
| 1531 | if (host->bus_ops && host->bus_ops->detect && !host->bus_dead | ||
| 1532 | && mmc_card_is_removable(host)) | ||
| 1451 | host->bus_ops->detect(host); | 1533 | host->bus_ops->detect(host); |
| 1452 | 1534 | ||
| 1535 | /* | ||
| 1536 | * Let mmc_bus_put() free the bus/bus_ops if we've found that | ||
| 1537 | * the card is no longer present. | ||
| 1538 | */ | ||
| 1453 | mmc_bus_put(host); | 1539 | mmc_bus_put(host); |
| 1454 | |||
| 1455 | |||
| 1456 | mmc_bus_get(host); | 1540 | mmc_bus_get(host); |
| 1457 | 1541 | ||
| 1458 | /* if there still is a card present, stop here */ | 1542 | /* if there still is a card present, stop here */ |
| @@ -1461,8 +1545,6 @@ void mmc_rescan(struct work_struct *work) | |||
| 1461 | goto out; | 1545 | goto out; |
| 1462 | } | 1546 | } |
| 1463 | 1547 | ||
| 1464 | /* detect a newly inserted card */ | ||
| 1465 | |||
| 1466 | /* | 1548 | /* |
| 1467 | * Only we can add a new handler, so it's safe to | 1549 | * Only we can add a new handler, so it's safe to |
| 1468 | * release the lock here. | 1550 | * release the lock here. |
| @@ -1472,72 +1554,16 @@ void mmc_rescan(struct work_struct *work) | |||
| 1472 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) | 1554 | if (host->ops->get_cd && host->ops->get_cd(host) == 0) |
| 1473 | goto out; | 1555 | goto out; |
| 1474 | 1556 | ||
| 1557 | mmc_claim_host(host); | ||
| 1475 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { | 1558 | for (i = 0; i < ARRAY_SIZE(freqs); i++) { |
| 1476 | mmc_claim_host(host); | 1559 | if (!mmc_rescan_try_freq(host, max(freqs[i], host->f_min))) |
| 1477 | 1560 | break; | |
| 1478 | if (freqs[i] >= host->f_min) | 1561 | if (freqs[i] < host->f_min) |
| 1479 | host->f_init = freqs[i]; | 1562 | break; |
| 1480 | else if (!i || freqs[i-1] > host->f_min) | ||
| 1481 | host->f_init = host->f_min; | ||
| 1482 | else { | ||
| 1483 | mmc_release_host(host); | ||
| 1484 | goto out; | ||
| 1485 | } | ||
| 1486 | #ifdef CONFIG_MMC_DEBUG | ||
| 1487 | pr_info("%s: %s: trying to init card at %u Hz\n", | ||
| 1488 | mmc_hostname(host), __func__, host->f_init); | ||
| 1489 | #endif | ||
| 1490 | mmc_power_up(host); | ||
| 1491 | sdio_reset(host); | ||
| 1492 | mmc_go_idle(host); | ||
| 1493 | |||
| 1494 | mmc_send_if_cond(host, host->ocr_avail); | ||
| 1495 | |||
| 1496 | /* | ||
| 1497 | * First we search for SDIO... | ||
| 1498 | */ | ||
| 1499 | err = mmc_send_io_op_cond(host, 0, &ocr); | ||
| 1500 | if (!err) { | ||
| 1501 | if (mmc_attach_sdio(host, ocr)) { | ||
| 1502 | mmc_claim_host(host); | ||
| 1503 | /* | ||
| 1504 | * Try SDMEM (but not MMC) even if SDIO | ||
| 1505 | * is broken. | ||
| 1506 | */ | ||
| 1507 | if (mmc_send_app_op_cond(host, 0, &ocr)) | ||
| 1508 | goto out_fail; | ||
| 1509 | |||
| 1510 | if (mmc_attach_sd(host, ocr)) | ||
| 1511 | mmc_power_off(host); | ||
| 1512 | } | ||
| 1513 | goto out; | ||
| 1514 | } | ||
| 1515 | |||
| 1516 | /* | ||
| 1517 | * ...then normal SD... | ||
| 1518 | */ | ||
| 1519 | err = mmc_send_app_op_cond(host, 0, &ocr); | ||
| 1520 | if (!err) { | ||
| 1521 | if (mmc_attach_sd(host, ocr)) | ||
| 1522 | mmc_power_off(host); | ||
| 1523 | goto out; | ||
| 1524 | } | ||
| 1525 | |||
| 1526 | /* | ||
| 1527 | * ...and finally MMC. | ||
| 1528 | */ | ||
| 1529 | err = mmc_send_op_cond(host, 0, &ocr); | ||
| 1530 | if (!err) { | ||
| 1531 | if (mmc_attach_mmc(host, ocr)) | ||
| 1532 | mmc_power_off(host); | ||
| 1533 | goto out; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | out_fail: | ||
| 1537 | mmc_release_host(host); | ||
| 1538 | mmc_power_off(host); | ||
| 1539 | } | 1563 | } |
| 1540 | out: | 1564 | mmc_release_host(host); |
| 1565 | |||
| 1566 | out: | ||
| 1541 | if (host->caps & MMC_CAP_NEEDS_POLL) | 1567 | if (host->caps & MMC_CAP_NEEDS_POLL) |
| 1542 | mmc_schedule_delayed_work(&host->detect, HZ); | 1568 | mmc_schedule_delayed_work(&host->detect, HZ); |
| 1543 | } | 1569 | } |
| @@ -1721,6 +1747,18 @@ int mmc_resume_host(struct mmc_host *host) | |||
| 1721 | if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { | 1747 | if (!(host->pm_flags & MMC_PM_KEEP_POWER)) { |
| 1722 | mmc_power_up(host); | 1748 | mmc_power_up(host); |
| 1723 | mmc_select_voltage(host, host->ocr); | 1749 | mmc_select_voltage(host, host->ocr); |
| 1750 | /* | ||
| 1751 | * Tell runtime PM core we just powered up the card, | ||
| 1752 | * since it still believes the card is powered off. | ||
| 1753 | * Note that currently runtime PM is only enabled | ||
| 1754 | * for SDIO cards that are MMC_CAP_POWER_OFF_CARD | ||
| 1755 | */ | ||
| 1756 | if (mmc_card_sdio(host->card) && | ||
| 1757 | (host->caps & MMC_CAP_POWER_OFF_CARD)) { | ||
| 1758 | pm_runtime_disable(&host->card->dev); | ||
| 1759 | pm_runtime_set_active(&host->card->dev); | ||
| 1760 | pm_runtime_enable(&host->card->dev); | ||
| 1761 | } | ||
| 1724 | } | 1762 | } |
| 1725 | BUG_ON(!host->bus_ops->resume); | 1763 | BUG_ON(!host->bus_ops->resume); |
| 1726 | err = host->bus_ops->resume(host); | 1764 | err = host->bus_ops->resume(host); |
diff --git a/drivers/mmc/core/core.h b/drivers/mmc/core/core.h index 77240cd11bcf..ca1fdde29df6 100644 --- a/drivers/mmc/core/core.h +++ b/drivers/mmc/core/core.h | |||
| @@ -33,6 +33,9 @@ void mmc_init_erase(struct mmc_card *card); | |||
| 33 | 33 | ||
| 34 | void mmc_set_chip_select(struct mmc_host *host, int mode); | 34 | void mmc_set_chip_select(struct mmc_host *host, int mode); |
| 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); | 35 | void mmc_set_clock(struct mmc_host *host, unsigned int hz); |
| 36 | void mmc_gate_clock(struct mmc_host *host); | ||
| 37 | void mmc_ungate_clock(struct mmc_host *host); | ||
| 38 | void mmc_set_ungated(struct mmc_host *host); | ||
| 36 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); | 39 | void mmc_set_bus_mode(struct mmc_host *host, unsigned int mode); |
| 37 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); | 40 | void mmc_set_bus_width(struct mmc_host *host, unsigned int width); |
| 38 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, | 41 | void mmc_set_bus_width_ddr(struct mmc_host *host, unsigned int width, |
| @@ -54,9 +57,9 @@ void mmc_rescan(struct work_struct *work); | |||
| 54 | void mmc_start_host(struct mmc_host *host); | 57 | void mmc_start_host(struct mmc_host *host); |
| 55 | void mmc_stop_host(struct mmc_host *host); | 58 | void mmc_stop_host(struct mmc_host *host); |
| 56 | 59 | ||
| 57 | int mmc_attach_mmc(struct mmc_host *host, u32 ocr); | 60 | int mmc_attach_mmc(struct mmc_host *host); |
| 58 | int mmc_attach_sd(struct mmc_host *host, u32 ocr); | 61 | int mmc_attach_sd(struct mmc_host *host); |
| 59 | int mmc_attach_sdio(struct mmc_host *host, u32 ocr); | 62 | int mmc_attach_sdio(struct mmc_host *host); |
| 60 | 63 | ||
| 61 | /* Module parameters */ | 64 | /* Module parameters */ |
| 62 | extern int use_spi_crc; | 65 | extern int use_spi_crc; |
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c index eed1405fd742..998797ed67a6 100644 --- a/drivers/mmc/core/debugfs.c +++ b/drivers/mmc/core/debugfs.c | |||
| @@ -183,6 +183,11 @@ void mmc_add_host_debugfs(struct mmc_host *host) | |||
| 183 | &mmc_clock_fops)) | 183 | &mmc_clock_fops)) |
| 184 | goto err_node; | 184 | goto err_node; |
| 185 | 185 | ||
| 186 | #ifdef CONFIG_MMC_CLKGATE | ||
| 187 | if (!debugfs_create_u32("clk_delay", (S_IRUSR | S_IWUSR), | ||
| 188 | root, &host->clk_delay)) | ||
| 189 | goto err_node; | ||
| 190 | #endif | ||
| 186 | return; | 191 | return; |
| 187 | 192 | ||
| 188 | err_node: | 193 | err_node: |
diff --git a/drivers/mmc/core/host.c b/drivers/mmc/core/host.c index 10b8af27e03a..b3ac6c5bc5c6 100644 --- a/drivers/mmc/core/host.c +++ b/drivers/mmc/core/host.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2003 Russell King, All Rights Reserved. | 4 | * Copyright (C) 2003 Russell King, All Rights Reserved. |
| 5 | * Copyright (C) 2007-2008 Pierre Ossman | 5 | * Copyright (C) 2007-2008 Pierre Ossman |
| 6 | * Copyright (C) 2010 Linus Walleij | ||
| 6 | * | 7 | * |
| 7 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| 8 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
| @@ -20,6 +21,7 @@ | |||
| 20 | #include <linux/suspend.h> | 21 | #include <linux/suspend.h> |
| 21 | 22 | ||
| 22 | #include <linux/mmc/host.h> | 23 | #include <linux/mmc/host.h> |
| 24 | #include <linux/mmc/card.h> | ||
| 23 | 25 | ||
| 24 | #include "core.h" | 26 | #include "core.h" |
| 25 | #include "host.h" | 27 | #include "host.h" |
| @@ -50,6 +52,205 @@ void mmc_unregister_host_class(void) | |||
| 50 | static DEFINE_IDR(mmc_host_idr); | 52 | static DEFINE_IDR(mmc_host_idr); |
| 51 | static DEFINE_SPINLOCK(mmc_host_lock); | 53 | static DEFINE_SPINLOCK(mmc_host_lock); |
| 52 | 54 | ||
| 55 | #ifdef CONFIG_MMC_CLKGATE | ||
| 56 | |||
| 57 | /* | ||
| 58 | * Enabling clock gating will make the core call out to the host | ||
| 59 | * once up and once down when it performs a request or card operation | ||
| 60 | * intermingled in any fashion. The driver will see this through | ||
| 61 | * set_ios() operations with ios.clock field set to 0 to gate (disable) | ||
| 62 | * the block clock, and to the old frequency to enable it again. | ||
| 63 | */ | ||
| 64 | static void mmc_host_clk_gate_delayed(struct mmc_host *host) | ||
| 65 | { | ||
| 66 | unsigned long tick_ns; | ||
| 67 | unsigned long freq = host->ios.clock; | ||
| 68 | unsigned long flags; | ||
| 69 | |||
| 70 | if (!freq) { | ||
| 71 | pr_debug("%s: frequency set to 0 in disable function, " | ||
| 72 | "this means the clock is already disabled.\n", | ||
| 73 | mmc_hostname(host)); | ||
| 74 | return; | ||
| 75 | } | ||
| 76 | /* | ||
| 77 | * New requests may have appeared while we were scheduling, | ||
| 78 | * then there is no reason to delay the check before | ||
| 79 | * clk_disable(). | ||
| 80 | */ | ||
| 81 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 82 | |||
| 83 | /* | ||
| 84 | * Delay n bus cycles (at least 8 from MMC spec) before attempting | ||
| 85 | * to disable the MCI block clock. The reference count may have | ||
| 86 | * gone up again after this delay due to rescheduling! | ||
| 87 | */ | ||
| 88 | if (!host->clk_requests) { | ||
| 89 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 90 | tick_ns = DIV_ROUND_UP(1000000000, freq); | ||
| 91 | ndelay(host->clk_delay * tick_ns); | ||
| 92 | } else { | ||
| 93 | /* New users appeared while waiting for this work */ | ||
| 94 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 95 | return; | ||
| 96 | } | ||
| 97 | mutex_lock(&host->clk_gate_mutex); | ||
| 98 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 99 | if (!host->clk_requests) { | ||
| 100 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 101 | /* This will set host->ios.clock to 0 */ | ||
| 102 | mmc_gate_clock(host); | ||
| 103 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 104 | pr_debug("%s: gated MCI clock\n", mmc_hostname(host)); | ||
| 105 | } | ||
| 106 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 107 | mutex_unlock(&host->clk_gate_mutex); | ||
| 108 | } | ||
| 109 | |||
| 110 | /* | ||
| 111 | * Internal work. Work to disable the clock at some later point. | ||
| 112 | */ | ||
| 113 | static void mmc_host_clk_gate_work(struct work_struct *work) | ||
| 114 | { | ||
| 115 | struct mmc_host *host = container_of(work, struct mmc_host, | ||
| 116 | clk_gate_work); | ||
| 117 | |||
| 118 | mmc_host_clk_gate_delayed(host); | ||
| 119 | } | ||
| 120 | |||
| 121 | /** | ||
| 122 | * mmc_host_clk_ungate - ungate hardware MCI clocks | ||
| 123 | * @host: host to ungate. | ||
| 124 | * | ||
| 125 | * Makes sure the host ios.clock is restored to a non-zero value | ||
| 126 | * past this call. Increase clock reference count and ungate clock | ||
| 127 | * if we're the first user. | ||
| 128 | */ | ||
| 129 | void mmc_host_clk_ungate(struct mmc_host *host) | ||
| 130 | { | ||
| 131 | unsigned long flags; | ||
| 132 | |||
| 133 | mutex_lock(&host->clk_gate_mutex); | ||
| 134 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 135 | if (host->clk_gated) { | ||
| 136 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 137 | mmc_ungate_clock(host); | ||
| 138 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 139 | pr_debug("%s: ungated MCI clock\n", mmc_hostname(host)); | ||
| 140 | } | ||
| 141 | host->clk_requests++; | ||
| 142 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 143 | mutex_unlock(&host->clk_gate_mutex); | ||
| 144 | } | ||
| 145 | |||
| 146 | /** | ||
| 147 | * mmc_host_may_gate_card - check if this card may be gated | ||
| 148 | * @card: card to check. | ||
| 149 | */ | ||
| 150 | static bool mmc_host_may_gate_card(struct mmc_card *card) | ||
| 151 | { | ||
| 152 | /* If there is no card we may gate it */ | ||
| 153 | if (!card) | ||
| 154 | return true; | ||
| 155 | /* | ||
| 156 | * Don't gate SDIO cards! These need to be clocked at all times | ||
| 157 | * since they may be independent systems generating interrupts | ||
| 158 | * and other events. The clock requests counter from the core will | ||
| 159 | * go down to zero since the core does not need it, but we will not | ||
| 160 | * gate the clock, because there is somebody out there that may still | ||
| 161 | * be using it. | ||
| 162 | */ | ||
| 163 | if (mmc_card_sdio(card)) | ||
| 164 | return false; | ||
| 165 | |||
| 166 | return true; | ||
| 167 | } | ||
| 168 | |||
| 169 | /** | ||
| 170 | * mmc_host_clk_gate - gate off hardware MCI clocks | ||
| 171 | * @host: host to gate. | ||
| 172 | * | ||
| 173 | * Calls the host driver with ios.clock set to zero as often as possible | ||
| 174 | * in order to gate off hardware MCI clocks. Decrease clock reference | ||
| 175 | * count and schedule disabling of clock. | ||
| 176 | */ | ||
| 177 | void mmc_host_clk_gate(struct mmc_host *host) | ||
| 178 | { | ||
| 179 | unsigned long flags; | ||
| 180 | |||
| 181 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 182 | host->clk_requests--; | ||
| 183 | if (mmc_host_may_gate_card(host->card) && | ||
| 184 | !host->clk_requests) | ||
| 185 | schedule_work(&host->clk_gate_work); | ||
| 186 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 187 | } | ||
| 188 | |||
| 189 | /** | ||
| 190 | * mmc_host_clk_rate - get current clock frequency setting | ||
| 191 | * @host: host to get the clock frequency for. | ||
| 192 | * | ||
| 193 | * Returns current clock frequency regardless of gating. | ||
| 194 | */ | ||
| 195 | unsigned int mmc_host_clk_rate(struct mmc_host *host) | ||
| 196 | { | ||
| 197 | unsigned long freq; | ||
| 198 | unsigned long flags; | ||
| 199 | |||
| 200 | spin_lock_irqsave(&host->clk_lock, flags); | ||
| 201 | if (host->clk_gated) | ||
| 202 | freq = host->clk_old; | ||
| 203 | else | ||
| 204 | freq = host->ios.clock; | ||
| 205 | spin_unlock_irqrestore(&host->clk_lock, flags); | ||
| 206 | return freq; | ||
| 207 | } | ||
| 208 | |||
| 209 | /** | ||
| 210 | * mmc_host_clk_init - set up clock gating code | ||
| 211 | * @host: host with potential clock to control | ||
| 212 | */ | ||
| 213 | static inline void mmc_host_clk_init(struct mmc_host *host) | ||
| 214 | { | ||
| 215 | host->clk_requests = 0; | ||
| 216 | /* Hold MCI clock for 8 cycles by default */ | ||
| 217 | host->clk_delay = 8; | ||
| 218 | host->clk_gated = false; | ||
| 219 | INIT_WORK(&host->clk_gate_work, mmc_host_clk_gate_work); | ||
| 220 | spin_lock_init(&host->clk_lock); | ||
| 221 | mutex_init(&host->clk_gate_mutex); | ||
| 222 | } | ||
| 223 | |||
| 224 | /** | ||
| 225 | * mmc_host_clk_exit - shut down clock gating code | ||
| 226 | * @host: host with potential clock to control | ||
| 227 | */ | ||
| 228 | static inline void mmc_host_clk_exit(struct mmc_host *host) | ||
| 229 | { | ||
| 230 | /* | ||
| 231 | * Wait for any outstanding gate and then make sure we're | ||
| 232 | * ungated before exiting. | ||
| 233 | */ | ||
| 234 | if (cancel_work_sync(&host->clk_gate_work)) | ||
| 235 | mmc_host_clk_gate_delayed(host); | ||
| 236 | if (host->clk_gated) | ||
| 237 | mmc_host_clk_ungate(host); | ||
| 238 | /* There should be only one user now */ | ||
| 239 | WARN_ON(host->clk_requests > 1); | ||
| 240 | } | ||
| 241 | |||
| 242 | #else | ||
| 243 | |||
| 244 | static inline void mmc_host_clk_init(struct mmc_host *host) | ||
| 245 | { | ||
| 246 | } | ||
| 247 | |||
| 248 | static inline void mmc_host_clk_exit(struct mmc_host *host) | ||
| 249 | { | ||
| 250 | } | ||
| 251 | |||
| 252 | #endif | ||
| 253 | |||
| 53 | /** | 254 | /** |
| 54 | * mmc_alloc_host - initialise the per-host structure. | 255 | * mmc_alloc_host - initialise the per-host structure. |
| 55 | * @extra: sizeof private data structure | 256 | * @extra: sizeof private data structure |
| @@ -82,6 +283,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) | |||
| 82 | host->class_dev.class = &mmc_host_class; | 283 | host->class_dev.class = &mmc_host_class; |
| 83 | device_initialize(&host->class_dev); | 284 | device_initialize(&host->class_dev); |
| 84 | 285 | ||
| 286 | mmc_host_clk_init(host); | ||
| 287 | |||
| 85 | spin_lock_init(&host->lock); | 288 | spin_lock_init(&host->lock); |
| 86 | init_waitqueue_head(&host->wq); | 289 | init_waitqueue_head(&host->wq); |
| 87 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); | 290 | INIT_DELAYED_WORK(&host->detect, mmc_rescan); |
| @@ -163,6 +366,8 @@ void mmc_remove_host(struct mmc_host *host) | |||
| 163 | device_del(&host->class_dev); | 366 | device_del(&host->class_dev); |
| 164 | 367 | ||
| 165 | led_trigger_unregister_simple(host->led); | 368 | led_trigger_unregister_simple(host->led); |
| 369 | |||
| 370 | mmc_host_clk_exit(host); | ||
| 166 | } | 371 | } |
| 167 | 372 | ||
| 168 | EXPORT_SYMBOL(mmc_remove_host); | 373 | EXPORT_SYMBOL(mmc_remove_host); |
| @@ -183,4 +388,3 @@ void mmc_free_host(struct mmc_host *host) | |||
| 183 | } | 388 | } |
| 184 | 389 | ||
| 185 | EXPORT_SYMBOL(mmc_free_host); | 390 | EXPORT_SYMBOL(mmc_free_host); |
| 186 | |||
diff --git a/drivers/mmc/core/host.h b/drivers/mmc/core/host.h index 8c87e1109a34..de199f911928 100644 --- a/drivers/mmc/core/host.h +++ b/drivers/mmc/core/host.h | |||
| @@ -10,10 +10,31 @@ | |||
| 10 | */ | 10 | */ |
| 11 | #ifndef _MMC_CORE_HOST_H | 11 | #ifndef _MMC_CORE_HOST_H |
| 12 | #define _MMC_CORE_HOST_H | 12 | #define _MMC_CORE_HOST_H |
| 13 | #include <linux/mmc/host.h> | ||
| 13 | 14 | ||
| 14 | int mmc_register_host_class(void); | 15 | int mmc_register_host_class(void); |
| 15 | void mmc_unregister_host_class(void); | 16 | void mmc_unregister_host_class(void); |
| 16 | 17 | ||
| 18 | #ifdef CONFIG_MMC_CLKGATE | ||
| 19 | void mmc_host_clk_ungate(struct mmc_host *host); | ||
| 20 | void mmc_host_clk_gate(struct mmc_host *host); | ||
| 21 | unsigned int mmc_host_clk_rate(struct mmc_host *host); | ||
| 22 | |||
| 23 | #else | ||
| 24 | static inline void mmc_host_clk_ungate(struct mmc_host *host) | ||
| 25 | { | ||
| 26 | } | ||
| 27 | |||
| 28 | static inline void mmc_host_clk_gate(struct mmc_host *host) | ||
| 29 | { | ||
| 30 | } | ||
| 31 | |||
| 32 | static inline unsigned int mmc_host_clk_rate(struct mmc_host *host) | ||
| 33 | { | ||
| 34 | return host->ios.clock; | ||
| 35 | } | ||
| 36 | #endif | ||
| 37 | |||
| 17 | void mmc_host_deeper_disable(struct work_struct *work); | 38 | void mmc_host_deeper_disable(struct work_struct *work); |
| 18 | 39 | ||
| 19 | #endif | 40 | #endif |
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c index 77f93c3b8808..16006ef153fe 100644 --- a/drivers/mmc/core/mmc.c +++ b/drivers/mmc/core/mmc.c | |||
| @@ -534,39 +534,57 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, | |||
| 534 | */ | 534 | */ |
| 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && | 535 | if ((card->csd.mmca_vsn >= CSD_SPEC_VER_4) && |
| 536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { | 536 | (host->caps & (MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA))) { |
| 537 | unsigned ext_csd_bit, bus_width; | 537 | static unsigned ext_csd_bits[][2] = { |
| 538 | 538 | { EXT_CSD_BUS_WIDTH_8, EXT_CSD_DDR_BUS_WIDTH_8 }, | |
| 539 | if (host->caps & MMC_CAP_8_BIT_DATA) { | 539 | { EXT_CSD_BUS_WIDTH_4, EXT_CSD_DDR_BUS_WIDTH_4 }, |
| 540 | if (ddr) | 540 | { EXT_CSD_BUS_WIDTH_1, EXT_CSD_BUS_WIDTH_1 }, |
| 541 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_8; | 541 | }; |
| 542 | else | 542 | static unsigned bus_widths[] = { |
| 543 | ext_csd_bit = EXT_CSD_BUS_WIDTH_8; | 543 | MMC_BUS_WIDTH_8, |
| 544 | bus_width = MMC_BUS_WIDTH_8; | 544 | MMC_BUS_WIDTH_4, |
| 545 | } else { | 545 | MMC_BUS_WIDTH_1 |
| 546 | if (ddr) | 546 | }; |
| 547 | ext_csd_bit = EXT_CSD_DDR_BUS_WIDTH_4; | 547 | unsigned idx, bus_width = 0; |
| 548 | else | 548 | |
| 549 | ext_csd_bit = EXT_CSD_BUS_WIDTH_4; | 549 | if (host->caps & MMC_CAP_8_BIT_DATA) |
| 550 | bus_width = MMC_BUS_WIDTH_4; | 550 | idx = 0; |
| 551 | else | ||
| 552 | idx = 1; | ||
| 553 | for (; idx < ARRAY_SIZE(bus_widths); idx++) { | ||
| 554 | bus_width = bus_widths[idx]; | ||
| 555 | if (bus_width == MMC_BUS_WIDTH_1) | ||
| 556 | ddr = 0; /* no DDR for 1-bit width */ | ||
| 557 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | ||
| 558 | EXT_CSD_BUS_WIDTH, | ||
| 559 | ext_csd_bits[idx][0]); | ||
| 560 | if (!err) { | ||
| 561 | mmc_set_bus_width_ddr(card->host, | ||
| 562 | bus_width, MMC_SDR_MODE); | ||
| 563 | /* | ||
| 564 | * If controller can't handle bus width test, | ||
| 565 | * use the highest bus width to maintain | ||
| 566 | * compatibility with previous MMC behavior. | ||
| 567 | */ | ||
| 568 | if (!(host->caps & MMC_CAP_BUS_WIDTH_TEST)) | ||
| 569 | break; | ||
| 570 | err = mmc_bus_test(card, bus_width); | ||
| 571 | if (!err) | ||
| 572 | break; | ||
| 573 | } | ||
| 551 | } | 574 | } |
| 552 | 575 | ||
| 553 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, | 576 | if (!err && ddr) { |
| 554 | EXT_CSD_BUS_WIDTH, ext_csd_bit); | 577 | err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, |
| 555 | 578 | EXT_CSD_BUS_WIDTH, | |
| 556 | if (err && err != -EBADMSG) | 579 | ext_csd_bits[idx][1]); |
| 557 | goto free_card; | 580 | } |
| 558 | |||
| 559 | if (err) { | 581 | if (err) { |
| 560 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " | 582 | printk(KERN_WARNING "%s: switch to bus width %d ddr %d " |
| 561 | "failed\n", mmc_hostname(card->host), | 583 | "failed\n", mmc_hostname(card->host), |
| 562 | 1 << bus_width, ddr); | 584 | 1 << bus_width, ddr); |
| 563 | err = 0; | 585 | goto free_card; |
| 564 | } else { | 586 | } else if (ddr) { |
| 565 | if (ddr) | 587 | mmc_card_set_ddr_mode(card); |
| 566 | mmc_card_set_ddr_mode(card); | ||
| 567 | else | ||
| 568 | ddr = MMC_SDR_MODE; | ||
| 569 | |||
| 570 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); | 588 | mmc_set_bus_width_ddr(card->host, bus_width, ddr); |
| 571 | } | 589 | } |
| 572 | } | 590 | } |
| @@ -737,14 +755,21 @@ static void mmc_attach_bus_ops(struct mmc_host *host) | |||
| 737 | /* | 755 | /* |
| 738 | * Starting point for MMC card init. | 756 | * Starting point for MMC card init. |
| 739 | */ | 757 | */ |
| 740 | int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | 758 | int mmc_attach_mmc(struct mmc_host *host) |
| 741 | { | 759 | { |
| 742 | int err; | 760 | int err; |
| 761 | u32 ocr; | ||
| 743 | 762 | ||
| 744 | BUG_ON(!host); | 763 | BUG_ON(!host); |
| 745 | WARN_ON(!host->claimed); | 764 | WARN_ON(!host->claimed); |
| 746 | 765 | ||
| 766 | err = mmc_send_op_cond(host, 0, &ocr); | ||
| 767 | if (err) | ||
| 768 | return err; | ||
| 769 | |||
| 747 | mmc_attach_bus_ops(host); | 770 | mmc_attach_bus_ops(host); |
| 771 | if (host->ocr_avail_mmc) | ||
| 772 | host->ocr_avail = host->ocr_avail_mmc; | ||
| 748 | 773 | ||
| 749 | /* | 774 | /* |
| 750 | * We need to get OCR a different way for SPI. | 775 | * We need to get OCR a different way for SPI. |
| @@ -784,20 +809,20 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) | |||
| 784 | goto err; | 809 | goto err; |
| 785 | 810 | ||
| 786 | mmc_release_host(host); | 811 | mmc_release_host(host); |
| 787 | |||
| 788 | err = mmc_add_card(host->card); | 812 | err = mmc_add_card(host->card); |
| 813 | mmc_claim_host(host); | ||
| 789 | if (err) | 814 | if (err) |
| 790 | goto remove_card; | 815 | goto remove_card; |
| 791 | 816 | ||
| 792 | return 0; | 817 | return 0; |
| 793 | 818 | ||
| 794 | remove_card: | 819 | remove_card: |
| 820 | mmc_release_host(host); | ||
| 795 | mmc_remove_card(host->card); | 821 | mmc_remove_card(host->card); |
| 796 | host->card = NULL; | ||
| 797 | mmc_claim_host(host); | 822 | mmc_claim_host(host); |
| 823 | host->card = NULL; | ||
| 798 | err: | 824 | err: |
| 799 | mmc_detach_bus(host); | 825 | mmc_detach_bus(host); |
| 800 | mmc_release_host(host); | ||
| 801 | 826 | ||
| 802 | printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", | 827 | printk(KERN_ERR "%s: error %d whilst initialising MMC card\n", |
| 803 | mmc_hostname(host), err); | 828 | mmc_hostname(host), err); |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 326447c9ede8..60842f878ded 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
| @@ -462,3 +462,104 @@ int mmc_send_status(struct mmc_card *card, u32 *status) | |||
| 462 | return 0; | 462 | return 0; |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | static int | ||
| 466 | mmc_send_bus_test(struct mmc_card *card, struct mmc_host *host, u8 opcode, | ||
| 467 | u8 len) | ||
| 468 | { | ||
| 469 | struct mmc_request mrq; | ||
| 470 | struct mmc_command cmd; | ||
| 471 | struct mmc_data data; | ||
| 472 | struct scatterlist sg; | ||
| 473 | u8 *data_buf; | ||
| 474 | u8 *test_buf; | ||
| 475 | int i, err; | ||
| 476 | static u8 testdata_8bit[8] = { 0x55, 0xaa, 0, 0, 0, 0, 0, 0 }; | ||
| 477 | static u8 testdata_4bit[4] = { 0x5a, 0, 0, 0 }; | ||
| 478 | |||
| 479 | /* dma onto stack is unsafe/nonportable, but callers to this | ||
| 480 | * routine normally provide temporary on-stack buffers ... | ||
| 481 | */ | ||
| 482 | data_buf = kmalloc(len, GFP_KERNEL); | ||
| 483 | if (!data_buf) | ||
| 484 | return -ENOMEM; | ||
| 485 | |||
| 486 | if (len == 8) | ||
| 487 | test_buf = testdata_8bit; | ||
| 488 | else if (len == 4) | ||
| 489 | test_buf = testdata_4bit; | ||
| 490 | else { | ||
| 491 | printk(KERN_ERR "%s: Invalid bus_width %d\n", | ||
| 492 | mmc_hostname(host), len); | ||
| 493 | kfree(data_buf); | ||
| 494 | return -EINVAL; | ||
| 495 | } | ||
| 496 | |||
| 497 | if (opcode == MMC_BUS_TEST_W) | ||
| 498 | memcpy(data_buf, test_buf, len); | ||
| 499 | |||
| 500 | memset(&mrq, 0, sizeof(struct mmc_request)); | ||
| 501 | memset(&cmd, 0, sizeof(struct mmc_command)); | ||
| 502 | memset(&data, 0, sizeof(struct mmc_data)); | ||
| 503 | |||
| 504 | mrq.cmd = &cmd; | ||
| 505 | mrq.data = &data; | ||
| 506 | cmd.opcode = opcode; | ||
| 507 | cmd.arg = 0; | ||
| 508 | |||
| 509 | /* NOTE HACK: the MMC_RSP_SPI_R1 is always correct here, but we | ||
| 510 | * rely on callers to never use this with "native" calls for reading | ||
| 511 | * CSD or CID. Native versions of those commands use the R2 type, | ||
| 512 | * not R1 plus a data block. | ||
| 513 | */ | ||
| 514 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | ||
| 515 | |||
| 516 | data.blksz = len; | ||
| 517 | data.blocks = 1; | ||
| 518 | if (opcode == MMC_BUS_TEST_R) | ||
| 519 | data.flags = MMC_DATA_READ; | ||
| 520 | else | ||
| 521 | data.flags = MMC_DATA_WRITE; | ||
| 522 | |||
| 523 | data.sg = &sg; | ||
| 524 | data.sg_len = 1; | ||
| 525 | sg_init_one(&sg, data_buf, len); | ||
| 526 | mmc_wait_for_req(host, &mrq); | ||
| 527 | err = 0; | ||
| 528 | if (opcode == MMC_BUS_TEST_R) { | ||
| 529 | for (i = 0; i < len / 4; i++) | ||
| 530 | if ((test_buf[i] ^ data_buf[i]) != 0xff) { | ||
| 531 | err = -EIO; | ||
| 532 | break; | ||
| 533 | } | ||
| 534 | } | ||
| 535 | kfree(data_buf); | ||
| 536 | |||
| 537 | if (cmd.error) | ||
| 538 | return cmd.error; | ||
| 539 | if (data.error) | ||
| 540 | return data.error; | ||
| 541 | |||
| 542 | return err; | ||
| 543 | } | ||
| 544 | |||
| 545 | int mmc_bus_test(struct mmc_card *card, u8 bus_width) | ||
| 546 | { | ||
| 547 | int err, width; | ||
| 548 | |||
| 549 | if (bus_width == MMC_BUS_WIDTH_8) | ||
| 550 | width = 8; | ||
| 551 | else if (bus_width == MMC_BUS_WIDTH_4) | ||
| 552 | width = 4; | ||
| 553 | else if (bus_width == MMC_BUS_WIDTH_1) | ||
| 554 | return 0; /* no need for test */ | ||
| 555 | else | ||
| 556 | return -EINVAL; | ||
| 557 | |||
| 558 | /* | ||
| 559 | * Ignore errors from BUS_TEST_W. BUS_TEST_R will fail if there | ||
| 560 | * is a problem. This improves chances that the test will work. | ||
| 561 | */ | ||
| 562 | mmc_send_bus_test(card, card->host, MMC_BUS_TEST_W, width); | ||
| 563 | err = mmc_send_bus_test(card, card->host, MMC_BUS_TEST_R, width); | ||
| 564 | return err; | ||
| 565 | } | ||
diff --git a/drivers/mmc/core/mmc_ops.h b/drivers/mmc/core/mmc_ops.h index 653eb8e84178..e6d44b8a18db 100644 --- a/drivers/mmc/core/mmc_ops.h +++ b/drivers/mmc/core/mmc_ops.h | |||
| @@ -26,6 +26,7 @@ int mmc_send_cid(struct mmc_host *host, u32 *cid); | |||
| 26 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); | 26 | int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); |
| 27 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc); | 27 | int mmc_spi_set_crc(struct mmc_host *host, int use_crc); |
| 28 | int mmc_card_sleepawake(struct mmc_host *host, int sleep); | 28 | int mmc_card_sleepawake(struct mmc_host *host, int sleep); |
| 29 | int mmc_bus_test(struct mmc_card *card, u8 bus_width); | ||
| 29 | 30 | ||
| 30 | #endif | 31 | #endif |
| 31 | 32 | ||
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 49da4dffd28e..d18c32bca99b 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
| @@ -764,14 +764,21 @@ static void mmc_sd_attach_bus_ops(struct mmc_host *host) | |||
| 764 | /* | 764 | /* |
| 765 | * Starting point for SD card init. | 765 | * Starting point for SD card init. |
| 766 | */ | 766 | */ |
| 767 | int mmc_attach_sd(struct mmc_host *host, u32 ocr) | 767 | int mmc_attach_sd(struct mmc_host *host) |
| 768 | { | 768 | { |
| 769 | int err; | 769 | int err; |
| 770 | u32 ocr; | ||
| 770 | 771 | ||
| 771 | BUG_ON(!host); | 772 | BUG_ON(!host); |
| 772 | WARN_ON(!host->claimed); | 773 | WARN_ON(!host->claimed); |
| 773 | 774 | ||
| 775 | err = mmc_send_app_op_cond(host, 0, &ocr); | ||
| 776 | if (err) | ||
| 777 | return err; | ||
| 778 | |||
| 774 | mmc_sd_attach_bus_ops(host); | 779 | mmc_sd_attach_bus_ops(host); |
| 780 | if (host->ocr_avail_sd) | ||
| 781 | host->ocr_avail = host->ocr_avail_sd; | ||
| 775 | 782 | ||
| 776 | /* | 783 | /* |
| 777 | * We need to get OCR a different way for SPI. | 784 | * We need to get OCR a different way for SPI. |
| @@ -795,7 +802,8 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) | |||
| 795 | ocr &= ~0x7F; | 802 | ocr &= ~0x7F; |
| 796 | } | 803 | } |
| 797 | 804 | ||
| 798 | if (ocr & MMC_VDD_165_195) { | 805 | if ((ocr & MMC_VDD_165_195) && |
| 806 | !(host->ocr_avail_sd & MMC_VDD_165_195)) { | ||
| 799 | printk(KERN_WARNING "%s: SD card claims to support the " | 807 | printk(KERN_WARNING "%s: SD card claims to support the " |
| 800 | "incompletely defined 'low voltage range'. This " | 808 | "incompletely defined 'low voltage range'. This " |
| 801 | "will be ignored.\n", mmc_hostname(host)); | 809 | "will be ignored.\n", mmc_hostname(host)); |
| @@ -820,20 +828,20 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) | |||
| 820 | goto err; | 828 | goto err; |
| 821 | 829 | ||
| 822 | mmc_release_host(host); | 830 | mmc_release_host(host); |
| 823 | |||
| 824 | err = mmc_add_card(host->card); | 831 | err = mmc_add_card(host->card); |
| 832 | mmc_claim_host(host); | ||
| 825 | if (err) | 833 | if (err) |
| 826 | goto remove_card; | 834 | goto remove_card; |
| 827 | 835 | ||
| 828 | return 0; | 836 | return 0; |
| 829 | 837 | ||
| 830 | remove_card: | 838 | remove_card: |
| 839 | mmc_release_host(host); | ||
| 831 | mmc_remove_card(host->card); | 840 | mmc_remove_card(host->card); |
| 832 | host->card = NULL; | 841 | host->card = NULL; |
| 833 | mmc_claim_host(host); | 842 | mmc_claim_host(host); |
| 834 | err: | 843 | err: |
| 835 | mmc_detach_bus(host); | 844 | mmc_detach_bus(host); |
| 836 | mmc_release_host(host); | ||
| 837 | 845 | ||
| 838 | printk(KERN_ERR "%s: error %d whilst initialising SD card\n", | 846 | printk(KERN_ERR "%s: error %d whilst initialising SD card\n", |
| 839 | mmc_hostname(host), err); | 847 | mmc_hostname(host), err); |
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index efef5f94ac42..5c4a54d9b6a4 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
| @@ -627,15 +627,27 @@ static int mmc_sdio_suspend(struct mmc_host *host) | |||
| 627 | 627 | ||
| 628 | static int mmc_sdio_resume(struct mmc_host *host) | 628 | static int mmc_sdio_resume(struct mmc_host *host) |
| 629 | { | 629 | { |
| 630 | int i, err; | 630 | int i, err = 0; |
| 631 | 631 | ||
| 632 | BUG_ON(!host); | 632 | BUG_ON(!host); |
| 633 | BUG_ON(!host->card); | 633 | BUG_ON(!host->card); |
| 634 | 634 | ||
| 635 | /* Basic card reinitialization. */ | 635 | /* Basic card reinitialization. */ |
| 636 | mmc_claim_host(host); | 636 | mmc_claim_host(host); |
| 637 | err = mmc_sdio_init_card(host, host->ocr, host->card, | 637 | |
| 638 | /* No need to reinitialize powered-resumed nonremovable cards */ | ||
| 639 | if (mmc_card_is_removable(host) || !mmc_card_is_powered_resumed(host)) | ||
| 640 | err = mmc_sdio_init_card(host, host->ocr, host->card, | ||
| 638 | (host->pm_flags & MMC_PM_KEEP_POWER)); | 641 | (host->pm_flags & MMC_PM_KEEP_POWER)); |
| 642 | else if (mmc_card_is_powered_resumed(host)) { | ||
| 643 | /* We may have switched to 1-bit mode during suspend */ | ||
| 644 | err = sdio_enable_4bit_bus(host->card); | ||
| 645 | if (err > 0) { | ||
| 646 | mmc_set_bus_width(host, MMC_BUS_WIDTH_4); | ||
| 647 | err = 0; | ||
| 648 | } | ||
| 649 | } | ||
| 650 | |||
| 639 | if (!err && host->sdio_irqs) | 651 | if (!err && host->sdio_irqs) |
| 640 | mmc_signal_sdio_irq(host); | 652 | mmc_signal_sdio_irq(host); |
| 641 | mmc_release_host(host); | 653 | mmc_release_host(host); |
| @@ -690,16 +702,22 @@ static const struct mmc_bus_ops mmc_sdio_ops = { | |||
| 690 | /* | 702 | /* |
| 691 | * Starting point for SDIO card init. | 703 | * Starting point for SDIO card init. |
| 692 | */ | 704 | */ |
| 693 | int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | 705 | int mmc_attach_sdio(struct mmc_host *host) |
| 694 | { | 706 | { |
| 695 | int err; | 707 | int err, i, funcs; |
| 696 | int i, funcs; | 708 | u32 ocr; |
| 697 | struct mmc_card *card; | 709 | struct mmc_card *card; |
| 698 | 710 | ||
| 699 | BUG_ON(!host); | 711 | BUG_ON(!host); |
| 700 | WARN_ON(!host->claimed); | 712 | WARN_ON(!host->claimed); |
| 701 | 713 | ||
| 714 | err = mmc_send_io_op_cond(host, 0, &ocr); | ||
| 715 | if (err) | ||
| 716 | return err; | ||
| 717 | |||
| 702 | mmc_attach_bus(host, &mmc_sdio_ops); | 718 | mmc_attach_bus(host, &mmc_sdio_ops); |
| 719 | if (host->ocr_avail_sdio) | ||
| 720 | host->ocr_avail = host->ocr_avail_sdio; | ||
| 703 | 721 | ||
| 704 | /* | 722 | /* |
| 705 | * Sanity check the voltages that the card claims to | 723 | * Sanity check the voltages that the card claims to |
| @@ -769,12 +787,12 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
| 769 | pm_runtime_enable(&card->sdio_func[i]->dev); | 787 | pm_runtime_enable(&card->sdio_func[i]->dev); |
| 770 | } | 788 | } |
| 771 | 789 | ||
| 772 | mmc_release_host(host); | ||
| 773 | |||
| 774 | /* | 790 | /* |
| 775 | * First add the card to the driver model... | 791 | * First add the card to the driver model... |
| 776 | */ | 792 | */ |
| 793 | mmc_release_host(host); | ||
| 777 | err = mmc_add_card(host->card); | 794 | err = mmc_add_card(host->card); |
| 795 | mmc_claim_host(host); | ||
| 778 | if (err) | 796 | if (err) |
| 779 | goto remove_added; | 797 | goto remove_added; |
| 780 | 798 | ||
| @@ -792,15 +810,17 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
| 792 | 810 | ||
| 793 | remove_added: | 811 | remove_added: |
| 794 | /* Remove without lock if the device has been added. */ | 812 | /* Remove without lock if the device has been added. */ |
| 813 | mmc_release_host(host); | ||
| 795 | mmc_sdio_remove(host); | 814 | mmc_sdio_remove(host); |
| 796 | mmc_claim_host(host); | 815 | mmc_claim_host(host); |
| 797 | remove: | 816 | remove: |
| 798 | /* And with lock if it hasn't been added. */ | 817 | /* And with lock if it hasn't been added. */ |
| 818 | mmc_release_host(host); | ||
| 799 | if (host->card) | 819 | if (host->card) |
| 800 | mmc_sdio_remove(host); | 820 | mmc_sdio_remove(host); |
| 821 | mmc_claim_host(host); | ||
| 801 | err: | 822 | err: |
| 802 | mmc_detach_bus(host); | 823 | mmc_detach_bus(host); |
| 803 | mmc_release_host(host); | ||
| 804 | 824 | ||
| 805 | printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n", | 825 | printk(KERN_ERR "%s: error %d whilst initialising SDIO card\n", |
| 806 | mmc_hostname(host), err); | 826 | mmc_hostname(host), err); |
diff --git a/drivers/mmc/core/sdio_bus.c b/drivers/mmc/core/sdio_bus.c index 203da443e339..d29b9c36919a 100644 --- a/drivers/mmc/core/sdio_bus.c +++ b/drivers/mmc/core/sdio_bus.c | |||
| @@ -197,44 +197,12 @@ out: | |||
| 197 | 197 | ||
| 198 | #ifdef CONFIG_PM_RUNTIME | 198 | #ifdef CONFIG_PM_RUNTIME |
| 199 | 199 | ||
| 200 | static int sdio_bus_pm_prepare(struct device *dev) | ||
| 201 | { | ||
| 202 | struct sdio_func *func = dev_to_sdio_func(dev); | ||
| 203 | |||
| 204 | /* | ||
| 205 | * Resume an SDIO device which was suspended at run time at this | ||
| 206 | * point, in order to allow standard SDIO suspend/resume paths | ||
| 207 | * to keep working as usual. | ||
| 208 | * | ||
| 209 | * Ultimately, the SDIO driver itself will decide (in its | ||
| 210 | * suspend handler, or lack thereof) whether the card should be | ||
| 211 | * removed or kept, and if kept, at what power state. | ||
| 212 | * | ||
| 213 | * At this point, PM core have increased our use count, so it's | ||
| 214 | * safe to directly resume the device. After system is resumed | ||
| 215 | * again, PM core will drop back its runtime PM use count, and if | ||
| 216 | * needed device will be suspended again. | ||
| 217 | * | ||
| 218 | * The end result is guaranteed to be a power state that is | ||
| 219 | * coherent with the device's runtime PM use count. | ||
| 220 | * | ||
| 221 | * The return value of pm_runtime_resume is deliberately unchecked | ||
| 222 | * since there is little point in failing system suspend if a | ||
| 223 | * device can't be resumed. | ||
| 224 | */ | ||
| 225 | if (func->card->host->caps & MMC_CAP_POWER_OFF_CARD) | ||
| 226 | pm_runtime_resume(dev); | ||
| 227 | |||
| 228 | return 0; | ||
| 229 | } | ||
| 230 | |||
| 231 | static const struct dev_pm_ops sdio_bus_pm_ops = { | 200 | static const struct dev_pm_ops sdio_bus_pm_ops = { |
| 232 | SET_RUNTIME_PM_OPS( | 201 | SET_RUNTIME_PM_OPS( |
| 233 | pm_generic_runtime_suspend, | 202 | pm_generic_runtime_suspend, |
| 234 | pm_generic_runtime_resume, | 203 | pm_generic_runtime_resume, |
| 235 | pm_generic_runtime_idle | 204 | pm_generic_runtime_idle |
| 236 | ) | 205 | ) |
| 237 | .prepare = sdio_bus_pm_prepare, | ||
| 238 | }; | 206 | }; |
| 239 | 207 | ||
| 240 | #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) | 208 | #define SDIO_PM_OPS_PTR (&sdio_bus_pm_ops) |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index e960a9300eb2..c22a4c039988 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
| @@ -142,6 +142,27 @@ config MMC_SDHCI_ESDHC_IMX | |||
| 142 | 142 | ||
| 143 | If unsure, say N. | 143 | If unsure, say N. |
| 144 | 144 | ||
| 145 | config MMC_SDHCI_DOVE | ||
| 146 | bool "SDHCI support on Marvell's Dove SoC" | ||
| 147 | depends on ARCH_DOVE | ||
| 148 | depends on MMC_SDHCI_PLTFM | ||
| 149 | select MMC_SDHCI_IO_ACCESSORS | ||
| 150 | help | ||
| 151 | This selects the Secure Digital Host Controller Interface in | ||
| 152 | Marvell's Dove SoC. | ||
| 153 | |||
| 154 | If unsure, say N. | ||
| 155 | |||
| 156 | config MMC_SDHCI_TEGRA | ||
| 157 | tristate "SDHCI platform support for the Tegra SD/MMC Controller" | ||
| 158 | depends on MMC_SDHCI_PLTFM && ARCH_TEGRA | ||
| 159 | select MMC_SDHCI_IO_ACCESSORS | ||
| 160 | help | ||
| 161 | This selects the Tegra SD/MMC controller. If you have a Tegra | ||
| 162 | platform with SD or MMC devices, say Y or M here. | ||
| 163 | |||
| 164 | If unsure, say N. | ||
| 165 | |||
| 145 | config MMC_SDHCI_S3C | 166 | config MMC_SDHCI_S3C |
| 146 | tristate "SDHCI support on Samsung S3C SoC" | 167 | tristate "SDHCI support on Samsung S3C SoC" |
| 147 | depends on MMC_SDHCI && PLAT_SAMSUNG | 168 | depends on MMC_SDHCI && PLAT_SAMSUNG |
| @@ -460,6 +481,22 @@ config SDH_BFIN_MISSING_CMD_PULLUP_WORKAROUND | |||
| 460 | help | 481 | help |
| 461 | If you say yes here SD-Cards may work on the EZkit. | 482 | If you say yes here SD-Cards may work on the EZkit. |
| 462 | 483 | ||
| 484 | config MMC_DW | ||
| 485 | tristate "Synopsys DesignWare Memory Card Interface" | ||
| 486 | depends on ARM | ||
| 487 | help | ||
| 488 | This selects support for the Synopsys DesignWare Mobile Storage IP | ||
| 489 | block, this provides host support for SD and MMC interfaces, in both | ||
| 490 | PIO and external DMA modes. | ||
| 491 | |||
| 492 | config MMC_DW_IDMAC | ||
| 493 | bool "Internal DMAC interface" | ||
| 494 | depends on MMC_DW | ||
| 495 | help | ||
| 496 | This selects support for the internal DMAC block within the Synopsys | ||
| 497 | Designware Mobile Storage IP block. This disables the external DMA | ||
| 498 | interface. | ||
| 499 | |||
| 463 | config MMC_SH_MMCIF | 500 | config MMC_SH_MMCIF |
| 464 | tristate "SuperH Internal MMCIF support" | 501 | tristate "SuperH Internal MMCIF support" |
| 465 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) | 502 | depends on MMC_BLOCK && (SUPERH || ARCH_SHMOBILE) |
diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile index 7b645ff43b30..e834fb223e9a 100644 --- a/drivers/mmc/host/Makefile +++ b/drivers/mmc/host/Makefile | |||
| @@ -31,6 +31,7 @@ obj-$(CONFIG_MMC_TMIO) += tmio_mmc.o | |||
| 31 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o | 31 | obj-$(CONFIG_MMC_CB710) += cb710-mmc.o |
| 32 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o | 32 | obj-$(CONFIG_MMC_VIA_SDMMC) += via-sdmmc.o |
| 33 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o | 33 | obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o |
| 34 | obj-$(CONFIG_MMC_DW) += dw_mmc.o | ||
| 34 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o | 35 | obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o |
| 35 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o | 36 | obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o |
| 36 | obj-$(CONFIG_MMC_USHC) += ushc.o | 37 | obj-$(CONFIG_MMC_USHC) += ushc.o |
| @@ -39,6 +40,8 @@ obj-$(CONFIG_MMC_SDHCI_PLTFM) += sdhci-platform.o | |||
| 39 | sdhci-platform-y := sdhci-pltfm.o | 40 | sdhci-platform-y := sdhci-pltfm.o |
| 40 | sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o | 41 | sdhci-platform-$(CONFIG_MMC_SDHCI_CNS3XXX) += sdhci-cns3xxx.o |
| 41 | sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o | 42 | sdhci-platform-$(CONFIG_MMC_SDHCI_ESDHC_IMX) += sdhci-esdhc-imx.o |
| 43 | sdhci-platform-$(CONFIG_MMC_SDHCI_DOVE) += sdhci-dove.o | ||
| 44 | sdhci-platform-$(CONFIG_MMC_SDHCI_TEGRA) += sdhci-tegra.o | ||
| 42 | 45 | ||
| 43 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o | 46 | obj-$(CONFIG_MMC_SDHCI_OF) += sdhci-of.o |
| 44 | sdhci-of-y := sdhci-of-core.o | 47 | sdhci-of-y := sdhci-of-core.o |
diff --git a/drivers/mmc/host/davinci_mmc.c b/drivers/mmc/host/davinci_mmc.c index e15547cf701f..0076c7448fe6 100644 --- a/drivers/mmc/host/davinci_mmc.c +++ b/drivers/mmc/host/davinci_mmc.c | |||
| @@ -66,8 +66,8 @@ | |||
| 66 | #define DAVINCI_MMCBLNC 0x60 | 66 | #define DAVINCI_MMCBLNC 0x60 |
| 67 | #define DAVINCI_SDIOCTL 0x64 | 67 | #define DAVINCI_SDIOCTL 0x64 |
| 68 | #define DAVINCI_SDIOST0 0x68 | 68 | #define DAVINCI_SDIOST0 0x68 |
| 69 | #define DAVINCI_SDIOEN 0x6C | 69 | #define DAVINCI_SDIOIEN 0x6C |
| 70 | #define DAVINCI_SDIOST 0x70 | 70 | #define DAVINCI_SDIOIST 0x70 |
| 71 | #define DAVINCI_MMCFIFOCTL 0x74 /* FIFO Control Register */ | 71 | #define DAVINCI_MMCFIFOCTL 0x74 /* FIFO Control Register */ |
| 72 | 72 | ||
| 73 | /* DAVINCI_MMCCTL definitions */ | 73 | /* DAVINCI_MMCCTL definitions */ |
| @@ -131,6 +131,14 @@ | |||
| 131 | #define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */ | 131 | #define MMCFIFOCTL_ACCWD_2 (2 << 3) /* access width of 2 bytes */ |
| 132 | #define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */ | 132 | #define MMCFIFOCTL_ACCWD_1 (3 << 3) /* access width of 1 byte */ |
| 133 | 133 | ||
| 134 | /* DAVINCI_SDIOST0 definitions */ | ||
| 135 | #define SDIOST0_DAT1_HI BIT(0) | ||
| 136 | |||
| 137 | /* DAVINCI_SDIOIEN definitions */ | ||
| 138 | #define SDIOIEN_IOINTEN BIT(0) | ||
| 139 | |||
| 140 | /* DAVINCI_SDIOIST definitions */ | ||
| 141 | #define SDIOIST_IOINT BIT(0) | ||
| 134 | 142 | ||
| 135 | /* MMCSD Init clock in Hz in opendrain mode */ | 143 | /* MMCSD Init clock in Hz in opendrain mode */ |
| 136 | #define MMCSD_INIT_CLOCK 200000 | 144 | #define MMCSD_INIT_CLOCK 200000 |
| @@ -164,7 +172,7 @@ struct mmc_davinci_host { | |||
| 164 | unsigned int mmc_input_clk; | 172 | unsigned int mmc_input_clk; |
| 165 | void __iomem *base; | 173 | void __iomem *base; |
| 166 | struct resource *mem_res; | 174 | struct resource *mem_res; |
| 167 | int irq; | 175 | int mmc_irq, sdio_irq; |
| 168 | unsigned char bus_mode; | 176 | unsigned char bus_mode; |
| 169 | 177 | ||
| 170 | #define DAVINCI_MMC_DATADIR_NONE 0 | 178 | #define DAVINCI_MMC_DATADIR_NONE 0 |
| @@ -184,6 +192,7 @@ struct mmc_davinci_host { | |||
| 184 | u32 rxdma, txdma; | 192 | u32 rxdma, txdma; |
| 185 | bool use_dma; | 193 | bool use_dma; |
| 186 | bool do_dma; | 194 | bool do_dma; |
| 195 | bool sdio_int; | ||
| 187 | 196 | ||
| 188 | /* Scatterlist DMA uses one or more parameter RAM entries: | 197 | /* Scatterlist DMA uses one or more parameter RAM entries: |
| 189 | * the main one (associated with rxdma or txdma) plus zero or | 198 | * the main one (associated with rxdma or txdma) plus zero or |
| @@ -480,7 +489,7 @@ static void mmc_davinci_send_dma_request(struct mmc_davinci_host *host, | |||
| 480 | struct scatterlist *sg; | 489 | struct scatterlist *sg; |
| 481 | unsigned sg_len; | 490 | unsigned sg_len; |
| 482 | unsigned bytes_left = host->bytes_left; | 491 | unsigned bytes_left = host->bytes_left; |
| 483 | const unsigned shift = ffs(rw_threshold) - 1;; | 492 | const unsigned shift = ffs(rw_threshold) - 1; |
| 484 | 493 | ||
| 485 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { | 494 | if (host->data_dir == DAVINCI_MMC_DATADIR_WRITE) { |
| 486 | template = &host->tx_template; | 495 | template = &host->tx_template; |
| @@ -866,6 +875,19 @@ mmc_davinci_xfer_done(struct mmc_davinci_host *host, struct mmc_data *data) | |||
| 866 | { | 875 | { |
| 867 | host->data = NULL; | 876 | host->data = NULL; |
| 868 | 877 | ||
| 878 | if (host->mmc->caps & MMC_CAP_SDIO_IRQ) { | ||
| 879 | /* | ||
| 880 | * SDIO Interrupt Detection work-around as suggested by | ||
| 881 | * Davinci Errata (TMS320DM355 Silicon Revision 1.1 Errata | ||
| 882 | * 2.1.6): Signal SDIO interrupt only if it is enabled by core | ||
| 883 | */ | ||
| 884 | if (host->sdio_int && !(readl(host->base + DAVINCI_SDIOST0) & | ||
| 885 | SDIOST0_DAT1_HI)) { | ||
| 886 | writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); | ||
| 887 | mmc_signal_sdio_irq(host->mmc); | ||
| 888 | } | ||
| 889 | } | ||
| 890 | |||
| 869 | if (host->do_dma) { | 891 | if (host->do_dma) { |
| 870 | davinci_abort_dma(host); | 892 | davinci_abort_dma(host); |
| 871 | 893 | ||
| @@ -932,6 +954,21 @@ davinci_abort_data(struct mmc_davinci_host *host, struct mmc_data *data) | |||
| 932 | mmc_davinci_reset_ctrl(host, 0); | 954 | mmc_davinci_reset_ctrl(host, 0); |
| 933 | } | 955 | } |
| 934 | 956 | ||
| 957 | static irqreturn_t mmc_davinci_sdio_irq(int irq, void *dev_id) | ||
| 958 | { | ||
| 959 | struct mmc_davinci_host *host = dev_id; | ||
| 960 | unsigned int status; | ||
| 961 | |||
| 962 | status = readl(host->base + DAVINCI_SDIOIST); | ||
| 963 | if (status & SDIOIST_IOINT) { | ||
| 964 | dev_dbg(mmc_dev(host->mmc), | ||
| 965 | "SDIO interrupt status %x\n", status); | ||
| 966 | writel(status | SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); | ||
| 967 | mmc_signal_sdio_irq(host->mmc); | ||
| 968 | } | ||
| 969 | return IRQ_HANDLED; | ||
| 970 | } | ||
| 971 | |||
| 935 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) | 972 | static irqreturn_t mmc_davinci_irq(int irq, void *dev_id) |
| 936 | { | 973 | { |
| 937 | struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id; | 974 | struct mmc_davinci_host *host = (struct mmc_davinci_host *)dev_id; |
| @@ -1076,11 +1113,32 @@ static int mmc_davinci_get_ro(struct mmc_host *mmc) | |||
| 1076 | return config->get_ro(pdev->id); | 1113 | return config->get_ro(pdev->id); |
| 1077 | } | 1114 | } |
| 1078 | 1115 | ||
| 1116 | static void mmc_davinci_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
| 1117 | { | ||
| 1118 | struct mmc_davinci_host *host = mmc_priv(mmc); | ||
| 1119 | |||
| 1120 | if (enable) { | ||
| 1121 | if (!(readl(host->base + DAVINCI_SDIOST0) & SDIOST0_DAT1_HI)) { | ||
| 1122 | writel(SDIOIST_IOINT, host->base + DAVINCI_SDIOIST); | ||
| 1123 | mmc_signal_sdio_irq(host->mmc); | ||
| 1124 | } else { | ||
| 1125 | host->sdio_int = true; | ||
| 1126 | writel(readl(host->base + DAVINCI_SDIOIEN) | | ||
| 1127 | SDIOIEN_IOINTEN, host->base + DAVINCI_SDIOIEN); | ||
| 1128 | } | ||
| 1129 | } else { | ||
| 1130 | host->sdio_int = false; | ||
| 1131 | writel(readl(host->base + DAVINCI_SDIOIEN) & ~SDIOIEN_IOINTEN, | ||
| 1132 | host->base + DAVINCI_SDIOIEN); | ||
| 1133 | } | ||
| 1134 | } | ||
| 1135 | |||
| 1079 | static struct mmc_host_ops mmc_davinci_ops = { | 1136 | static struct mmc_host_ops mmc_davinci_ops = { |
| 1080 | .request = mmc_davinci_request, | 1137 | .request = mmc_davinci_request, |
| 1081 | .set_ios = mmc_davinci_set_ios, | 1138 | .set_ios = mmc_davinci_set_ios, |
| 1082 | .get_cd = mmc_davinci_get_cd, | 1139 | .get_cd = mmc_davinci_get_cd, |
| 1083 | .get_ro = mmc_davinci_get_ro, | 1140 | .get_ro = mmc_davinci_get_ro, |
| 1141 | .enable_sdio_irq = mmc_davinci_enable_sdio_irq, | ||
| 1084 | }; | 1142 | }; |
| 1085 | 1143 | ||
| 1086 | /*----------------------------------------------------------------------*/ | 1144 | /*----------------------------------------------------------------------*/ |
| @@ -1209,7 +1267,8 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
| 1209 | host->nr_sg = MAX_NR_SG; | 1267 | host->nr_sg = MAX_NR_SG; |
| 1210 | 1268 | ||
| 1211 | host->use_dma = use_dma; | 1269 | host->use_dma = use_dma; |
| 1212 | host->irq = irq; | 1270 | host->mmc_irq = irq; |
| 1271 | host->sdio_irq = platform_get_irq(pdev, 1); | ||
| 1213 | 1272 | ||
| 1214 | if (host->use_dma && davinci_acquire_dma_channels(host) != 0) | 1273 | if (host->use_dma && davinci_acquire_dma_channels(host) != 0) |
| 1215 | host->use_dma = 0; | 1274 | host->use_dma = 0; |
| @@ -1270,6 +1329,13 @@ static int __init davinci_mmcsd_probe(struct platform_device *pdev) | |||
| 1270 | if (ret) | 1329 | if (ret) |
| 1271 | goto out; | 1330 | goto out; |
| 1272 | 1331 | ||
| 1332 | if (host->sdio_irq >= 0) { | ||
| 1333 | ret = request_irq(host->sdio_irq, mmc_davinci_sdio_irq, 0, | ||
| 1334 | mmc_hostname(mmc), host); | ||
| 1335 | if (!ret) | ||
| 1336 | mmc->caps |= MMC_CAP_SDIO_IRQ; | ||
| 1337 | } | ||
| 1338 | |||
| 1273 | rename_region(mem, mmc_hostname(mmc)); | 1339 | rename_region(mem, mmc_hostname(mmc)); |
| 1274 | 1340 | ||
| 1275 | dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n", | 1341 | dev_info(mmc_dev(host->mmc), "Using %s, %d-bit mode\n", |
| @@ -1313,7 +1379,9 @@ static int __exit davinci_mmcsd_remove(struct platform_device *pdev) | |||
| 1313 | mmc_davinci_cpufreq_deregister(host); | 1379 | mmc_davinci_cpufreq_deregister(host); |
| 1314 | 1380 | ||
| 1315 | mmc_remove_host(host->mmc); | 1381 | mmc_remove_host(host->mmc); |
| 1316 | free_irq(host->irq, host); | 1382 | free_irq(host->mmc_irq, host); |
| 1383 | if (host->mmc->caps & MMC_CAP_SDIO_IRQ) | ||
| 1384 | free_irq(host->sdio_irq, host); | ||
| 1317 | 1385 | ||
| 1318 | davinci_release_dma_channels(host); | 1386 | davinci_release_dma_channels(host); |
| 1319 | 1387 | ||
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c new file mode 100644 index 000000000000..2fcc82577c1b --- /dev/null +++ b/drivers/mmc/host/dw_mmc.c | |||
| @@ -0,0 +1,1796 @@ | |||
| 1 | /* | ||
| 2 | * Synopsys DesignWare Multimedia Card Interface driver | ||
| 3 | * (Based on NXP driver for lpc 31xx) | ||
| 4 | * | ||
| 5 | * Copyright (C) 2009 NXP Semiconductors | ||
| 6 | * Copyright (C) 2009, 2010 Imagination Technologies Ltd. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/blkdev.h> | ||
| 15 | #include <linux/clk.h> | ||
| 16 | #include <linux/debugfs.h> | ||
| 17 | #include <linux/device.h> | ||
| 18 | #include <linux/dma-mapping.h> | ||
| 19 | #include <linux/err.h> | ||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/interrupt.h> | ||
| 22 | #include <linux/ioport.h> | ||
| 23 | #include <linux/module.h> | ||
| 24 | #include <linux/platform_device.h> | ||
| 25 | #include <linux/scatterlist.h> | ||
| 26 | #include <linux/seq_file.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <linux/stat.h> | ||
| 29 | #include <linux/delay.h> | ||
| 30 | #include <linux/irq.h> | ||
| 31 | #include <linux/mmc/host.h> | ||
| 32 | #include <linux/mmc/mmc.h> | ||
| 33 | #include <linux/mmc/dw_mmc.h> | ||
| 34 | #include <linux/bitops.h> | ||
| 35 | |||
| 36 | #include "dw_mmc.h" | ||
| 37 | |||
| 38 | /* Common flag combinations */ | ||
| 39 | #define DW_MCI_DATA_ERROR_FLAGS (SDMMC_INT_DTO | SDMMC_INT_DCRC | \ | ||
| 40 | SDMMC_INT_HTO | SDMMC_INT_SBE | \ | ||
| 41 | SDMMC_INT_EBE) | ||
| 42 | #define DW_MCI_CMD_ERROR_FLAGS (SDMMC_INT_RTO | SDMMC_INT_RCRC | \ | ||
| 43 | SDMMC_INT_RESP_ERR) | ||
| 44 | #define DW_MCI_ERROR_FLAGS (DW_MCI_DATA_ERROR_FLAGS | \ | ||
| 45 | DW_MCI_CMD_ERROR_FLAGS | SDMMC_INT_HLE) | ||
| 46 | #define DW_MCI_SEND_STATUS 1 | ||
| 47 | #define DW_MCI_RECV_STATUS 2 | ||
| 48 | #define DW_MCI_DMA_THRESHOLD 16 | ||
| 49 | |||
| 50 | #ifdef CONFIG_MMC_DW_IDMAC | ||
| 51 | struct idmac_desc { | ||
| 52 | u32 des0; /* Control Descriptor */ | ||
| 53 | #define IDMAC_DES0_DIC BIT(1) | ||
| 54 | #define IDMAC_DES0_LD BIT(2) | ||
| 55 | #define IDMAC_DES0_FD BIT(3) | ||
| 56 | #define IDMAC_DES0_CH BIT(4) | ||
| 57 | #define IDMAC_DES0_ER BIT(5) | ||
| 58 | #define IDMAC_DES0_CES BIT(30) | ||
| 59 | #define IDMAC_DES0_OWN BIT(31) | ||
| 60 | |||
| 61 | u32 des1; /* Buffer sizes */ | ||
| 62 | #define IDMAC_SET_BUFFER1_SIZE(d, s) \ | ||
| 63 | ((d)->des1 = ((d)->des1 & 0x03ffc000) | ((s) & 0x3fff)) | ||
| 64 | |||
| 65 | u32 des2; /* buffer 1 physical address */ | ||
| 66 | |||
| 67 | u32 des3; /* buffer 2 physical address */ | ||
| 68 | }; | ||
| 69 | #endif /* CONFIG_MMC_DW_IDMAC */ | ||
| 70 | |||
| 71 | /** | ||
| 72 | * struct dw_mci_slot - MMC slot state | ||
| 73 | * @mmc: The mmc_host representing this slot. | ||
| 74 | * @host: The MMC controller this slot is using. | ||
| 75 | * @ctype: Card type for this slot. | ||
| 76 | * @mrq: mmc_request currently being processed or waiting to be | ||
| 77 | * processed, or NULL when the slot is idle. | ||
| 78 | * @queue_node: List node for placing this node in the @queue list of | ||
| 79 | * &struct dw_mci. | ||
| 80 | * @clock: Clock rate configured by set_ios(). Protected by host->lock. | ||
| 81 | * @flags: Random state bits associated with the slot. | ||
| 82 | * @id: Number of this slot. | ||
| 83 | * @last_detect_state: Most recently observed card detect state. | ||
| 84 | */ | ||
| 85 | struct dw_mci_slot { | ||
| 86 | struct mmc_host *mmc; | ||
| 87 | struct dw_mci *host; | ||
| 88 | |||
| 89 | u32 ctype; | ||
| 90 | |||
| 91 | struct mmc_request *mrq; | ||
| 92 | struct list_head queue_node; | ||
| 93 | |||
| 94 | unsigned int clock; | ||
| 95 | unsigned long flags; | ||
| 96 | #define DW_MMC_CARD_PRESENT 0 | ||
| 97 | #define DW_MMC_CARD_NEED_INIT 1 | ||
| 98 | int id; | ||
| 99 | int last_detect_state; | ||
| 100 | }; | ||
| 101 | |||
| 102 | #if defined(CONFIG_DEBUG_FS) | ||
| 103 | static int dw_mci_req_show(struct seq_file *s, void *v) | ||
| 104 | { | ||
| 105 | struct dw_mci_slot *slot = s->private; | ||
| 106 | struct mmc_request *mrq; | ||
| 107 | struct mmc_command *cmd; | ||
| 108 | struct mmc_command *stop; | ||
| 109 | struct mmc_data *data; | ||
| 110 | |||
| 111 | /* Make sure we get a consistent snapshot */ | ||
| 112 | spin_lock_bh(&slot->host->lock); | ||
| 113 | mrq = slot->mrq; | ||
| 114 | |||
| 115 | if (mrq) { | ||
| 116 | cmd = mrq->cmd; | ||
| 117 | data = mrq->data; | ||
| 118 | stop = mrq->stop; | ||
| 119 | |||
| 120 | if (cmd) | ||
| 121 | seq_printf(s, | ||
| 122 | "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", | ||
| 123 | cmd->opcode, cmd->arg, cmd->flags, | ||
| 124 | cmd->resp[0], cmd->resp[1], cmd->resp[2], | ||
| 125 | cmd->resp[2], cmd->error); | ||
| 126 | if (data) | ||
| 127 | seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", | ||
| 128 | data->bytes_xfered, data->blocks, | ||
| 129 | data->blksz, data->flags, data->error); | ||
| 130 | if (stop) | ||
| 131 | seq_printf(s, | ||
| 132 | "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", | ||
| 133 | stop->opcode, stop->arg, stop->flags, | ||
| 134 | stop->resp[0], stop->resp[1], stop->resp[2], | ||
| 135 | stop->resp[2], stop->error); | ||
| 136 | } | ||
| 137 | |||
| 138 | spin_unlock_bh(&slot->host->lock); | ||
| 139 | |||
| 140 | return 0; | ||
| 141 | } | ||
| 142 | |||
| 143 | static int dw_mci_req_open(struct inode *inode, struct file *file) | ||
| 144 | { | ||
| 145 | return single_open(file, dw_mci_req_show, inode->i_private); | ||
| 146 | } | ||
| 147 | |||
| 148 | static const struct file_operations dw_mci_req_fops = { | ||
| 149 | .owner = THIS_MODULE, | ||
| 150 | .open = dw_mci_req_open, | ||
| 151 | .read = seq_read, | ||
| 152 | .llseek = seq_lseek, | ||
| 153 | .release = single_release, | ||
| 154 | }; | ||
| 155 | |||
| 156 | static int dw_mci_regs_show(struct seq_file *s, void *v) | ||
| 157 | { | ||
| 158 | seq_printf(s, "STATUS:\t0x%08x\n", SDMMC_STATUS); | ||
| 159 | seq_printf(s, "RINTSTS:\t0x%08x\n", SDMMC_RINTSTS); | ||
| 160 | seq_printf(s, "CMD:\t0x%08x\n", SDMMC_CMD); | ||
| 161 | seq_printf(s, "CTRL:\t0x%08x\n", SDMMC_CTRL); | ||
| 162 | seq_printf(s, "INTMASK:\t0x%08x\n", SDMMC_INTMASK); | ||
| 163 | seq_printf(s, "CLKENA:\t0x%08x\n", SDMMC_CLKENA); | ||
| 164 | |||
| 165 | return 0; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int dw_mci_regs_open(struct inode *inode, struct file *file) | ||
| 169 | { | ||
| 170 | return single_open(file, dw_mci_regs_show, inode->i_private); | ||
| 171 | } | ||
| 172 | |||
| 173 | static const struct file_operations dw_mci_regs_fops = { | ||
| 174 | .owner = THIS_MODULE, | ||
| 175 | .open = dw_mci_regs_open, | ||
| 176 | .read = seq_read, | ||
| 177 | .llseek = seq_lseek, | ||
| 178 | .release = single_release, | ||
| 179 | }; | ||
| 180 | |||
| 181 | static void dw_mci_init_debugfs(struct dw_mci_slot *slot) | ||
| 182 | { | ||
| 183 | struct mmc_host *mmc = slot->mmc; | ||
| 184 | struct dw_mci *host = slot->host; | ||
| 185 | struct dentry *root; | ||
| 186 | struct dentry *node; | ||
| 187 | |||
| 188 | root = mmc->debugfs_root; | ||
| 189 | if (!root) | ||
| 190 | return; | ||
| 191 | |||
| 192 | node = debugfs_create_file("regs", S_IRUSR, root, host, | ||
| 193 | &dw_mci_regs_fops); | ||
| 194 | if (!node) | ||
| 195 | goto err; | ||
| 196 | |||
| 197 | node = debugfs_create_file("req", S_IRUSR, root, slot, | ||
| 198 | &dw_mci_req_fops); | ||
| 199 | if (!node) | ||
| 200 | goto err; | ||
| 201 | |||
| 202 | node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); | ||
| 203 | if (!node) | ||
| 204 | goto err; | ||
| 205 | |||
| 206 | node = debugfs_create_x32("pending_events", S_IRUSR, root, | ||
| 207 | (u32 *)&host->pending_events); | ||
| 208 | if (!node) | ||
| 209 | goto err; | ||
| 210 | |||
| 211 | node = debugfs_create_x32("completed_events", S_IRUSR, root, | ||
| 212 | (u32 *)&host->completed_events); | ||
| 213 | if (!node) | ||
| 214 | goto err; | ||
| 215 | |||
| 216 | return; | ||
| 217 | |||
| 218 | err: | ||
| 219 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); | ||
| 220 | } | ||
| 221 | #endif /* defined(CONFIG_DEBUG_FS) */ | ||
| 222 | |||
| 223 | static void dw_mci_set_timeout(struct dw_mci *host) | ||
| 224 | { | ||
| 225 | /* timeout (maximum) */ | ||
| 226 | mci_writel(host, TMOUT, 0xffffffff); | ||
| 227 | } | ||
| 228 | |||
| 229 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | ||
| 230 | { | ||
| 231 | struct mmc_data *data; | ||
| 232 | u32 cmdr; | ||
| 233 | cmd->error = -EINPROGRESS; | ||
| 234 | |||
| 235 | cmdr = cmd->opcode; | ||
| 236 | |||
| 237 | if (cmdr == MMC_STOP_TRANSMISSION) | ||
| 238 | cmdr |= SDMMC_CMD_STOP; | ||
| 239 | else | ||
| 240 | cmdr |= SDMMC_CMD_PRV_DAT_WAIT; | ||
| 241 | |||
| 242 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
| 243 | /* We expect a response, so set this bit */ | ||
| 244 | cmdr |= SDMMC_CMD_RESP_EXP; | ||
| 245 | if (cmd->flags & MMC_RSP_136) | ||
| 246 | cmdr |= SDMMC_CMD_RESP_LONG; | ||
| 247 | } | ||
| 248 | |||
| 249 | if (cmd->flags & MMC_RSP_CRC) | ||
| 250 | cmdr |= SDMMC_CMD_RESP_CRC; | ||
| 251 | |||
| 252 | data = cmd->data; | ||
| 253 | if (data) { | ||
| 254 | cmdr |= SDMMC_CMD_DAT_EXP; | ||
| 255 | if (data->flags & MMC_DATA_STREAM) | ||
| 256 | cmdr |= SDMMC_CMD_STRM_MODE; | ||
| 257 | if (data->flags & MMC_DATA_WRITE) | ||
| 258 | cmdr |= SDMMC_CMD_DAT_WR; | ||
| 259 | } | ||
| 260 | |||
| 261 | return cmdr; | ||
| 262 | } | ||
| 263 | |||
| 264 | static void dw_mci_start_command(struct dw_mci *host, | ||
| 265 | struct mmc_command *cmd, u32 cmd_flags) | ||
| 266 | { | ||
| 267 | host->cmd = cmd; | ||
| 268 | dev_vdbg(&host->pdev->dev, | ||
| 269 | "start command: ARGR=0x%08x CMDR=0x%08x\n", | ||
| 270 | cmd->arg, cmd_flags); | ||
| 271 | |||
| 272 | mci_writel(host, CMDARG, cmd->arg); | ||
| 273 | wmb(); | ||
| 274 | |||
| 275 | mci_writel(host, CMD, cmd_flags | SDMMC_CMD_START); | ||
| 276 | } | ||
| 277 | |||
| 278 | static void send_stop_cmd(struct dw_mci *host, struct mmc_data *data) | ||
| 279 | { | ||
| 280 | dw_mci_start_command(host, data->stop, host->stop_cmdr); | ||
| 281 | } | ||
| 282 | |||
| 283 | /* DMA interface functions */ | ||
| 284 | static void dw_mci_stop_dma(struct dw_mci *host) | ||
| 285 | { | ||
| 286 | if (host->use_dma) { | ||
| 287 | host->dma_ops->stop(host); | ||
| 288 | host->dma_ops->cleanup(host); | ||
| 289 | } else { | ||
| 290 | /* Data transfer was stopped by the interrupt handler */ | ||
| 291 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | #ifdef CONFIG_MMC_DW_IDMAC | ||
| 296 | static void dw_mci_dma_cleanup(struct dw_mci *host) | ||
| 297 | { | ||
| 298 | struct mmc_data *data = host->data; | ||
| 299 | |||
| 300 | if (data) | ||
| 301 | dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, | ||
| 302 | ((data->flags & MMC_DATA_WRITE) | ||
| 303 | ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); | ||
| 304 | } | ||
| 305 | |||
| 306 | static void dw_mci_idmac_stop_dma(struct dw_mci *host) | ||
| 307 | { | ||
| 308 | u32 temp; | ||
| 309 | |||
| 310 | /* Disable and reset the IDMAC interface */ | ||
| 311 | temp = mci_readl(host, CTRL); | ||
| 312 | temp &= ~SDMMC_CTRL_USE_IDMAC; | ||
| 313 | temp |= SDMMC_CTRL_DMA_RESET; | ||
| 314 | mci_writel(host, CTRL, temp); | ||
| 315 | |||
| 316 | /* Stop the IDMAC running */ | ||
| 317 | temp = mci_readl(host, BMOD); | ||
| 318 | temp &= ~SDMMC_IDMAC_ENABLE; | ||
| 319 | mci_writel(host, BMOD, temp); | ||
| 320 | } | ||
| 321 | |||
| 322 | static void dw_mci_idmac_complete_dma(struct dw_mci *host) | ||
| 323 | { | ||
| 324 | struct mmc_data *data = host->data; | ||
| 325 | |||
| 326 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); | ||
| 327 | |||
| 328 | host->dma_ops->cleanup(host); | ||
| 329 | |||
| 330 | /* | ||
| 331 | * If the card was removed, data will be NULL. No point in trying to | ||
| 332 | * send the stop command or waiting for NBUSY in this case. | ||
| 333 | */ | ||
| 334 | if (data) { | ||
| 335 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | ||
| 336 | tasklet_schedule(&host->tasklet); | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | static void dw_mci_translate_sglist(struct dw_mci *host, struct mmc_data *data, | ||
| 341 | unsigned int sg_len) | ||
| 342 | { | ||
| 343 | int i; | ||
| 344 | struct idmac_desc *desc = host->sg_cpu; | ||
| 345 | |||
| 346 | for (i = 0; i < sg_len; i++, desc++) { | ||
| 347 | unsigned int length = sg_dma_len(&data->sg[i]); | ||
| 348 | u32 mem_addr = sg_dma_address(&data->sg[i]); | ||
| 349 | |||
| 350 | /* Set the OWN bit and disable interrupts for this descriptor */ | ||
| 351 | desc->des0 = IDMAC_DES0_OWN | IDMAC_DES0_DIC | IDMAC_DES0_CH; | ||
| 352 | |||
| 353 | /* Buffer length */ | ||
| 354 | IDMAC_SET_BUFFER1_SIZE(desc, length); | ||
| 355 | |||
| 356 | /* Physical address to DMA to/from */ | ||
| 357 | desc->des2 = mem_addr; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* Set first descriptor */ | ||
| 361 | desc = host->sg_cpu; | ||
| 362 | desc->des0 |= IDMAC_DES0_FD; | ||
| 363 | |||
| 364 | /* Set last descriptor */ | ||
| 365 | desc = host->sg_cpu + (i - 1) * sizeof(struct idmac_desc); | ||
| 366 | desc->des0 &= ~(IDMAC_DES0_CH | IDMAC_DES0_DIC); | ||
| 367 | desc->des0 |= IDMAC_DES0_LD; | ||
| 368 | |||
| 369 | wmb(); | ||
| 370 | } | ||
| 371 | |||
| 372 | static void dw_mci_idmac_start_dma(struct dw_mci *host, unsigned int sg_len) | ||
| 373 | { | ||
| 374 | u32 temp; | ||
| 375 | |||
| 376 | dw_mci_translate_sglist(host, host->data, sg_len); | ||
| 377 | |||
| 378 | /* Select IDMAC interface */ | ||
| 379 | temp = mci_readl(host, CTRL); | ||
| 380 | temp |= SDMMC_CTRL_USE_IDMAC; | ||
| 381 | mci_writel(host, CTRL, temp); | ||
| 382 | |||
| 383 | wmb(); | ||
| 384 | |||
| 385 | /* Enable the IDMAC */ | ||
| 386 | temp = mci_readl(host, BMOD); | ||
| 387 | temp |= SDMMC_IDMAC_ENABLE; | ||
| 388 | mci_writel(host, BMOD, temp); | ||
| 389 | |||
| 390 | /* Start it running */ | ||
| 391 | mci_writel(host, PLDMND, 1); | ||
| 392 | } | ||
| 393 | |||
| 394 | static int dw_mci_idmac_init(struct dw_mci *host) | ||
| 395 | { | ||
| 396 | struct idmac_desc *p; | ||
| 397 | int i; | ||
| 398 | |||
| 399 | /* Number of descriptors in the ring buffer */ | ||
| 400 | host->ring_size = PAGE_SIZE / sizeof(struct idmac_desc); | ||
| 401 | |||
| 402 | /* Forward link the descriptor list */ | ||
| 403 | for (i = 0, p = host->sg_cpu; i < host->ring_size - 1; i++, p++) | ||
| 404 | p->des3 = host->sg_dma + (sizeof(struct idmac_desc) * (i + 1)); | ||
| 405 | |||
| 406 | /* Set the last descriptor as the end-of-ring descriptor */ | ||
| 407 | p->des3 = host->sg_dma; | ||
| 408 | p->des0 = IDMAC_DES0_ER; | ||
| 409 | |||
| 410 | /* Mask out interrupts - get Tx & Rx complete only */ | ||
| 411 | mci_writel(host, IDINTEN, SDMMC_IDMAC_INT_NI | SDMMC_IDMAC_INT_RI | | ||
| 412 | SDMMC_IDMAC_INT_TI); | ||
| 413 | |||
| 414 | /* Set the descriptor base address */ | ||
| 415 | mci_writel(host, DBADDR, host->sg_dma); | ||
| 416 | return 0; | ||
| 417 | } | ||
| 418 | |||
| 419 | static struct dw_mci_dma_ops dw_mci_idmac_ops = { | ||
| 420 | .init = dw_mci_idmac_init, | ||
| 421 | .start = dw_mci_idmac_start_dma, | ||
| 422 | .stop = dw_mci_idmac_stop_dma, | ||
| 423 | .complete = dw_mci_idmac_complete_dma, | ||
| 424 | .cleanup = dw_mci_dma_cleanup, | ||
| 425 | }; | ||
| 426 | #endif /* CONFIG_MMC_DW_IDMAC */ | ||
| 427 | |||
| 428 | static int dw_mci_submit_data_dma(struct dw_mci *host, struct mmc_data *data) | ||
| 429 | { | ||
| 430 | struct scatterlist *sg; | ||
| 431 | unsigned int i, direction, sg_len; | ||
| 432 | u32 temp; | ||
| 433 | |||
| 434 | /* If we don't have a channel, we can't do DMA */ | ||
| 435 | if (!host->use_dma) | ||
| 436 | return -ENODEV; | ||
| 437 | |||
| 438 | /* | ||
| 439 | * We don't do DMA on "complex" transfers, i.e. with | ||
| 440 | * non-word-aligned buffers or lengths. Also, we don't bother | ||
| 441 | * with all the DMA setup overhead for short transfers. | ||
| 442 | */ | ||
| 443 | if (data->blocks * data->blksz < DW_MCI_DMA_THRESHOLD) | ||
| 444 | return -EINVAL; | ||
| 445 | if (data->blksz & 3) | ||
| 446 | return -EINVAL; | ||
| 447 | |||
| 448 | for_each_sg(data->sg, sg, data->sg_len, i) { | ||
| 449 | if (sg->offset & 3 || sg->length & 3) | ||
| 450 | return -EINVAL; | ||
| 451 | } | ||
| 452 | |||
| 453 | if (data->flags & MMC_DATA_READ) | ||
| 454 | direction = DMA_FROM_DEVICE; | ||
| 455 | else | ||
| 456 | direction = DMA_TO_DEVICE; | ||
| 457 | |||
| 458 | sg_len = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, | ||
| 459 | direction); | ||
| 460 | |||
| 461 | dev_vdbg(&host->pdev->dev, | ||
| 462 | "sd sg_cpu: %#lx sg_dma: %#lx sg_len: %d\n", | ||
| 463 | (unsigned long)host->sg_cpu, (unsigned long)host->sg_dma, | ||
| 464 | sg_len); | ||
| 465 | |||
| 466 | /* Enable the DMA interface */ | ||
| 467 | temp = mci_readl(host, CTRL); | ||
| 468 | temp |= SDMMC_CTRL_DMA_ENABLE; | ||
| 469 | mci_writel(host, CTRL, temp); | ||
| 470 | |||
| 471 | /* Disable RX/TX IRQs, let DMA handle it */ | ||
| 472 | temp = mci_readl(host, INTMASK); | ||
| 473 | temp &= ~(SDMMC_INT_RXDR | SDMMC_INT_TXDR); | ||
| 474 | mci_writel(host, INTMASK, temp); | ||
| 475 | |||
| 476 | host->dma_ops->start(host, sg_len); | ||
| 477 | |||
| 478 | return 0; | ||
| 479 | } | ||
| 480 | |||
| 481 | static void dw_mci_submit_data(struct dw_mci *host, struct mmc_data *data) | ||
| 482 | { | ||
| 483 | u32 temp; | ||
| 484 | |||
| 485 | data->error = -EINPROGRESS; | ||
| 486 | |||
| 487 | WARN_ON(host->data); | ||
| 488 | host->sg = NULL; | ||
| 489 | host->data = data; | ||
| 490 | |||
| 491 | if (dw_mci_submit_data_dma(host, data)) { | ||
| 492 | host->sg = data->sg; | ||
| 493 | host->pio_offset = 0; | ||
| 494 | if (data->flags & MMC_DATA_READ) | ||
| 495 | host->dir_status = DW_MCI_RECV_STATUS; | ||
| 496 | else | ||
| 497 | host->dir_status = DW_MCI_SEND_STATUS; | ||
| 498 | |||
| 499 | temp = mci_readl(host, INTMASK); | ||
| 500 | temp |= SDMMC_INT_TXDR | SDMMC_INT_RXDR; | ||
| 501 | mci_writel(host, INTMASK, temp); | ||
| 502 | |||
| 503 | temp = mci_readl(host, CTRL); | ||
| 504 | temp &= ~SDMMC_CTRL_DMA_ENABLE; | ||
| 505 | mci_writel(host, CTRL, temp); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | |||
| 509 | static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg) | ||
| 510 | { | ||
| 511 | struct dw_mci *host = slot->host; | ||
| 512 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | ||
| 513 | unsigned int cmd_status = 0; | ||
| 514 | |||
| 515 | mci_writel(host, CMDARG, arg); | ||
| 516 | wmb(); | ||
| 517 | mci_writel(host, CMD, SDMMC_CMD_START | cmd); | ||
| 518 | |||
| 519 | while (time_before(jiffies, timeout)) { | ||
| 520 | cmd_status = mci_readl(host, CMD); | ||
| 521 | if (!(cmd_status & SDMMC_CMD_START)) | ||
| 522 | return; | ||
| 523 | } | ||
| 524 | dev_err(&slot->mmc->class_dev, | ||
| 525 | "Timeout sending command (cmd %#x arg %#x status %#x)\n", | ||
| 526 | cmd, arg, cmd_status); | ||
| 527 | } | ||
| 528 | |||
| 529 | static void dw_mci_setup_bus(struct dw_mci_slot *slot) | ||
| 530 | { | ||
| 531 | struct dw_mci *host = slot->host; | ||
| 532 | u32 div; | ||
| 533 | |||
| 534 | if (slot->clock != host->current_speed) { | ||
| 535 | if (host->bus_hz % slot->clock) | ||
| 536 | /* | ||
| 537 | * move the + 1 after the divide to prevent | ||
| 538 | * over-clocking the card. | ||
| 539 | */ | ||
| 540 | div = ((host->bus_hz / slot->clock) >> 1) + 1; | ||
| 541 | else | ||
| 542 | div = (host->bus_hz / slot->clock) >> 1; | ||
| 543 | |||
| 544 | dev_info(&slot->mmc->class_dev, | ||
| 545 | "Bus speed (slot %d) = %dHz (slot req %dHz, actual %dHZ" | ||
| 546 | " div = %d)\n", slot->id, host->bus_hz, slot->clock, | ||
| 547 | div ? ((host->bus_hz / div) >> 1) : host->bus_hz, div); | ||
| 548 | |||
| 549 | /* disable clock */ | ||
| 550 | mci_writel(host, CLKENA, 0); | ||
| 551 | mci_writel(host, CLKSRC, 0); | ||
| 552 | |||
| 553 | /* inform CIU */ | ||
| 554 | mci_send_cmd(slot, | ||
| 555 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
| 556 | |||
| 557 | /* set clock to desired speed */ | ||
| 558 | mci_writel(host, CLKDIV, div); | ||
| 559 | |||
| 560 | /* inform CIU */ | ||
| 561 | mci_send_cmd(slot, | ||
| 562 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
| 563 | |||
| 564 | /* enable clock */ | ||
| 565 | mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE); | ||
| 566 | |||
| 567 | /* inform CIU */ | ||
| 568 | mci_send_cmd(slot, | ||
| 569 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
| 570 | |||
| 571 | host->current_speed = slot->clock; | ||
| 572 | } | ||
| 573 | |||
| 574 | /* Set the current slot bus width */ | ||
| 575 | mci_writel(host, CTYPE, slot->ctype); | ||
| 576 | } | ||
| 577 | |||
| 578 | static void dw_mci_start_request(struct dw_mci *host, | ||
| 579 | struct dw_mci_slot *slot) | ||
| 580 | { | ||
| 581 | struct mmc_request *mrq; | ||
| 582 | struct mmc_command *cmd; | ||
| 583 | struct mmc_data *data; | ||
| 584 | u32 cmdflags; | ||
| 585 | |||
| 586 | mrq = slot->mrq; | ||
| 587 | if (host->pdata->select_slot) | ||
| 588 | host->pdata->select_slot(slot->id); | ||
| 589 | |||
| 590 | /* Slot specific timing and width adjustment */ | ||
| 591 | dw_mci_setup_bus(slot); | ||
| 592 | |||
| 593 | host->cur_slot = slot; | ||
| 594 | host->mrq = mrq; | ||
| 595 | |||
| 596 | host->pending_events = 0; | ||
| 597 | host->completed_events = 0; | ||
| 598 | host->data_status = 0; | ||
| 599 | |||
| 600 | data = mrq->data; | ||
| 601 | if (data) { | ||
| 602 | dw_mci_set_timeout(host); | ||
| 603 | mci_writel(host, BYTCNT, data->blksz*data->blocks); | ||
| 604 | mci_writel(host, BLKSIZ, data->blksz); | ||
| 605 | } | ||
| 606 | |||
| 607 | cmd = mrq->cmd; | ||
| 608 | cmdflags = dw_mci_prepare_command(slot->mmc, cmd); | ||
| 609 | |||
| 610 | /* this is the first command, send the initialization clock */ | ||
| 611 | if (test_and_clear_bit(DW_MMC_CARD_NEED_INIT, &slot->flags)) | ||
| 612 | cmdflags |= SDMMC_CMD_INIT; | ||
| 613 | |||
| 614 | if (data) { | ||
| 615 | dw_mci_submit_data(host, data); | ||
| 616 | wmb(); | ||
| 617 | } | ||
| 618 | |||
| 619 | dw_mci_start_command(host, cmd, cmdflags); | ||
| 620 | |||
| 621 | if (mrq->stop) | ||
| 622 | host->stop_cmdr = dw_mci_prepare_command(slot->mmc, mrq->stop); | ||
| 623 | } | ||
| 624 | |||
| 625 | static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, | ||
| 626 | struct mmc_request *mrq) | ||
| 627 | { | ||
| 628 | dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n", | ||
| 629 | host->state); | ||
| 630 | |||
| 631 | spin_lock_bh(&host->lock); | ||
| 632 | slot->mrq = mrq; | ||
| 633 | |||
| 634 | if (host->state == STATE_IDLE) { | ||
| 635 | host->state = STATE_SENDING_CMD; | ||
| 636 | dw_mci_start_request(host, slot); | ||
| 637 | } else { | ||
| 638 | list_add_tail(&slot->queue_node, &host->queue); | ||
| 639 | } | ||
| 640 | |||
| 641 | spin_unlock_bh(&host->lock); | ||
| 642 | } | ||
| 643 | |||
| 644 | static void dw_mci_request(struct mmc_host *mmc, struct mmc_request *mrq) | ||
| 645 | { | ||
| 646 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
| 647 | struct dw_mci *host = slot->host; | ||
| 648 | |||
| 649 | WARN_ON(slot->mrq); | ||
| 650 | |||
| 651 | if (!test_bit(DW_MMC_CARD_PRESENT, &slot->flags)) { | ||
| 652 | mrq->cmd->error = -ENOMEDIUM; | ||
| 653 | mmc_request_done(mmc, mrq); | ||
| 654 | return; | ||
| 655 | } | ||
| 656 | |||
| 657 | /* We don't support multiple blocks of weird lengths. */ | ||
| 658 | dw_mci_queue_request(host, slot, mrq); | ||
| 659 | } | ||
| 660 | |||
| 661 | static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | ||
| 662 | { | ||
| 663 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
| 664 | |||
| 665 | /* set default 1 bit mode */ | ||
| 666 | slot->ctype = SDMMC_CTYPE_1BIT; | ||
| 667 | |||
| 668 | switch (ios->bus_width) { | ||
| 669 | case MMC_BUS_WIDTH_1: | ||
| 670 | slot->ctype = SDMMC_CTYPE_1BIT; | ||
| 671 | break; | ||
| 672 | case MMC_BUS_WIDTH_4: | ||
| 673 | slot->ctype = SDMMC_CTYPE_4BIT; | ||
| 674 | break; | ||
| 675 | } | ||
| 676 | |||
| 677 | if (ios->clock) { | ||
| 678 | /* | ||
| 679 | * Use mirror of ios->clock to prevent race with mmc | ||
| 680 | * core ios update when finding the minimum. | ||
| 681 | */ | ||
| 682 | slot->clock = ios->clock; | ||
| 683 | } | ||
| 684 | |||
| 685 | switch (ios->power_mode) { | ||
| 686 | case MMC_POWER_UP: | ||
| 687 | set_bit(DW_MMC_CARD_NEED_INIT, &slot->flags); | ||
| 688 | break; | ||
| 689 | default: | ||
| 690 | break; | ||
| 691 | } | ||
| 692 | } | ||
| 693 | |||
| 694 | static int dw_mci_get_ro(struct mmc_host *mmc) | ||
| 695 | { | ||
| 696 | int read_only; | ||
| 697 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
| 698 | struct dw_mci_board *brd = slot->host->pdata; | ||
| 699 | |||
| 700 | /* Use platform get_ro function, else try on board write protect */ | ||
| 701 | if (brd->get_ro) | ||
| 702 | read_only = brd->get_ro(slot->id); | ||
| 703 | else | ||
| 704 | read_only = | ||
| 705 | mci_readl(slot->host, WRTPRT) & (1 << slot->id) ? 1 : 0; | ||
| 706 | |||
| 707 | dev_dbg(&mmc->class_dev, "card is %s\n", | ||
| 708 | read_only ? "read-only" : "read-write"); | ||
| 709 | |||
| 710 | return read_only; | ||
| 711 | } | ||
| 712 | |||
| 713 | static int dw_mci_get_cd(struct mmc_host *mmc) | ||
| 714 | { | ||
| 715 | int present; | ||
| 716 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
| 717 | struct dw_mci_board *brd = slot->host->pdata; | ||
| 718 | |||
| 719 | /* Use platform get_cd function, else try onboard card detect */ | ||
| 720 | if (brd->get_cd) | ||
| 721 | present = !brd->get_cd(slot->id); | ||
| 722 | else | ||
| 723 | present = (mci_readl(slot->host, CDETECT) & (1 << slot->id)) | ||
| 724 | == 0 ? 1 : 0; | ||
| 725 | |||
| 726 | if (present) | ||
| 727 | dev_dbg(&mmc->class_dev, "card is present\n"); | ||
| 728 | else | ||
| 729 | dev_dbg(&mmc->class_dev, "card is not present\n"); | ||
| 730 | |||
| 731 | return present; | ||
| 732 | } | ||
| 733 | |||
| 734 | static const struct mmc_host_ops dw_mci_ops = { | ||
| 735 | .request = dw_mci_request, | ||
| 736 | .set_ios = dw_mci_set_ios, | ||
| 737 | .get_ro = dw_mci_get_ro, | ||
| 738 | .get_cd = dw_mci_get_cd, | ||
| 739 | }; | ||
| 740 | |||
| 741 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | ||
| 742 | __releases(&host->lock) | ||
| 743 | __acquires(&host->lock) | ||
| 744 | { | ||
| 745 | struct dw_mci_slot *slot; | ||
| 746 | struct mmc_host *prev_mmc = host->cur_slot->mmc; | ||
| 747 | |||
| 748 | WARN_ON(host->cmd || host->data); | ||
| 749 | |||
| 750 | host->cur_slot->mrq = NULL; | ||
| 751 | host->mrq = NULL; | ||
| 752 | if (!list_empty(&host->queue)) { | ||
| 753 | slot = list_entry(host->queue.next, | ||
| 754 | struct dw_mci_slot, queue_node); | ||
| 755 | list_del(&slot->queue_node); | ||
| 756 | dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n", | ||
| 757 | mmc_hostname(slot->mmc)); | ||
| 758 | host->state = STATE_SENDING_CMD; | ||
| 759 | dw_mci_start_request(host, slot); | ||
| 760 | } else { | ||
| 761 | dev_vdbg(&host->pdev->dev, "list empty\n"); | ||
| 762 | host->state = STATE_IDLE; | ||
| 763 | } | ||
| 764 | |||
| 765 | spin_unlock(&host->lock); | ||
| 766 | mmc_request_done(prev_mmc, mrq); | ||
| 767 | spin_lock(&host->lock); | ||
| 768 | } | ||
| 769 | |||
| 770 | static void dw_mci_command_complete(struct dw_mci *host, struct mmc_command *cmd) | ||
| 771 | { | ||
| 772 | u32 status = host->cmd_status; | ||
| 773 | |||
| 774 | host->cmd_status = 0; | ||
| 775 | |||
| 776 | /* Read the response from the card (up to 16 bytes) */ | ||
| 777 | if (cmd->flags & MMC_RSP_PRESENT) { | ||
| 778 | if (cmd->flags & MMC_RSP_136) { | ||
| 779 | cmd->resp[3] = mci_readl(host, RESP0); | ||
| 780 | cmd->resp[2] = mci_readl(host, RESP1); | ||
| 781 | cmd->resp[1] = mci_readl(host, RESP2); | ||
| 782 | cmd->resp[0] = mci_readl(host, RESP3); | ||
| 783 | } else { | ||
| 784 | cmd->resp[0] = mci_readl(host, RESP0); | ||
| 785 | cmd->resp[1] = 0; | ||
| 786 | cmd->resp[2] = 0; | ||
| 787 | cmd->resp[3] = 0; | ||
| 788 | } | ||
| 789 | } | ||
| 790 | |||
| 791 | if (status & SDMMC_INT_RTO) | ||
| 792 | cmd->error = -ETIMEDOUT; | ||
| 793 | else if ((cmd->flags & MMC_RSP_CRC) && (status & SDMMC_INT_RCRC)) | ||
| 794 | cmd->error = -EILSEQ; | ||
| 795 | else if (status & SDMMC_INT_RESP_ERR) | ||
| 796 | cmd->error = -EIO; | ||
| 797 | else | ||
| 798 | cmd->error = 0; | ||
| 799 | |||
| 800 | if (cmd->error) { | ||
| 801 | /* newer ip versions need a delay between retries */ | ||
| 802 | if (host->quirks & DW_MCI_QUIRK_RETRY_DELAY) | ||
| 803 | mdelay(20); | ||
| 804 | |||
| 805 | if (cmd->data) { | ||
| 806 | host->data = NULL; | ||
| 807 | dw_mci_stop_dma(host); | ||
| 808 | } | ||
| 809 | } | ||
| 810 | } | ||
| 811 | |||
| 812 | static void dw_mci_tasklet_func(unsigned long priv) | ||
| 813 | { | ||
| 814 | struct dw_mci *host = (struct dw_mci *)priv; | ||
| 815 | struct mmc_data *data; | ||
| 816 | struct mmc_command *cmd; | ||
| 817 | enum dw_mci_state state; | ||
| 818 | enum dw_mci_state prev_state; | ||
| 819 | u32 status; | ||
| 820 | |||
| 821 | spin_lock(&host->lock); | ||
| 822 | |||
| 823 | state = host->state; | ||
| 824 | data = host->data; | ||
| 825 | |||
| 826 | do { | ||
| 827 | prev_state = state; | ||
| 828 | |||
| 829 | switch (state) { | ||
| 830 | case STATE_IDLE: | ||
| 831 | break; | ||
| 832 | |||
| 833 | case STATE_SENDING_CMD: | ||
| 834 | if (!test_and_clear_bit(EVENT_CMD_COMPLETE, | ||
| 835 | &host->pending_events)) | ||
| 836 | break; | ||
| 837 | |||
| 838 | cmd = host->cmd; | ||
| 839 | host->cmd = NULL; | ||
| 840 | set_bit(EVENT_CMD_COMPLETE, &host->completed_events); | ||
| 841 | dw_mci_command_complete(host, host->mrq->cmd); | ||
| 842 | if (!host->mrq->data || cmd->error) { | ||
| 843 | dw_mci_request_end(host, host->mrq); | ||
| 844 | goto unlock; | ||
| 845 | } | ||
| 846 | |||
| 847 | prev_state = state = STATE_SENDING_DATA; | ||
| 848 | /* fall through */ | ||
| 849 | |||
| 850 | case STATE_SENDING_DATA: | ||
| 851 | if (test_and_clear_bit(EVENT_DATA_ERROR, | ||
| 852 | &host->pending_events)) { | ||
| 853 | dw_mci_stop_dma(host); | ||
| 854 | if (data->stop) | ||
| 855 | send_stop_cmd(host, data); | ||
| 856 | state = STATE_DATA_ERROR; | ||
| 857 | break; | ||
| 858 | } | ||
| 859 | |||
| 860 | if (!test_and_clear_bit(EVENT_XFER_COMPLETE, | ||
| 861 | &host->pending_events)) | ||
| 862 | break; | ||
| 863 | |||
| 864 | set_bit(EVENT_XFER_COMPLETE, &host->completed_events); | ||
| 865 | prev_state = state = STATE_DATA_BUSY; | ||
| 866 | /* fall through */ | ||
| 867 | |||
| 868 | case STATE_DATA_BUSY: | ||
| 869 | if (!test_and_clear_bit(EVENT_DATA_COMPLETE, | ||
| 870 | &host->pending_events)) | ||
| 871 | break; | ||
| 872 | |||
| 873 | host->data = NULL; | ||
| 874 | set_bit(EVENT_DATA_COMPLETE, &host->completed_events); | ||
| 875 | status = host->data_status; | ||
| 876 | |||
| 877 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 878 | if (status & SDMMC_INT_DTO) { | ||
| 879 | dev_err(&host->pdev->dev, | ||
| 880 | "data timeout error\n"); | ||
| 881 | data->error = -ETIMEDOUT; | ||
| 882 | } else if (status & SDMMC_INT_DCRC) { | ||
| 883 | dev_err(&host->pdev->dev, | ||
| 884 | "data CRC error\n"); | ||
| 885 | data->error = -EILSEQ; | ||
| 886 | } else { | ||
| 887 | dev_err(&host->pdev->dev, | ||
| 888 | "data FIFO error " | ||
| 889 | "(status=%08x)\n", | ||
| 890 | status); | ||
| 891 | data->error = -EIO; | ||
| 892 | } | ||
| 893 | } else { | ||
| 894 | data->bytes_xfered = data->blocks * data->blksz; | ||
| 895 | data->error = 0; | ||
| 896 | } | ||
| 897 | |||
| 898 | if (!data->stop) { | ||
| 899 | dw_mci_request_end(host, host->mrq); | ||
| 900 | goto unlock; | ||
| 901 | } | ||
| 902 | |||
| 903 | prev_state = state = STATE_SENDING_STOP; | ||
| 904 | if (!data->error) | ||
| 905 | send_stop_cmd(host, data); | ||
| 906 | /* fall through */ | ||
| 907 | |||
| 908 | case STATE_SENDING_STOP: | ||
| 909 | if (!test_and_clear_bit(EVENT_CMD_COMPLETE, | ||
| 910 | &host->pending_events)) | ||
| 911 | break; | ||
| 912 | |||
| 913 | host->cmd = NULL; | ||
| 914 | dw_mci_command_complete(host, host->mrq->stop); | ||
| 915 | dw_mci_request_end(host, host->mrq); | ||
| 916 | goto unlock; | ||
| 917 | |||
| 918 | case STATE_DATA_ERROR: | ||
| 919 | if (!test_and_clear_bit(EVENT_XFER_COMPLETE, | ||
| 920 | &host->pending_events)) | ||
| 921 | break; | ||
| 922 | |||
| 923 | state = STATE_DATA_BUSY; | ||
| 924 | break; | ||
| 925 | } | ||
| 926 | } while (state != prev_state); | ||
| 927 | |||
| 928 | host->state = state; | ||
| 929 | unlock: | ||
| 930 | spin_unlock(&host->lock); | ||
| 931 | |||
| 932 | } | ||
| 933 | |||
| 934 | static void dw_mci_push_data16(struct dw_mci *host, void *buf, int cnt) | ||
| 935 | { | ||
| 936 | u16 *pdata = (u16 *)buf; | ||
| 937 | |||
| 938 | WARN_ON(cnt % 2 != 0); | ||
| 939 | |||
| 940 | cnt = cnt >> 1; | ||
| 941 | while (cnt > 0) { | ||
| 942 | mci_writew(host, DATA, *pdata++); | ||
| 943 | cnt--; | ||
| 944 | } | ||
| 945 | } | ||
| 946 | |||
| 947 | static void dw_mci_pull_data16(struct dw_mci *host, void *buf, int cnt) | ||
| 948 | { | ||
| 949 | u16 *pdata = (u16 *)buf; | ||
| 950 | |||
| 951 | WARN_ON(cnt % 2 != 0); | ||
| 952 | |||
| 953 | cnt = cnt >> 1; | ||
| 954 | while (cnt > 0) { | ||
| 955 | *pdata++ = mci_readw(host, DATA); | ||
| 956 | cnt--; | ||
| 957 | } | ||
| 958 | } | ||
| 959 | |||
| 960 | static void dw_mci_push_data32(struct dw_mci *host, void *buf, int cnt) | ||
| 961 | { | ||
| 962 | u32 *pdata = (u32 *)buf; | ||
| 963 | |||
| 964 | WARN_ON(cnt % 4 != 0); | ||
| 965 | WARN_ON((unsigned long)pdata & 0x3); | ||
| 966 | |||
| 967 | cnt = cnt >> 2; | ||
| 968 | while (cnt > 0) { | ||
| 969 | mci_writel(host, DATA, *pdata++); | ||
| 970 | cnt--; | ||
| 971 | } | ||
| 972 | } | ||
| 973 | |||
| 974 | static void dw_mci_pull_data32(struct dw_mci *host, void *buf, int cnt) | ||
| 975 | { | ||
| 976 | u32 *pdata = (u32 *)buf; | ||
| 977 | |||
| 978 | WARN_ON(cnt % 4 != 0); | ||
| 979 | WARN_ON((unsigned long)pdata & 0x3); | ||
| 980 | |||
| 981 | cnt = cnt >> 2; | ||
| 982 | while (cnt > 0) { | ||
| 983 | *pdata++ = mci_readl(host, DATA); | ||
| 984 | cnt--; | ||
| 985 | } | ||
| 986 | } | ||
| 987 | |||
| 988 | static void dw_mci_push_data64(struct dw_mci *host, void *buf, int cnt) | ||
| 989 | { | ||
| 990 | u64 *pdata = (u64 *)buf; | ||
| 991 | |||
| 992 | WARN_ON(cnt % 8 != 0); | ||
| 993 | |||
| 994 | cnt = cnt >> 3; | ||
| 995 | while (cnt > 0) { | ||
| 996 | mci_writeq(host, DATA, *pdata++); | ||
| 997 | cnt--; | ||
| 998 | } | ||
| 999 | } | ||
| 1000 | |||
| 1001 | static void dw_mci_pull_data64(struct dw_mci *host, void *buf, int cnt) | ||
| 1002 | { | ||
| 1003 | u64 *pdata = (u64 *)buf; | ||
| 1004 | |||
| 1005 | WARN_ON(cnt % 8 != 0); | ||
| 1006 | |||
| 1007 | cnt = cnt >> 3; | ||
| 1008 | while (cnt > 0) { | ||
| 1009 | *pdata++ = mci_readq(host, DATA); | ||
| 1010 | cnt--; | ||
| 1011 | } | ||
| 1012 | } | ||
| 1013 | |||
| 1014 | static void dw_mci_read_data_pio(struct dw_mci *host) | ||
| 1015 | { | ||
| 1016 | struct scatterlist *sg = host->sg; | ||
| 1017 | void *buf = sg_virt(sg); | ||
| 1018 | unsigned int offset = host->pio_offset; | ||
| 1019 | struct mmc_data *data = host->data; | ||
| 1020 | int shift = host->data_shift; | ||
| 1021 | u32 status; | ||
| 1022 | unsigned int nbytes = 0, len, old_len, count = 0; | ||
| 1023 | |||
| 1024 | do { | ||
| 1025 | len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift; | ||
| 1026 | if (count == 0) | ||
| 1027 | old_len = len; | ||
| 1028 | |||
| 1029 | if (offset + len <= sg->length) { | ||
| 1030 | host->pull_data(host, (void *)(buf + offset), len); | ||
| 1031 | |||
| 1032 | offset += len; | ||
| 1033 | nbytes += len; | ||
| 1034 | |||
| 1035 | if (offset == sg->length) { | ||
| 1036 | flush_dcache_page(sg_page(sg)); | ||
| 1037 | host->sg = sg = sg_next(sg); | ||
| 1038 | if (!sg) | ||
| 1039 | goto done; | ||
| 1040 | |||
| 1041 | offset = 0; | ||
| 1042 | buf = sg_virt(sg); | ||
| 1043 | } | ||
| 1044 | } else { | ||
| 1045 | unsigned int remaining = sg->length - offset; | ||
| 1046 | host->pull_data(host, (void *)(buf + offset), | ||
| 1047 | remaining); | ||
| 1048 | nbytes += remaining; | ||
| 1049 | |||
| 1050 | flush_dcache_page(sg_page(sg)); | ||
| 1051 | host->sg = sg = sg_next(sg); | ||
| 1052 | if (!sg) | ||
| 1053 | goto done; | ||
| 1054 | |||
| 1055 | offset = len - remaining; | ||
| 1056 | buf = sg_virt(sg); | ||
| 1057 | host->pull_data(host, buf, offset); | ||
| 1058 | nbytes += offset; | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | status = mci_readl(host, MINTSTS); | ||
| 1062 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | ||
| 1063 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1064 | host->data_status = status; | ||
| 1065 | data->bytes_xfered += nbytes; | ||
| 1066 | smp_wmb(); | ||
| 1067 | |||
| 1068 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1069 | |||
| 1070 | tasklet_schedule(&host->tasklet); | ||
| 1071 | return; | ||
| 1072 | } | ||
| 1073 | count++; | ||
| 1074 | } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/ | ||
| 1075 | len = SDMMC_GET_FCNT(mci_readl(host, STATUS)); | ||
| 1076 | host->pio_offset = offset; | ||
| 1077 | data->bytes_xfered += nbytes; | ||
| 1078 | return; | ||
| 1079 | |||
| 1080 | done: | ||
| 1081 | data->bytes_xfered += nbytes; | ||
| 1082 | smp_wmb(); | ||
| 1083 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | static void dw_mci_write_data_pio(struct dw_mci *host) | ||
| 1087 | { | ||
| 1088 | struct scatterlist *sg = host->sg; | ||
| 1089 | void *buf = sg_virt(sg); | ||
| 1090 | unsigned int offset = host->pio_offset; | ||
| 1091 | struct mmc_data *data = host->data; | ||
| 1092 | int shift = host->data_shift; | ||
| 1093 | u32 status; | ||
| 1094 | unsigned int nbytes = 0, len; | ||
| 1095 | |||
| 1096 | do { | ||
| 1097 | len = SDMMC_FIFO_SZ - | ||
| 1098 | (SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift); | ||
| 1099 | if (offset + len <= sg->length) { | ||
| 1100 | host->push_data(host, (void *)(buf + offset), len); | ||
| 1101 | |||
| 1102 | offset += len; | ||
| 1103 | nbytes += len; | ||
| 1104 | if (offset == sg->length) { | ||
| 1105 | host->sg = sg = sg_next(sg); | ||
| 1106 | if (!sg) | ||
| 1107 | goto done; | ||
| 1108 | |||
| 1109 | offset = 0; | ||
| 1110 | buf = sg_virt(sg); | ||
| 1111 | } | ||
| 1112 | } else { | ||
| 1113 | unsigned int remaining = sg->length - offset; | ||
| 1114 | |||
| 1115 | host->push_data(host, (void *)(buf + offset), | ||
| 1116 | remaining); | ||
| 1117 | nbytes += remaining; | ||
| 1118 | |||
| 1119 | host->sg = sg = sg_next(sg); | ||
| 1120 | if (!sg) | ||
| 1121 | goto done; | ||
| 1122 | |||
| 1123 | offset = len - remaining; | ||
| 1124 | buf = sg_virt(sg); | ||
| 1125 | host->push_data(host, (void *)buf, offset); | ||
| 1126 | nbytes += offset; | ||
| 1127 | } | ||
| 1128 | |||
| 1129 | status = mci_readl(host, MINTSTS); | ||
| 1130 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | ||
| 1131 | if (status & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1132 | host->data_status = status; | ||
| 1133 | data->bytes_xfered += nbytes; | ||
| 1134 | |||
| 1135 | smp_wmb(); | ||
| 1136 | |||
| 1137 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1138 | |||
| 1139 | tasklet_schedule(&host->tasklet); | ||
| 1140 | return; | ||
| 1141 | } | ||
| 1142 | } while (status & SDMMC_INT_TXDR); /* if TXDR write again */ | ||
| 1143 | |||
| 1144 | host->pio_offset = offset; | ||
| 1145 | data->bytes_xfered += nbytes; | ||
| 1146 | |||
| 1147 | return; | ||
| 1148 | |||
| 1149 | done: | ||
| 1150 | data->bytes_xfered += nbytes; | ||
| 1151 | smp_wmb(); | ||
| 1152 | set_bit(EVENT_XFER_COMPLETE, &host->pending_events); | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status) | ||
| 1156 | { | ||
| 1157 | if (!host->cmd_status) | ||
| 1158 | host->cmd_status = status; | ||
| 1159 | |||
| 1160 | smp_wmb(); | ||
| 1161 | |||
| 1162 | set_bit(EVENT_CMD_COMPLETE, &host->pending_events); | ||
| 1163 | tasklet_schedule(&host->tasklet); | ||
| 1164 | } | ||
| 1165 | |||
| 1166 | static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | ||
| 1167 | { | ||
| 1168 | struct dw_mci *host = dev_id; | ||
| 1169 | u32 status, pending; | ||
| 1170 | unsigned int pass_count = 0; | ||
| 1171 | |||
| 1172 | do { | ||
| 1173 | status = mci_readl(host, RINTSTS); | ||
| 1174 | pending = mci_readl(host, MINTSTS); /* read-only mask reg */ | ||
| 1175 | |||
| 1176 | /* | ||
| 1177 | * DTO fix - version 2.10a and below, and only if internal DMA | ||
| 1178 | * is configured. | ||
| 1179 | */ | ||
| 1180 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) { | ||
| 1181 | if (!pending && | ||
| 1182 | ((mci_readl(host, STATUS) >> 17) & 0x1fff)) | ||
| 1183 | pending |= SDMMC_INT_DATA_OVER; | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | if (!pending) | ||
| 1187 | break; | ||
| 1188 | |||
| 1189 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { | ||
| 1190 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); | ||
| 1191 | host->cmd_status = status; | ||
| 1192 | smp_wmb(); | ||
| 1193 | set_bit(EVENT_CMD_COMPLETE, &host->pending_events); | ||
| 1194 | tasklet_schedule(&host->tasklet); | ||
| 1195 | } | ||
| 1196 | |||
| 1197 | if (pending & DW_MCI_DATA_ERROR_FLAGS) { | ||
| 1198 | /* if there is an error report DATA_ERROR */ | ||
| 1199 | mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS); | ||
| 1200 | host->data_status = status; | ||
| 1201 | smp_wmb(); | ||
| 1202 | set_bit(EVENT_DATA_ERROR, &host->pending_events); | ||
| 1203 | tasklet_schedule(&host->tasklet); | ||
| 1204 | } | ||
| 1205 | |||
| 1206 | if (pending & SDMMC_INT_DATA_OVER) { | ||
| 1207 | mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER); | ||
| 1208 | if (!host->data_status) | ||
| 1209 | host->data_status = status; | ||
| 1210 | smp_wmb(); | ||
| 1211 | if (host->dir_status == DW_MCI_RECV_STATUS) { | ||
| 1212 | if (host->sg != NULL) | ||
| 1213 | dw_mci_read_data_pio(host); | ||
| 1214 | } | ||
| 1215 | set_bit(EVENT_DATA_COMPLETE, &host->pending_events); | ||
| 1216 | tasklet_schedule(&host->tasklet); | ||
| 1217 | } | ||
| 1218 | |||
| 1219 | if (pending & SDMMC_INT_RXDR) { | ||
| 1220 | mci_writel(host, RINTSTS, SDMMC_INT_RXDR); | ||
| 1221 | if (host->sg) | ||
| 1222 | dw_mci_read_data_pio(host); | ||
| 1223 | } | ||
| 1224 | |||
| 1225 | if (pending & SDMMC_INT_TXDR) { | ||
| 1226 | mci_writel(host, RINTSTS, SDMMC_INT_TXDR); | ||
| 1227 | if (host->sg) | ||
| 1228 | dw_mci_write_data_pio(host); | ||
| 1229 | } | ||
| 1230 | |||
| 1231 | if (pending & SDMMC_INT_CMD_DONE) { | ||
| 1232 | mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE); | ||
| 1233 | dw_mci_cmd_interrupt(host, status); | ||
| 1234 | } | ||
| 1235 | |||
| 1236 | if (pending & SDMMC_INT_CD) { | ||
| 1237 | mci_writel(host, RINTSTS, SDMMC_INT_CD); | ||
| 1238 | tasklet_schedule(&host->card_tasklet); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | } while (pass_count++ < 5); | ||
| 1242 | |||
| 1243 | #ifdef CONFIG_MMC_DW_IDMAC | ||
| 1244 | /* Handle DMA interrupts */ | ||
| 1245 | pending = mci_readl(host, IDSTS); | ||
| 1246 | if (pending & (SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI)) { | ||
| 1247 | mci_writel(host, IDSTS, SDMMC_IDMAC_INT_TI | SDMMC_IDMAC_INT_RI); | ||
| 1248 | mci_writel(host, IDSTS, SDMMC_IDMAC_INT_NI); | ||
| 1249 | set_bit(EVENT_DATA_COMPLETE, &host->pending_events); | ||
| 1250 | host->dma_ops->complete(host); | ||
| 1251 | } | ||
| 1252 | #endif | ||
| 1253 | |||
| 1254 | return IRQ_HANDLED; | ||
| 1255 | } | ||
| 1256 | |||
| 1257 | static void dw_mci_tasklet_card(unsigned long data) | ||
| 1258 | { | ||
| 1259 | struct dw_mci *host = (struct dw_mci *)data; | ||
| 1260 | int i; | ||
| 1261 | |||
| 1262 | for (i = 0; i < host->num_slots; i++) { | ||
| 1263 | struct dw_mci_slot *slot = host->slot[i]; | ||
| 1264 | struct mmc_host *mmc = slot->mmc; | ||
| 1265 | struct mmc_request *mrq; | ||
| 1266 | int present; | ||
| 1267 | u32 ctrl; | ||
| 1268 | |||
| 1269 | present = dw_mci_get_cd(mmc); | ||
| 1270 | while (present != slot->last_detect_state) { | ||
| 1271 | spin_lock(&host->lock); | ||
| 1272 | |||
| 1273 | dev_dbg(&slot->mmc->class_dev, "card %s\n", | ||
| 1274 | present ? "inserted" : "removed"); | ||
| 1275 | |||
| 1276 | /* Card change detected */ | ||
| 1277 | slot->last_detect_state = present; | ||
| 1278 | |||
| 1279 | /* Power up slot */ | ||
| 1280 | if (present != 0) { | ||
| 1281 | if (host->pdata->setpower) | ||
| 1282 | host->pdata->setpower(slot->id, | ||
| 1283 | mmc->ocr_avail); | ||
| 1284 | |||
| 1285 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1286 | } | ||
| 1287 | |||
| 1288 | /* Clean up queue if present */ | ||
| 1289 | mrq = slot->mrq; | ||
| 1290 | if (mrq) { | ||
| 1291 | if (mrq == host->mrq) { | ||
| 1292 | host->data = NULL; | ||
| 1293 | host->cmd = NULL; | ||
| 1294 | |||
| 1295 | switch (host->state) { | ||
| 1296 | case STATE_IDLE: | ||
| 1297 | break; | ||
| 1298 | case STATE_SENDING_CMD: | ||
| 1299 | mrq->cmd->error = -ENOMEDIUM; | ||
| 1300 | if (!mrq->data) | ||
| 1301 | break; | ||
| 1302 | /* fall through */ | ||
| 1303 | case STATE_SENDING_DATA: | ||
| 1304 | mrq->data->error = -ENOMEDIUM; | ||
| 1305 | dw_mci_stop_dma(host); | ||
| 1306 | break; | ||
| 1307 | case STATE_DATA_BUSY: | ||
| 1308 | case STATE_DATA_ERROR: | ||
| 1309 | if (mrq->data->error == -EINPROGRESS) | ||
| 1310 | mrq->data->error = -ENOMEDIUM; | ||
| 1311 | if (!mrq->stop) | ||
| 1312 | break; | ||
| 1313 | /* fall through */ | ||
| 1314 | case STATE_SENDING_STOP: | ||
| 1315 | mrq->stop->error = -ENOMEDIUM; | ||
| 1316 | break; | ||
| 1317 | } | ||
| 1318 | |||
| 1319 | dw_mci_request_end(host, mrq); | ||
| 1320 | } else { | ||
| 1321 | list_del(&slot->queue_node); | ||
| 1322 | mrq->cmd->error = -ENOMEDIUM; | ||
| 1323 | if (mrq->data) | ||
| 1324 | mrq->data->error = -ENOMEDIUM; | ||
| 1325 | if (mrq->stop) | ||
| 1326 | mrq->stop->error = -ENOMEDIUM; | ||
| 1327 | |||
| 1328 | spin_unlock(&host->lock); | ||
| 1329 | mmc_request_done(slot->mmc, mrq); | ||
| 1330 | spin_lock(&host->lock); | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | |||
| 1334 | /* Power down slot */ | ||
| 1335 | if (present == 0) { | ||
| 1336 | if (host->pdata->setpower) | ||
| 1337 | host->pdata->setpower(slot->id, 0); | ||
| 1338 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1339 | |||
| 1340 | /* | ||
| 1341 | * Clear down the FIFO - doing so generates a | ||
| 1342 | * block interrupt, hence setting the | ||
| 1343 | * scatter-gather pointer to NULL. | ||
| 1344 | */ | ||
| 1345 | host->sg = NULL; | ||
| 1346 | |||
| 1347 | ctrl = mci_readl(host, CTRL); | ||
| 1348 | ctrl |= SDMMC_CTRL_FIFO_RESET; | ||
| 1349 | mci_writel(host, CTRL, ctrl); | ||
| 1350 | |||
| 1351 | #ifdef CONFIG_MMC_DW_IDMAC | ||
| 1352 | ctrl = mci_readl(host, BMOD); | ||
| 1353 | ctrl |= 0x01; /* Software reset of DMA */ | ||
| 1354 | mci_writel(host, BMOD, ctrl); | ||
| 1355 | #endif | ||
| 1356 | |||
| 1357 | } | ||
| 1358 | |||
| 1359 | spin_unlock(&host->lock); | ||
| 1360 | present = dw_mci_get_cd(mmc); | ||
| 1361 | } | ||
| 1362 | |||
| 1363 | mmc_detect_change(slot->mmc, | ||
| 1364 | msecs_to_jiffies(host->pdata->detect_delay_ms)); | ||
| 1365 | } | ||
| 1366 | } | ||
| 1367 | |||
| 1368 | static int __init dw_mci_init_slot(struct dw_mci *host, unsigned int id) | ||
| 1369 | { | ||
| 1370 | struct mmc_host *mmc; | ||
| 1371 | struct dw_mci_slot *slot; | ||
| 1372 | |||
| 1373 | mmc = mmc_alloc_host(sizeof(struct dw_mci_slot), &host->pdev->dev); | ||
| 1374 | if (!mmc) | ||
| 1375 | return -ENOMEM; | ||
| 1376 | |||
| 1377 | slot = mmc_priv(mmc); | ||
| 1378 | slot->id = id; | ||
| 1379 | slot->mmc = mmc; | ||
| 1380 | slot->host = host; | ||
| 1381 | |||
| 1382 | mmc->ops = &dw_mci_ops; | ||
| 1383 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 510); | ||
| 1384 | mmc->f_max = host->bus_hz; | ||
| 1385 | |||
| 1386 | if (host->pdata->get_ocr) | ||
| 1387 | mmc->ocr_avail = host->pdata->get_ocr(id); | ||
| 1388 | else | ||
| 1389 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
| 1390 | |||
| 1391 | /* | ||
| 1392 | * Start with slot power disabled, it will be enabled when a card | ||
| 1393 | * is detected. | ||
| 1394 | */ | ||
| 1395 | if (host->pdata->setpower) | ||
| 1396 | host->pdata->setpower(id, 0); | ||
| 1397 | |||
| 1398 | mmc->caps = 0; | ||
| 1399 | if (host->pdata->get_bus_wd) | ||
| 1400 | if (host->pdata->get_bus_wd(slot->id) >= 4) | ||
| 1401 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
| 1402 | |||
| 1403 | if (host->pdata->quirks & DW_MCI_QUIRK_HIGHSPEED) | ||
| 1404 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | ||
| 1405 | |||
| 1406 | #ifdef CONFIG_MMC_DW_IDMAC | ||
| 1407 | mmc->max_segs = host->ring_size; | ||
| 1408 | mmc->max_blk_size = 65536; | ||
| 1409 | mmc->max_blk_count = host->ring_size; | ||
| 1410 | mmc->max_seg_size = 0x1000; | ||
| 1411 | mmc->max_req_size = mmc->max_seg_size * mmc->max_blk_count; | ||
| 1412 | #else | ||
| 1413 | if (host->pdata->blk_settings) { | ||
| 1414 | mmc->max_segs = host->pdata->blk_settings->max_segs; | ||
| 1415 | mmc->max_blk_size = host->pdata->blk_settings->max_blk_size; | ||
| 1416 | mmc->max_blk_count = host->pdata->blk_settings->max_blk_count; | ||
| 1417 | mmc->max_req_size = host->pdata->blk_settings->max_req_size; | ||
| 1418 | mmc->max_seg_size = host->pdata->blk_settings->max_seg_size; | ||
| 1419 | } else { | ||
| 1420 | /* Useful defaults if platform data is unset. */ | ||
| 1421 | mmc->max_segs = 64; | ||
| 1422 | mmc->max_blk_size = 65536; /* BLKSIZ is 16 bits */ | ||
| 1423 | mmc->max_blk_count = 512; | ||
| 1424 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
| 1425 | mmc->max_seg_size = mmc->max_req_size; | ||
| 1426 | } | ||
| 1427 | #endif /* CONFIG_MMC_DW_IDMAC */ | ||
| 1428 | |||
| 1429 | if (dw_mci_get_cd(mmc)) | ||
| 1430 | set_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1431 | else | ||
| 1432 | clear_bit(DW_MMC_CARD_PRESENT, &slot->flags); | ||
| 1433 | |||
| 1434 | host->slot[id] = slot; | ||
| 1435 | mmc_add_host(mmc); | ||
| 1436 | |||
| 1437 | #if defined(CONFIG_DEBUG_FS) | ||
| 1438 | dw_mci_init_debugfs(slot); | ||
| 1439 | #endif | ||
| 1440 | |||
| 1441 | /* Card initially undetected */ | ||
| 1442 | slot->last_detect_state = 0; | ||
| 1443 | |||
| 1444 | return 0; | ||
| 1445 | } | ||
| 1446 | |||
| 1447 | static void dw_mci_cleanup_slot(struct dw_mci_slot *slot, unsigned int id) | ||
| 1448 | { | ||
| 1449 | /* Shutdown detect IRQ */ | ||
| 1450 | if (slot->host->pdata->exit) | ||
| 1451 | slot->host->pdata->exit(id); | ||
| 1452 | |||
| 1453 | /* Debugfs stuff is cleaned up by mmc core */ | ||
| 1454 | mmc_remove_host(slot->mmc); | ||
| 1455 | slot->host->slot[id] = NULL; | ||
| 1456 | mmc_free_host(slot->mmc); | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | static void dw_mci_init_dma(struct dw_mci *host) | ||
| 1460 | { | ||
| 1461 | /* Alloc memory for sg translation */ | ||
| 1462 | host->sg_cpu = dma_alloc_coherent(&host->pdev->dev, PAGE_SIZE, | ||
| 1463 | &host->sg_dma, GFP_KERNEL); | ||
| 1464 | if (!host->sg_cpu) { | ||
| 1465 | dev_err(&host->pdev->dev, "%s: could not alloc DMA memory\n", | ||
| 1466 | __func__); | ||
| 1467 | goto no_dma; | ||
| 1468 | } | ||
| 1469 | |||
| 1470 | /* Determine which DMA interface to use */ | ||
| 1471 | #ifdef CONFIG_MMC_DW_IDMAC | ||
| 1472 | host->dma_ops = &dw_mci_idmac_ops; | ||
| 1473 | dev_info(&host->pdev->dev, "Using internal DMA controller.\n"); | ||
| 1474 | #endif | ||
| 1475 | |||
| 1476 | if (!host->dma_ops) | ||
| 1477 | goto no_dma; | ||
| 1478 | |||
| 1479 | if (host->dma_ops->init) { | ||
| 1480 | if (host->dma_ops->init(host)) { | ||
| 1481 | dev_err(&host->pdev->dev, "%s: Unable to initialize " | ||
| 1482 | "DMA Controller.\n", __func__); | ||
| 1483 | goto no_dma; | ||
| 1484 | } | ||
| 1485 | } else { | ||
| 1486 | dev_err(&host->pdev->dev, "DMA initialization not found.\n"); | ||
| 1487 | goto no_dma; | ||
| 1488 | } | ||
| 1489 | |||
| 1490 | host->use_dma = 1; | ||
| 1491 | return; | ||
| 1492 | |||
| 1493 | no_dma: | ||
| 1494 | dev_info(&host->pdev->dev, "Using PIO mode.\n"); | ||
| 1495 | host->use_dma = 0; | ||
| 1496 | return; | ||
| 1497 | } | ||
| 1498 | |||
| 1499 | static bool mci_wait_reset(struct device *dev, struct dw_mci *host) | ||
| 1500 | { | ||
| 1501 | unsigned long timeout = jiffies + msecs_to_jiffies(500); | ||
| 1502 | unsigned int ctrl; | ||
| 1503 | |||
| 1504 | mci_writel(host, CTRL, (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | | ||
| 1505 | SDMMC_CTRL_DMA_RESET)); | ||
| 1506 | |||
| 1507 | /* wait till resets clear */ | ||
| 1508 | do { | ||
| 1509 | ctrl = mci_readl(host, CTRL); | ||
| 1510 | if (!(ctrl & (SDMMC_CTRL_RESET | SDMMC_CTRL_FIFO_RESET | | ||
| 1511 | SDMMC_CTRL_DMA_RESET))) | ||
| 1512 | return true; | ||
| 1513 | } while (time_before(jiffies, timeout)); | ||
| 1514 | |||
| 1515 | dev_err(dev, "Timeout resetting block (ctrl %#x)\n", ctrl); | ||
| 1516 | |||
| 1517 | return false; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | static int dw_mci_probe(struct platform_device *pdev) | ||
| 1521 | { | ||
| 1522 | struct dw_mci *host; | ||
| 1523 | struct resource *regs; | ||
| 1524 | struct dw_mci_board *pdata; | ||
| 1525 | int irq, ret, i, width; | ||
| 1526 | u32 fifo_size; | ||
| 1527 | |||
| 1528 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 1529 | if (!regs) | ||
| 1530 | return -ENXIO; | ||
| 1531 | |||
| 1532 | irq = platform_get_irq(pdev, 0); | ||
| 1533 | if (irq < 0) | ||
| 1534 | return irq; | ||
| 1535 | |||
| 1536 | host = kzalloc(sizeof(struct dw_mci), GFP_KERNEL); | ||
| 1537 | if (!host) | ||
| 1538 | return -ENOMEM; | ||
| 1539 | |||
| 1540 | host->pdev = pdev; | ||
| 1541 | host->pdata = pdata = pdev->dev.platform_data; | ||
| 1542 | if (!pdata || !pdata->init) { | ||
| 1543 | dev_err(&pdev->dev, | ||
| 1544 | "Platform data must supply init function\n"); | ||
| 1545 | ret = -ENODEV; | ||
| 1546 | goto err_freehost; | ||
| 1547 | } | ||
| 1548 | |||
| 1549 | if (!pdata->select_slot && pdata->num_slots > 1) { | ||
| 1550 | dev_err(&pdev->dev, | ||
| 1551 | "Platform data must supply select_slot function\n"); | ||
| 1552 | ret = -ENODEV; | ||
| 1553 | goto err_freehost; | ||
| 1554 | } | ||
| 1555 | |||
| 1556 | if (!pdata->bus_hz) { | ||
| 1557 | dev_err(&pdev->dev, | ||
| 1558 | "Platform data must supply bus speed\n"); | ||
| 1559 | ret = -ENODEV; | ||
| 1560 | goto err_freehost; | ||
| 1561 | } | ||
| 1562 | |||
| 1563 | host->bus_hz = pdata->bus_hz; | ||
| 1564 | host->quirks = pdata->quirks; | ||
| 1565 | |||
| 1566 | spin_lock_init(&host->lock); | ||
| 1567 | INIT_LIST_HEAD(&host->queue); | ||
| 1568 | |||
| 1569 | ret = -ENOMEM; | ||
| 1570 | host->regs = ioremap(regs->start, regs->end - regs->start + 1); | ||
| 1571 | if (!host->regs) | ||
| 1572 | goto err_freehost; | ||
| 1573 | |||
| 1574 | host->dma_ops = pdata->dma_ops; | ||
| 1575 | dw_mci_init_dma(host); | ||
| 1576 | |||
| 1577 | /* | ||
| 1578 | * Get the host data width - this assumes that HCON has been set with | ||
| 1579 | * the correct values. | ||
| 1580 | */ | ||
| 1581 | i = (mci_readl(host, HCON) >> 7) & 0x7; | ||
| 1582 | if (!i) { | ||
| 1583 | host->push_data = dw_mci_push_data16; | ||
| 1584 | host->pull_data = dw_mci_pull_data16; | ||
| 1585 | width = 16; | ||
| 1586 | host->data_shift = 1; | ||
| 1587 | } else if (i == 2) { | ||
| 1588 | host->push_data = dw_mci_push_data64; | ||
| 1589 | host->pull_data = dw_mci_pull_data64; | ||
| 1590 | width = 64; | ||
| 1591 | host->data_shift = 3; | ||
| 1592 | } else { | ||
| 1593 | /* Check for a reserved value, and warn if it is */ | ||
| 1594 | WARN((i != 1), | ||
| 1595 | "HCON reports a reserved host data width!\n" | ||
| 1596 | "Defaulting to 32-bit access.\n"); | ||
| 1597 | host->push_data = dw_mci_push_data32; | ||
| 1598 | host->pull_data = dw_mci_pull_data32; | ||
| 1599 | width = 32; | ||
| 1600 | host->data_shift = 2; | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | /* Reset all blocks */ | ||
| 1604 | if (!mci_wait_reset(&pdev->dev, host)) { | ||
| 1605 | ret = -ENODEV; | ||
| 1606 | goto err_dmaunmap; | ||
| 1607 | } | ||
| 1608 | |||
| 1609 | /* Clear the interrupts for the host controller */ | ||
| 1610 | mci_writel(host, RINTSTS, 0xFFFFFFFF); | ||
| 1611 | mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ | ||
| 1612 | |||
| 1613 | /* Put in max timeout */ | ||
| 1614 | mci_writel(host, TMOUT, 0xFFFFFFFF); | ||
| 1615 | |||
| 1616 | /* | ||
| 1617 | * FIFO threshold settings RxMark = fifo_size / 2 - 1, | ||
| 1618 | * Tx Mark = fifo_size / 2 DMA Size = 8 | ||
| 1619 | */ | ||
| 1620 | fifo_size = mci_readl(host, FIFOTH); | ||
| 1621 | fifo_size = (fifo_size >> 16) & 0x7ff; | ||
| 1622 | mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) | | ||
| 1623 | ((fifo_size/2) << 0))); | ||
| 1624 | |||
| 1625 | /* disable clock to CIU */ | ||
| 1626 | mci_writel(host, CLKENA, 0); | ||
| 1627 | mci_writel(host, CLKSRC, 0); | ||
| 1628 | |||
| 1629 | tasklet_init(&host->tasklet, dw_mci_tasklet_func, (unsigned long)host); | ||
| 1630 | tasklet_init(&host->card_tasklet, | ||
| 1631 | dw_mci_tasklet_card, (unsigned long)host); | ||
| 1632 | |||
| 1633 | ret = request_irq(irq, dw_mci_interrupt, 0, "dw-mci", host); | ||
| 1634 | if (ret) | ||
| 1635 | goto err_dmaunmap; | ||
| 1636 | |||
| 1637 | platform_set_drvdata(pdev, host); | ||
| 1638 | |||
| 1639 | if (host->pdata->num_slots) | ||
| 1640 | host->num_slots = host->pdata->num_slots; | ||
| 1641 | else | ||
| 1642 | host->num_slots = ((mci_readl(host, HCON) >> 1) & 0x1F) + 1; | ||
| 1643 | |||
| 1644 | /* We need at least one slot to succeed */ | ||
| 1645 | for (i = 0; i < host->num_slots; i++) { | ||
| 1646 | ret = dw_mci_init_slot(host, i); | ||
| 1647 | if (ret) { | ||
| 1648 | ret = -ENODEV; | ||
| 1649 | goto err_init_slot; | ||
| 1650 | } | ||
| 1651 | } | ||
| 1652 | |||
| 1653 | /* | ||
| 1654 | * Enable interrupts for command done, data over, data empty, card det, | ||
| 1655 | * receive ready and error such as transmit, receive timeout, crc error | ||
| 1656 | */ | ||
| 1657 | mci_writel(host, RINTSTS, 0xFFFFFFFF); | ||
| 1658 | mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER | | ||
| 1659 | SDMMC_INT_TXDR | SDMMC_INT_RXDR | | ||
| 1660 | DW_MCI_ERROR_FLAGS | SDMMC_INT_CD); | ||
| 1661 | mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE); /* Enable mci interrupt */ | ||
| 1662 | |||
| 1663 | dev_info(&pdev->dev, "DW MMC controller at irq %d, " | ||
| 1664 | "%d bit host data width\n", irq, width); | ||
| 1665 | if (host->quirks & DW_MCI_QUIRK_IDMAC_DTO) | ||
| 1666 | dev_info(&pdev->dev, "Internal DMAC interrupt fix enabled.\n"); | ||
| 1667 | |||
| 1668 | return 0; | ||
| 1669 | |||
| 1670 | err_init_slot: | ||
| 1671 | /* De-init any initialized slots */ | ||
| 1672 | while (i > 0) { | ||
| 1673 | if (host->slot[i]) | ||
| 1674 | dw_mci_cleanup_slot(host->slot[i], i); | ||
| 1675 | i--; | ||
| 1676 | } | ||
| 1677 | free_irq(irq, host); | ||
| 1678 | |||
| 1679 | err_dmaunmap: | ||
| 1680 | if (host->use_dma && host->dma_ops->exit) | ||
| 1681 | host->dma_ops->exit(host); | ||
| 1682 | dma_free_coherent(&host->pdev->dev, PAGE_SIZE, | ||
| 1683 | host->sg_cpu, host->sg_dma); | ||
| 1684 | iounmap(host->regs); | ||
| 1685 | |||
| 1686 | err_freehost: | ||
| 1687 | kfree(host); | ||
| 1688 | return ret; | ||
| 1689 | } | ||
| 1690 | |||
| 1691 | static int __exit dw_mci_remove(struct platform_device *pdev) | ||
| 1692 | { | ||
| 1693 | struct dw_mci *host = platform_get_drvdata(pdev); | ||
| 1694 | int i; | ||
| 1695 | |||
| 1696 | mci_writel(host, RINTSTS, 0xFFFFFFFF); | ||
| 1697 | mci_writel(host, INTMASK, 0); /* disable all mmc interrupt first */ | ||
| 1698 | |||
| 1699 | platform_set_drvdata(pdev, NULL); | ||
| 1700 | |||
| 1701 | for (i = 0; i < host->num_slots; i++) { | ||
| 1702 | dev_dbg(&pdev->dev, "remove slot %d\n", i); | ||
| 1703 | if (host->slot[i]) | ||
| 1704 | dw_mci_cleanup_slot(host->slot[i], i); | ||
| 1705 | } | ||
| 1706 | |||
| 1707 | /* disable clock to CIU */ | ||
| 1708 | mci_writel(host, CLKENA, 0); | ||
| 1709 | mci_writel(host, CLKSRC, 0); | ||
| 1710 | |||
| 1711 | free_irq(platform_get_irq(pdev, 0), host); | ||
| 1712 | dma_free_coherent(&pdev->dev, PAGE_SIZE, host->sg_cpu, host->sg_dma); | ||
| 1713 | |||
| 1714 | if (host->use_dma && host->dma_ops->exit) | ||
| 1715 | host->dma_ops->exit(host); | ||
| 1716 | |||
| 1717 | iounmap(host->regs); | ||
| 1718 | |||
| 1719 | kfree(host); | ||
| 1720 | return 0; | ||
| 1721 | } | ||
| 1722 | |||
| 1723 | #ifdef CONFIG_PM | ||
| 1724 | /* | ||
| 1725 | * TODO: we should probably disable the clock to the card in the suspend path. | ||
| 1726 | */ | ||
| 1727 | static int dw_mci_suspend(struct platform_device *pdev, pm_message_t mesg) | ||
| 1728 | { | ||
| 1729 | int i, ret; | ||
| 1730 | struct dw_mci *host = platform_get_drvdata(pdev); | ||
| 1731 | |||
| 1732 | for (i = 0; i < host->num_slots; i++) { | ||
| 1733 | struct dw_mci_slot *slot = host->slot[i]; | ||
| 1734 | if (!slot) | ||
| 1735 | continue; | ||
| 1736 | ret = mmc_suspend_host(slot->mmc); | ||
| 1737 | if (ret < 0) { | ||
| 1738 | while (--i >= 0) { | ||
| 1739 | slot = host->slot[i]; | ||
| 1740 | if (slot) | ||
| 1741 | mmc_resume_host(host->slot[i]->mmc); | ||
| 1742 | } | ||
| 1743 | return ret; | ||
| 1744 | } | ||
| 1745 | } | ||
| 1746 | |||
| 1747 | return 0; | ||
| 1748 | } | ||
| 1749 | |||
| 1750 | static int dw_mci_resume(struct platform_device *pdev) | ||
| 1751 | { | ||
| 1752 | int i, ret; | ||
| 1753 | struct dw_mci *host = platform_get_drvdata(pdev); | ||
| 1754 | |||
| 1755 | for (i = 0; i < host->num_slots; i++) { | ||
| 1756 | struct dw_mci_slot *slot = host->slot[i]; | ||
| 1757 | if (!slot) | ||
| 1758 | continue; | ||
| 1759 | ret = mmc_resume_host(host->slot[i]->mmc); | ||
| 1760 | if (ret < 0) | ||
| 1761 | return ret; | ||
| 1762 | } | ||
| 1763 | |||
| 1764 | return 0; | ||
| 1765 | } | ||
| 1766 | #else | ||
| 1767 | #define dw_mci_suspend NULL | ||
| 1768 | #define dw_mci_resume NULL | ||
| 1769 | #endif /* CONFIG_PM */ | ||
| 1770 | |||
| 1771 | static struct platform_driver dw_mci_driver = { | ||
| 1772 | .remove = __exit_p(dw_mci_remove), | ||
| 1773 | .suspend = dw_mci_suspend, | ||
| 1774 | .resume = dw_mci_resume, | ||
| 1775 | .driver = { | ||
| 1776 | .name = "dw_mmc", | ||
| 1777 | }, | ||
| 1778 | }; | ||
| 1779 | |||
| 1780 | static int __init dw_mci_init(void) | ||
| 1781 | { | ||
| 1782 | return platform_driver_probe(&dw_mci_driver, dw_mci_probe); | ||
| 1783 | } | ||
| 1784 | |||
| 1785 | static void __exit dw_mci_exit(void) | ||
| 1786 | { | ||
| 1787 | platform_driver_unregister(&dw_mci_driver); | ||
| 1788 | } | ||
| 1789 | |||
| 1790 | module_init(dw_mci_init); | ||
| 1791 | module_exit(dw_mci_exit); | ||
| 1792 | |||
| 1793 | MODULE_DESCRIPTION("DW Multimedia Card Interface driver"); | ||
| 1794 | MODULE_AUTHOR("NXP Semiconductor VietNam"); | ||
| 1795 | MODULE_AUTHOR("Imagination Technologies Ltd"); | ||
| 1796 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/mmc/host/dw_mmc.h b/drivers/mmc/host/dw_mmc.h new file mode 100644 index 000000000000..5dd55a75233d --- /dev/null +++ b/drivers/mmc/host/dw_mmc.h | |||
| @@ -0,0 +1,168 @@ | |||
| 1 | /* | ||
| 2 | * Synopsys DesignWare Multimedia Card Interface driver | ||
| 3 | * (Based on NXP driver for lpc 31xx) | ||
| 4 | * | ||
| 5 | * Copyright (C) 2009 NXP Semiconductors | ||
| 6 | * Copyright (C) 2009, 2010 Imagination Technologies Ltd. | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License as published by | ||
| 10 | * the Free Software Foundation; either version 2 of the License, or | ||
| 11 | * (at your option) any later version. | ||
| 12 | */ | ||
| 13 | |||
| 14 | #ifndef _DW_MMC_H_ | ||
| 15 | #define _DW_MMC_H_ | ||
| 16 | |||
| 17 | #define SDMMC_CTRL 0x000 | ||
| 18 | #define SDMMC_PWREN 0x004 | ||
| 19 | #define SDMMC_CLKDIV 0x008 | ||
| 20 | #define SDMMC_CLKSRC 0x00c | ||
| 21 | #define SDMMC_CLKENA 0x010 | ||
| 22 | #define SDMMC_TMOUT 0x014 | ||
| 23 | #define SDMMC_CTYPE 0x018 | ||
| 24 | #define SDMMC_BLKSIZ 0x01c | ||
| 25 | #define SDMMC_BYTCNT 0x020 | ||
| 26 | #define SDMMC_INTMASK 0x024 | ||
| 27 | #define SDMMC_CMDARG 0x028 | ||
| 28 | #define SDMMC_CMD 0x02c | ||
| 29 | #define SDMMC_RESP0 0x030 | ||
| 30 | #define SDMMC_RESP1 0x034 | ||
| 31 | #define SDMMC_RESP2 0x038 | ||
| 32 | #define SDMMC_RESP3 0x03c | ||
| 33 | #define SDMMC_MINTSTS 0x040 | ||
| 34 | #define SDMMC_RINTSTS 0x044 | ||
| 35 | #define SDMMC_STATUS 0x048 | ||
| 36 | #define SDMMC_FIFOTH 0x04c | ||
| 37 | #define SDMMC_CDETECT 0x050 | ||
| 38 | #define SDMMC_WRTPRT 0x054 | ||
| 39 | #define SDMMC_GPIO 0x058 | ||
| 40 | #define SDMMC_TCBCNT 0x05c | ||
| 41 | #define SDMMC_TBBCNT 0x060 | ||
| 42 | #define SDMMC_DEBNCE 0x064 | ||
| 43 | #define SDMMC_USRID 0x068 | ||
| 44 | #define SDMMC_VERID 0x06c | ||
| 45 | #define SDMMC_HCON 0x070 | ||
| 46 | #define SDMMC_BMOD 0x080 | ||
| 47 | #define SDMMC_PLDMND 0x084 | ||
| 48 | #define SDMMC_DBADDR 0x088 | ||
| 49 | #define SDMMC_IDSTS 0x08c | ||
| 50 | #define SDMMC_IDINTEN 0x090 | ||
| 51 | #define SDMMC_DSCADDR 0x094 | ||
| 52 | #define SDMMC_BUFADDR 0x098 | ||
| 53 | #define SDMMC_DATA 0x100 | ||
| 54 | #define SDMMC_DATA_ADR 0x100 | ||
| 55 | |||
| 56 | /* shift bit field */ | ||
| 57 | #define _SBF(f, v) ((v) << (f)) | ||
| 58 | |||
| 59 | /* Control register defines */ | ||
| 60 | #define SDMMC_CTRL_USE_IDMAC BIT(25) | ||
| 61 | #define SDMMC_CTRL_CEATA_INT_EN BIT(11) | ||
| 62 | #define SDMMC_CTRL_SEND_AS_CCSD BIT(10) | ||
| 63 | #define SDMMC_CTRL_SEND_CCSD BIT(9) | ||
| 64 | #define SDMMC_CTRL_ABRT_READ_DATA BIT(8) | ||
| 65 | #define SDMMC_CTRL_SEND_IRQ_RESP BIT(7) | ||
| 66 | #define SDMMC_CTRL_READ_WAIT BIT(6) | ||
| 67 | #define SDMMC_CTRL_DMA_ENABLE BIT(5) | ||
| 68 | #define SDMMC_CTRL_INT_ENABLE BIT(4) | ||
| 69 | #define SDMMC_CTRL_DMA_RESET BIT(2) | ||
| 70 | #define SDMMC_CTRL_FIFO_RESET BIT(1) | ||
| 71 | #define SDMMC_CTRL_RESET BIT(0) | ||
| 72 | /* Clock Enable register defines */ | ||
| 73 | #define SDMMC_CLKEN_LOW_PWR BIT(16) | ||
| 74 | #define SDMMC_CLKEN_ENABLE BIT(0) | ||
| 75 | /* time-out register defines */ | ||
| 76 | #define SDMMC_TMOUT_DATA(n) _SBF(8, (n)) | ||
| 77 | #define SDMMC_TMOUT_DATA_MSK 0xFFFFFF00 | ||
| 78 | #define SDMMC_TMOUT_RESP(n) ((n) & 0xFF) | ||
| 79 | #define SDMMC_TMOUT_RESP_MSK 0xFF | ||
| 80 | /* card-type register defines */ | ||
| 81 | #define SDMMC_CTYPE_8BIT BIT(16) | ||
| 82 | #define SDMMC_CTYPE_4BIT BIT(0) | ||
| 83 | #define SDMMC_CTYPE_1BIT 0 | ||
| 84 | /* Interrupt status & mask register defines */ | ||
| 85 | #define SDMMC_INT_SDIO BIT(16) | ||
| 86 | #define SDMMC_INT_EBE BIT(15) | ||
| 87 | #define SDMMC_INT_ACD BIT(14) | ||
| 88 | #define SDMMC_INT_SBE BIT(13) | ||
| 89 | #define SDMMC_INT_HLE BIT(12) | ||
| 90 | #define SDMMC_INT_FRUN BIT(11) | ||
| 91 | #define SDMMC_INT_HTO BIT(10) | ||
| 92 | #define SDMMC_INT_DTO BIT(9) | ||
| 93 | #define SDMMC_INT_RTO BIT(8) | ||
| 94 | #define SDMMC_INT_DCRC BIT(7) | ||
| 95 | #define SDMMC_INT_RCRC BIT(6) | ||
| 96 | #define SDMMC_INT_RXDR BIT(5) | ||
| 97 | #define SDMMC_INT_TXDR BIT(4) | ||
| 98 | #define SDMMC_INT_DATA_OVER BIT(3) | ||
| 99 | #define SDMMC_INT_CMD_DONE BIT(2) | ||
| 100 | #define SDMMC_INT_RESP_ERR BIT(1) | ||
| 101 | #define SDMMC_INT_CD BIT(0) | ||
| 102 | #define SDMMC_INT_ERROR 0xbfc2 | ||
| 103 | /* Command register defines */ | ||
| 104 | #define SDMMC_CMD_START BIT(31) | ||
| 105 | #define SDMMC_CMD_CCS_EXP BIT(23) | ||
| 106 | #define SDMMC_CMD_CEATA_RD BIT(22) | ||
| 107 | #define SDMMC_CMD_UPD_CLK BIT(21) | ||
| 108 | #define SDMMC_CMD_INIT BIT(15) | ||
| 109 | #define SDMMC_CMD_STOP BIT(14) | ||
| 110 | #define SDMMC_CMD_PRV_DAT_WAIT BIT(13) | ||
| 111 | #define SDMMC_CMD_SEND_STOP BIT(12) | ||
| 112 | #define SDMMC_CMD_STRM_MODE BIT(11) | ||
| 113 | #define SDMMC_CMD_DAT_WR BIT(10) | ||
| 114 | #define SDMMC_CMD_DAT_EXP BIT(9) | ||
| 115 | #define SDMMC_CMD_RESP_CRC BIT(8) | ||
| 116 | #define SDMMC_CMD_RESP_LONG BIT(7) | ||
| 117 | #define SDMMC_CMD_RESP_EXP BIT(6) | ||
| 118 | #define SDMMC_CMD_INDX(n) ((n) & 0x1F) | ||
| 119 | /* Status register defines */ | ||
| 120 | #define SDMMC_GET_FCNT(x) (((x)>>17) & 0x1FF) | ||
| 121 | #define SDMMC_FIFO_SZ 32 | ||
| 122 | /* Internal DMAC interrupt defines */ | ||
| 123 | #define SDMMC_IDMAC_INT_AI BIT(9) | ||
| 124 | #define SDMMC_IDMAC_INT_NI BIT(8) | ||
| 125 | #define SDMMC_IDMAC_INT_CES BIT(5) | ||
| 126 | #define SDMMC_IDMAC_INT_DU BIT(4) | ||
| 127 | #define SDMMC_IDMAC_INT_FBE BIT(2) | ||
| 128 | #define SDMMC_IDMAC_INT_RI BIT(1) | ||
| 129 | #define SDMMC_IDMAC_INT_TI BIT(0) | ||
| 130 | /* Internal DMAC bus mode bits */ | ||
| 131 | #define SDMMC_IDMAC_ENABLE BIT(7) | ||
| 132 | #define SDMMC_IDMAC_FB BIT(1) | ||
| 133 | #define SDMMC_IDMAC_SWRESET BIT(0) | ||
| 134 | |||
| 135 | /* Register access macros */ | ||
| 136 | #define mci_readl(dev, reg) \ | ||
| 137 | __raw_readl(dev->regs + SDMMC_##reg) | ||
| 138 | #define mci_writel(dev, reg, value) \ | ||
| 139 | __raw_writel((value), dev->regs + SDMMC_##reg) | ||
| 140 | |||
| 141 | /* 16-bit FIFO access macros */ | ||
| 142 | #define mci_readw(dev, reg) \ | ||
| 143 | __raw_readw(dev->regs + SDMMC_##reg) | ||
| 144 | #define mci_writew(dev, reg, value) \ | ||
| 145 | __raw_writew((value), dev->regs + SDMMC_##reg) | ||
| 146 | |||
| 147 | /* 64-bit FIFO access macros */ | ||
| 148 | #ifdef readq | ||
| 149 | #define mci_readq(dev, reg) \ | ||
| 150 | __raw_readq(dev->regs + SDMMC_##reg) | ||
| 151 | #define mci_writeq(dev, reg, value) \ | ||
| 152 | __raw_writeq((value), dev->regs + SDMMC_##reg) | ||
| 153 | #else | ||
| 154 | /* | ||
| 155 | * Dummy readq implementation for architectures that don't define it. | ||
| 156 | * | ||
| 157 | * We would assume that none of these architectures would configure | ||
| 158 | * the IP block with a 64bit FIFO width, so this code will never be | ||
| 159 | * executed on those machines. Defining these macros here keeps the | ||
| 160 | * rest of the code free from ifdefs. | ||
| 161 | */ | ||
| 162 | #define mci_readq(dev, reg) \ | ||
| 163 | (*(volatile u64 __force *)(dev->regs + SDMMC_##reg)) | ||
| 164 | #define mci_writeq(dev, reg, value) \ | ||
| 165 | (*(volatile u64 __force *)(dev->regs + SDMMC_##reg) = value) | ||
| 166 | #endif | ||
| 167 | |||
| 168 | #endif /* _DW_MMC_H_ */ | ||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index bdd2cbb87cba..4428594261c5 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/clk.h> | 31 | #include <linux/clk.h> |
| 32 | #include <linux/io.h> | 32 | #include <linux/io.h> |
| 33 | #include <linux/gpio.h> | 33 | #include <linux/gpio.h> |
| 34 | #include <linux/regulator/consumer.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
| 36 | #include <asm/irq.h> | 37 | #include <asm/irq.h> |
| @@ -141,10 +142,49 @@ struct mxcmci_host { | |||
| 141 | 142 | ||
| 142 | struct work_struct datawork; | 143 | struct work_struct datawork; |
| 143 | spinlock_t lock; | 144 | spinlock_t lock; |
| 145 | |||
| 146 | struct regulator *vcc; | ||
| 144 | }; | 147 | }; |
| 145 | 148 | ||
| 146 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | 149 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); |
| 147 | 150 | ||
| 151 | static inline void mxcmci_init_ocr(struct mxcmci_host *host) | ||
| 152 | { | ||
| 153 | host->vcc = regulator_get(mmc_dev(host->mmc), "vmmc"); | ||
| 154 | |||
| 155 | if (IS_ERR(host->vcc)) { | ||
| 156 | host->vcc = NULL; | ||
| 157 | } else { | ||
| 158 | host->mmc->ocr_avail = mmc_regulator_get_ocrmask(host->vcc); | ||
| 159 | if (host->pdata && host->pdata->ocr_avail) | ||
| 160 | dev_warn(mmc_dev(host->mmc), | ||
| 161 | "pdata->ocr_avail will not be used\n"); | ||
| 162 | } | ||
| 163 | |||
| 164 | if (host->vcc == NULL) { | ||
| 165 | /* fall-back to platform data */ | ||
| 166 | if (host->pdata && host->pdata->ocr_avail) | ||
| 167 | host->mmc->ocr_avail = host->pdata->ocr_avail; | ||
| 168 | else | ||
| 169 | host->mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | static inline void mxcmci_set_power(struct mxcmci_host *host, | ||
| 174 | unsigned char power_mode, | ||
| 175 | unsigned int vdd) | ||
| 176 | { | ||
| 177 | if (host->vcc) { | ||
| 178 | if (power_mode == MMC_POWER_UP) | ||
| 179 | mmc_regulator_set_ocr(host->mmc, host->vcc, vdd); | ||
| 180 | else if (power_mode == MMC_POWER_OFF) | ||
| 181 | mmc_regulator_set_ocr(host->mmc, host->vcc, 0); | ||
| 182 | } | ||
| 183 | |||
| 184 | if (host->pdata && host->pdata->setpower) | ||
| 185 | host->pdata->setpower(mmc_dev(host->mmc), vdd); | ||
| 186 | } | ||
| 187 | |||
| 148 | static inline int mxcmci_use_dma(struct mxcmci_host *host) | 188 | static inline int mxcmci_use_dma(struct mxcmci_host *host) |
| 149 | { | 189 | { |
| 150 | return host->do_dma; | 190 | return host->do_dma; |
| @@ -680,9 +720,9 @@ static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 680 | host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; | 720 | host->cmdat &= ~CMD_DAT_CONT_BUS_WIDTH_4; |
| 681 | 721 | ||
| 682 | if (host->power_mode != ios->power_mode) { | 722 | if (host->power_mode != ios->power_mode) { |
| 683 | if (host->pdata && host->pdata->setpower) | 723 | mxcmci_set_power(host, ios->power_mode, ios->vdd); |
| 684 | host->pdata->setpower(mmc_dev(mmc), ios->vdd); | ||
| 685 | host->power_mode = ios->power_mode; | 724 | host->power_mode = ios->power_mode; |
| 725 | |||
| 686 | if (ios->power_mode == MMC_POWER_ON) | 726 | if (ios->power_mode == MMC_POWER_ON) |
| 687 | host->cmdat |= CMD_DAT_CONT_INIT; | 727 | host->cmdat |= CMD_DAT_CONT_INIT; |
| 688 | } | 728 | } |
| @@ -807,10 +847,7 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 807 | host->pdata = pdev->dev.platform_data; | 847 | host->pdata = pdev->dev.platform_data; |
| 808 | spin_lock_init(&host->lock); | 848 | spin_lock_init(&host->lock); |
| 809 | 849 | ||
| 810 | if (host->pdata && host->pdata->ocr_avail) | 850 | mxcmci_init_ocr(host); |
| 811 | mmc->ocr_avail = host->pdata->ocr_avail; | ||
| 812 | else | ||
| 813 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
| 814 | 851 | ||
| 815 | if (host->pdata && host->pdata->dat3_card_detect) | 852 | if (host->pdata && host->pdata->dat3_card_detect) |
| 816 | host->default_irq_mask = | 853 | host->default_irq_mask = |
| @@ -915,6 +952,9 @@ static int mxcmci_remove(struct platform_device *pdev) | |||
| 915 | 952 | ||
| 916 | mmc_remove_host(mmc); | 953 | mmc_remove_host(mmc); |
| 917 | 954 | ||
| 955 | if (host->vcc) | ||
| 956 | regulator_put(host->vcc); | ||
| 957 | |||
| 918 | if (host->pdata && host->pdata->exit) | 958 | if (host->pdata && host->pdata->exit) |
| 919 | host->pdata->exit(&pdev->dev, mmc); | 959 | host->pdata->exit(&pdev->dev, mmc); |
| 920 | 960 | ||
| @@ -927,7 +967,6 @@ static int mxcmci_remove(struct platform_device *pdev) | |||
| 927 | clk_put(host->clk); | 967 | clk_put(host->clk); |
| 928 | 968 | ||
| 929 | release_mem_region(host->res->start, resource_size(host->res)); | 969 | release_mem_region(host->res->start, resource_size(host->res)); |
| 930 | release_resource(host->res); | ||
| 931 | 970 | ||
| 932 | mmc_free_host(mmc); | 971 | mmc_free_host(mmc); |
| 933 | 972 | ||
diff --git a/drivers/mmc/host/sdhci-dove.c b/drivers/mmc/host/sdhci-dove.c new file mode 100644 index 000000000000..2aeef4ffed8c --- /dev/null +++ b/drivers/mmc/host/sdhci-dove.c | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* | ||
| 2 | * sdhci-dove.c Support for SDHCI on Marvell's Dove SoC | ||
| 3 | * | ||
| 4 | * Author: Saeed Bishara <saeed@marvell.com> | ||
| 5 | * Mike Rapoport <mike@compulab.co.il> | ||
| 6 | * Based on sdhci-cns3xxx.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | * This program is distributed in the hope that it will be useful, | ||
| 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | * GNU General Public License for more details. | ||
| 16 | * | ||
| 17 | * You should have received a copy of the GNU General Public License | ||
| 18 | * along with this program; if not, write to the Free Software | ||
| 19 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/io.h> | ||
| 23 | #include <linux/mmc/host.h> | ||
| 24 | |||
| 25 | #include "sdhci.h" | ||
| 26 | #include "sdhci-pltfm.h" | ||
| 27 | |||
| 28 | static u16 sdhci_dove_readw(struct sdhci_host *host, int reg) | ||
| 29 | { | ||
| 30 | u16 ret; | ||
| 31 | |||
| 32 | switch (reg) { | ||
| 33 | case SDHCI_HOST_VERSION: | ||
| 34 | case SDHCI_SLOT_INT_STATUS: | ||
| 35 | /* those registers don't exist */ | ||
| 36 | return 0; | ||
| 37 | default: | ||
| 38 | ret = readw(host->ioaddr + reg); | ||
| 39 | } | ||
| 40 | return ret; | ||
| 41 | } | ||
| 42 | |||
| 43 | static u32 sdhci_dove_readl(struct sdhci_host *host, int reg) | ||
| 44 | { | ||
| 45 | u32 ret; | ||
| 46 | |||
| 47 | switch (reg) { | ||
| 48 | case SDHCI_CAPABILITIES: | ||
| 49 | ret = readl(host->ioaddr + reg); | ||
| 50 | /* Mask the support for 3.0V */ | ||
| 51 | ret &= ~SDHCI_CAN_VDD_300; | ||
| 52 | break; | ||
| 53 | default: | ||
| 54 | ret = readl(host->ioaddr + reg); | ||
| 55 | } | ||
| 56 | return ret; | ||
| 57 | } | ||
| 58 | |||
| 59 | static struct sdhci_ops sdhci_dove_ops = { | ||
| 60 | .read_w = sdhci_dove_readw, | ||
| 61 | .read_l = sdhci_dove_readl, | ||
| 62 | }; | ||
| 63 | |||
| 64 | struct sdhci_pltfm_data sdhci_dove_pdata = { | ||
| 65 | .ops = &sdhci_dove_ops, | ||
| 66 | .quirks = SDHCI_QUIRK_NO_SIMULT_VDD_AND_POWER | | ||
| 67 | SDHCI_QUIRK_NO_BUSY_IRQ | | ||
| 68 | SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | ||
| 69 | SDHCI_QUIRK_FORCE_DMA, | ||
| 70 | }; | ||
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 | }, |
diff --git a/drivers/mmc/host/sdhci-pltfm.c b/drivers/mmc/host/sdhci-pltfm.c index 0502f89f662b..dbab0407f4b6 100644 --- a/drivers/mmc/host/sdhci-pltfm.c +++ b/drivers/mmc/host/sdhci-pltfm.c | |||
| @@ -170,6 +170,12 @@ static const struct platform_device_id sdhci_pltfm_ids[] = { | |||
| 170 | #ifdef CONFIG_MMC_SDHCI_ESDHC_IMX | 170 | #ifdef CONFIG_MMC_SDHCI_ESDHC_IMX |
| 171 | { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata }, | 171 | { "sdhci-esdhc-imx", (kernel_ulong_t)&sdhci_esdhc_imx_pdata }, |
| 172 | #endif | 172 | #endif |
| 173 | #ifdef CONFIG_MMC_SDHCI_DOVE | ||
| 174 | { "sdhci-dove", (kernel_ulong_t)&sdhci_dove_pdata }, | ||
| 175 | #endif | ||
| 176 | #ifdef CONFIG_MMC_SDHCI_TEGRA | ||
| 177 | { "sdhci-tegra", (kernel_ulong_t)&sdhci_tegra_pdata }, | ||
| 178 | #endif | ||
| 173 | { }, | 179 | { }, |
| 174 | }; | 180 | }; |
| 175 | MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids); | 181 | MODULE_DEVICE_TABLE(platform, sdhci_pltfm_ids); |
diff --git a/drivers/mmc/host/sdhci-pltfm.h b/drivers/mmc/host/sdhci-pltfm.h index c1bfe48af56a..ea2e44d9be5e 100644 --- a/drivers/mmc/host/sdhci-pltfm.h +++ b/drivers/mmc/host/sdhci-pltfm.h | |||
| @@ -22,5 +22,7 @@ struct sdhci_pltfm_host { | |||
| 22 | 22 | ||
| 23 | extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata; | 23 | extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata; |
| 24 | extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata; | 24 | extern struct sdhci_pltfm_data sdhci_esdhc_imx_pdata; |
| 25 | extern struct sdhci_pltfm_data sdhci_dove_pdata; | ||
| 26 | extern struct sdhci_pltfm_data sdhci_tegra_pdata; | ||
| 25 | 27 | ||
| 26 | #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ | 28 | #endif /* _DRIVERS_MMC_SDHCI_PLTFM_H */ |
diff --git a/drivers/mmc/host/sdhci-s3c.c b/drivers/mmc/host/sdhci-s3c.c index aacb862ecc8a..17203586305c 100644 --- a/drivers/mmc/host/sdhci-s3c.c +++ b/drivers/mmc/host/sdhci-s3c.c | |||
| @@ -130,6 +130,15 @@ static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost, | |||
| 130 | if (!clksrc) | 130 | if (!clksrc) |
| 131 | return UINT_MAX; | 131 | return UINT_MAX; |
| 132 | 132 | ||
| 133 | /* | ||
| 134 | * Clock divider's step is different as 1 from that of host controller | ||
| 135 | * when 'clk_type' is S3C_SDHCI_CLK_DIV_EXTERNAL. | ||
| 136 | */ | ||
| 137 | if (ourhost->pdata->clk_type) { | ||
| 138 | rate = clk_round_rate(clksrc, wanted); | ||
| 139 | return wanted - rate; | ||
| 140 | } | ||
| 141 | |||
| 133 | rate = clk_get_rate(clksrc); | 142 | rate = clk_get_rate(clksrc); |
| 134 | 143 | ||
| 135 | for (div = 1; div < 256; div *= 2) { | 144 | for (div = 1; div < 256; div *= 2) { |
| @@ -232,6 +241,42 @@ static unsigned int sdhci_s3c_get_min_clock(struct sdhci_host *host) | |||
| 232 | return min; | 241 | return min; |
| 233 | } | 242 | } |
| 234 | 243 | ||
| 244 | /* sdhci_cmu_get_max_clk - callback to get maximum clock frequency.*/ | ||
| 245 | static unsigned int sdhci_cmu_get_max_clock(struct sdhci_host *host) | ||
| 246 | { | ||
| 247 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 248 | |||
| 249 | return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], UINT_MAX); | ||
| 250 | } | ||
| 251 | |||
| 252 | /* sdhci_cmu_get_min_clock - callback to get minimal supported clock value. */ | ||
| 253 | static unsigned int sdhci_cmu_get_min_clock(struct sdhci_host *host) | ||
| 254 | { | ||
| 255 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 256 | |||
| 257 | /* | ||
| 258 | * initial clock can be in the frequency range of | ||
| 259 | * 100KHz-400KHz, so we set it as max value. | ||
| 260 | */ | ||
| 261 | return clk_round_rate(ourhost->clk_bus[ourhost->cur_clk], 400000); | ||
| 262 | } | ||
| 263 | |||
| 264 | /* sdhci_cmu_set_clock - callback on clock change.*/ | ||
| 265 | static void sdhci_cmu_set_clock(struct sdhci_host *host, unsigned int clock) | ||
| 266 | { | ||
| 267 | struct sdhci_s3c *ourhost = to_s3c(host); | ||
| 268 | |||
| 269 | /* don't bother if the clock is going off */ | ||
| 270 | if (clock == 0) | ||
| 271 | return; | ||
| 272 | |||
| 273 | sdhci_s3c_set_clock(host, clock); | ||
| 274 | |||
| 275 | clk_set_rate(ourhost->clk_bus[ourhost->cur_clk], clock); | ||
| 276 | |||
| 277 | host->clock = clock; | ||
| 278 | } | ||
| 279 | |||
| 235 | static struct sdhci_ops sdhci_s3c_ops = { | 280 | static struct sdhci_ops sdhci_s3c_ops = { |
| 236 | .get_max_clock = sdhci_s3c_get_max_clk, | 281 | .get_max_clock = sdhci_s3c_get_max_clk, |
| 237 | .set_clock = sdhci_s3c_set_clock, | 282 | .set_clock = sdhci_s3c_set_clock, |
| @@ -361,6 +406,13 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 361 | 406 | ||
| 362 | clks++; | 407 | clks++; |
| 363 | sc->clk_bus[ptr] = clk; | 408 | sc->clk_bus[ptr] = clk; |
| 409 | |||
| 410 | /* | ||
| 411 | * save current clock index to know which clock bus | ||
| 412 | * is used later in overriding functions. | ||
| 413 | */ | ||
| 414 | sc->cur_clk = ptr; | ||
| 415 | |||
| 364 | clk_enable(clk); | 416 | clk_enable(clk); |
| 365 | 417 | ||
| 366 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", | 418 | dev_info(dev, "clock source %d: %s (%ld Hz)\n", |
| @@ -427,6 +479,20 @@ static int __devinit sdhci_s3c_probe(struct platform_device *pdev) | |||
| 427 | /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ | 479 | /* HSMMC on Samsung SoCs uses SDCLK as timeout clock */ |
| 428 | host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; | 480 | host->quirks |= SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK; |
| 429 | 481 | ||
| 482 | /* | ||
| 483 | * If controller does not have internal clock divider, | ||
| 484 | * we can use overriding functions instead of default. | ||
| 485 | */ | ||
| 486 | if (pdata->clk_type) { | ||
| 487 | sdhci_s3c_ops.set_clock = sdhci_cmu_set_clock; | ||
| 488 | sdhci_s3c_ops.get_min_clock = sdhci_cmu_get_min_clock; | ||
| 489 | sdhci_s3c_ops.get_max_clock = sdhci_cmu_get_max_clock; | ||
| 490 | } | ||
| 491 | |||
| 492 | /* It supports additional host capabilities if needed */ | ||
| 493 | if (pdata->host_caps) | ||
| 494 | host->mmc->caps |= pdata->host_caps; | ||
| 495 | |||
| 430 | ret = sdhci_add_host(host); | 496 | ret = sdhci_add_host(host); |
| 431 | if (ret) { | 497 | if (ret) { |
| 432 | dev_err(dev, "sdhci_add_host() failed\n"); | 498 | dev_err(dev, "sdhci_add_host() failed\n"); |
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c new file mode 100644 index 000000000000..4823ee94a63f --- /dev/null +++ b/drivers/mmc/host/sdhci-tegra.c | |||
| @@ -0,0 +1,257 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010 Google, Inc. | ||
| 3 | * | ||
| 4 | * This software is licensed under the terms of the GNU General Public | ||
| 5 | * License version 2, as published by the Free Software Foundation, and | ||
| 6 | * may be copied, distributed, and modified under those terms. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/err.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/clk.h> | ||
| 19 | #include <linux/io.h> | ||
| 20 | #include <linux/gpio.h> | ||
| 21 | #include <linux/mmc/card.h> | ||
| 22 | #include <linux/mmc/host.h> | ||
| 23 | |||
| 24 | #include <mach/gpio.h> | ||
| 25 | #include <mach/sdhci.h> | ||
| 26 | |||
| 27 | #include "sdhci.h" | ||
| 28 | #include "sdhci-pltfm.h" | ||
| 29 | |||
| 30 | static u32 tegra_sdhci_readl(struct sdhci_host *host, int reg) | ||
| 31 | { | ||
| 32 | u32 val; | ||
| 33 | |||
| 34 | if (unlikely(reg == SDHCI_PRESENT_STATE)) { | ||
| 35 | /* Use wp_gpio here instead? */ | ||
| 36 | val = readl(host->ioaddr + reg); | ||
| 37 | return val | SDHCI_WRITE_PROTECT; | ||
| 38 | } | ||
| 39 | |||
| 40 | return readl(host->ioaddr + reg); | ||
| 41 | } | ||
| 42 | |||
| 43 | static u16 tegra_sdhci_readw(struct sdhci_host *host, int reg) | ||
| 44 | { | ||
| 45 | if (unlikely(reg == SDHCI_HOST_VERSION)) { | ||
| 46 | /* Erratum: Version register is invalid in HW. */ | ||
| 47 | return SDHCI_SPEC_200; | ||
| 48 | } | ||
| 49 | |||
| 50 | return readw(host->ioaddr + reg); | ||
| 51 | } | ||
| 52 | |||
| 53 | static void tegra_sdhci_writel(struct sdhci_host *host, u32 val, int reg) | ||
| 54 | { | ||
| 55 | /* Seems like we're getting spurious timeout and crc errors, so | ||
| 56 | * disable signalling of them. In case of real errors software | ||
| 57 | * timers should take care of eventually detecting them. | ||
| 58 | */ | ||
| 59 | if (unlikely(reg == SDHCI_SIGNAL_ENABLE)) | ||
| 60 | val &= ~(SDHCI_INT_TIMEOUT|SDHCI_INT_CRC); | ||
| 61 | |||
| 62 | writel(val, host->ioaddr + reg); | ||
| 63 | |||
| 64 | if (unlikely(reg == SDHCI_INT_ENABLE)) { | ||
| 65 | /* Erratum: Must enable block gap interrupt detection */ | ||
| 66 | u8 gap_ctrl = readb(host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); | ||
| 67 | if (val & SDHCI_INT_CARD_INT) | ||
| 68 | gap_ctrl |= 0x8; | ||
| 69 | else | ||
| 70 | gap_ctrl &= ~0x8; | ||
| 71 | writeb(gap_ctrl, host->ioaddr + SDHCI_BLOCK_GAP_CONTROL); | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | static unsigned int tegra_sdhci_get_ro(struct sdhci_host *sdhci) | ||
| 76 | { | ||
| 77 | struct platform_device *pdev = to_platform_device(mmc_dev(sdhci->mmc)); | ||
| 78 | struct tegra_sdhci_platform_data *plat; | ||
| 79 | |||
| 80 | plat = pdev->dev.platform_data; | ||
| 81 | |||
| 82 | if (!gpio_is_valid(plat->wp_gpio)) | ||
| 83 | return -1; | ||
| 84 | |||
| 85 | return gpio_get_value(plat->wp_gpio); | ||
| 86 | } | ||
| 87 | |||
| 88 | static irqreturn_t carddetect_irq(int irq, void *data) | ||
| 89 | { | ||
| 90 | struct sdhci_host *sdhost = (struct sdhci_host *)data; | ||
| 91 | |||
| 92 | tasklet_schedule(&sdhost->card_tasklet); | ||
| 93 | return IRQ_HANDLED; | ||
| 94 | }; | ||
| 95 | |||
| 96 | static int tegra_sdhci_8bit(struct sdhci_host *host, int bus_width) | ||
| 97 | { | ||
| 98 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); | ||
| 99 | struct tegra_sdhci_platform_data *plat; | ||
| 100 | u32 ctrl; | ||
| 101 | |||
| 102 | plat = pdev->dev.platform_data; | ||
| 103 | |||
| 104 | ctrl = sdhci_readb(host, SDHCI_HOST_CONTROL); | ||
| 105 | if (plat->is_8bit && bus_width == MMC_BUS_WIDTH_8) { | ||
| 106 | ctrl &= ~SDHCI_CTRL_4BITBUS; | ||
| 107 | ctrl |= SDHCI_CTRL_8BITBUS; | ||
| 108 | } else { | ||
| 109 | ctrl &= ~SDHCI_CTRL_8BITBUS; | ||
| 110 | if (bus_width == MMC_BUS_WIDTH_4) | ||
| 111 | ctrl |= SDHCI_CTRL_4BITBUS; | ||
| 112 | else | ||
| 113 | ctrl &= ~SDHCI_CTRL_4BITBUS; | ||
| 114 | } | ||
| 115 | sdhci_writeb(host, ctrl, SDHCI_HOST_CONTROL); | ||
| 116 | return 0; | ||
| 117 | } | ||
| 118 | |||
| 119 | |||
| 120 | static int tegra_sdhci_pltfm_init(struct sdhci_host *host, | ||
| 121 | struct sdhci_pltfm_data *pdata) | ||
| 122 | { | ||
| 123 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 124 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); | ||
| 125 | struct tegra_sdhci_platform_data *plat; | ||
| 126 | struct clk *clk; | ||
| 127 | int rc; | ||
| 128 | |||
| 129 | plat = pdev->dev.platform_data; | ||
| 130 | if (plat == NULL) { | ||
| 131 | dev_err(mmc_dev(host->mmc), "missing platform data\n"); | ||
| 132 | return -ENXIO; | ||
| 133 | } | ||
| 134 | |||
| 135 | if (gpio_is_valid(plat->power_gpio)) { | ||
| 136 | rc = gpio_request(plat->power_gpio, "sdhci_power"); | ||
| 137 | if (rc) { | ||
| 138 | dev_err(mmc_dev(host->mmc), | ||
| 139 | "failed to allocate power gpio\n"); | ||
| 140 | goto out; | ||
| 141 | } | ||
| 142 | tegra_gpio_enable(plat->power_gpio); | ||
| 143 | gpio_direction_output(plat->power_gpio, 1); | ||
| 144 | } | ||
| 145 | |||
| 146 | if (gpio_is_valid(plat->cd_gpio)) { | ||
| 147 | rc = gpio_request(plat->cd_gpio, "sdhci_cd"); | ||
| 148 | if (rc) { | ||
| 149 | dev_err(mmc_dev(host->mmc), | ||
| 150 | "failed to allocate cd gpio\n"); | ||
| 151 | goto out_power; | ||
| 152 | } | ||
| 153 | tegra_gpio_enable(plat->cd_gpio); | ||
| 154 | gpio_direction_input(plat->cd_gpio); | ||
| 155 | |||
| 156 | rc = request_irq(gpio_to_irq(plat->cd_gpio), carddetect_irq, | ||
| 157 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
| 158 | mmc_hostname(host->mmc), host); | ||
| 159 | |||
| 160 | if (rc) { | ||
| 161 | dev_err(mmc_dev(host->mmc), "request irq error\n"); | ||
| 162 | goto out_cd; | ||
| 163 | } | ||
| 164 | |||
| 165 | } | ||
| 166 | |||
| 167 | if (gpio_is_valid(plat->wp_gpio)) { | ||
| 168 | rc = gpio_request(plat->wp_gpio, "sdhci_wp"); | ||
| 169 | if (rc) { | ||
| 170 | dev_err(mmc_dev(host->mmc), | ||
| 171 | "failed to allocate wp gpio\n"); | ||
| 172 | goto out_cd; | ||
| 173 | } | ||
| 174 | tegra_gpio_enable(plat->wp_gpio); | ||
| 175 | gpio_direction_input(plat->wp_gpio); | ||
| 176 | } | ||
| 177 | |||
| 178 | clk = clk_get(mmc_dev(host->mmc), NULL); | ||
| 179 | if (IS_ERR(clk)) { | ||
| 180 | dev_err(mmc_dev(host->mmc), "clk err\n"); | ||
| 181 | rc = PTR_ERR(clk); | ||
| 182 | goto out_wp; | ||
| 183 | } | ||
| 184 | clk_enable(clk); | ||
| 185 | pltfm_host->clk = clk; | ||
| 186 | |||
| 187 | if (plat->is_8bit) | ||
| 188 | host->mmc->caps |= MMC_CAP_8_BIT_DATA; | ||
| 189 | |||
| 190 | return 0; | ||
| 191 | |||
| 192 | out_wp: | ||
| 193 | if (gpio_is_valid(plat->wp_gpio)) { | ||
| 194 | tegra_gpio_disable(plat->wp_gpio); | ||
| 195 | gpio_free(plat->wp_gpio); | ||
| 196 | } | ||
| 197 | |||
| 198 | out_cd: | ||
| 199 | if (gpio_is_valid(plat->cd_gpio)) { | ||
| 200 | tegra_gpio_disable(plat->cd_gpio); | ||
| 201 | gpio_free(plat->cd_gpio); | ||
| 202 | } | ||
| 203 | |||
| 204 | out_power: | ||
| 205 | if (gpio_is_valid(plat->power_gpio)) { | ||
| 206 | tegra_gpio_disable(plat->power_gpio); | ||
| 207 | gpio_free(plat->power_gpio); | ||
| 208 | } | ||
| 209 | |||
| 210 | out: | ||
| 211 | return rc; | ||
| 212 | } | ||
| 213 | |||
| 214 | static void tegra_sdhci_pltfm_exit(struct sdhci_host *host) | ||
| 215 | { | ||
| 216 | struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); | ||
| 217 | struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc)); | ||
| 218 | struct tegra_sdhci_platform_data *plat; | ||
| 219 | |||
| 220 | plat = pdev->dev.platform_data; | ||
| 221 | |||
| 222 | if (gpio_is_valid(plat->wp_gpio)) { | ||
| 223 | tegra_gpio_disable(plat->wp_gpio); | ||
| 224 | gpio_free(plat->wp_gpio); | ||
| 225 | } | ||
| 226 | |||
| 227 | if (gpio_is_valid(plat->cd_gpio)) { | ||
| 228 | tegra_gpio_disable(plat->cd_gpio); | ||
| 229 | gpio_free(plat->cd_gpio); | ||
| 230 | } | ||
| 231 | |||
| 232 | if (gpio_is_valid(plat->power_gpio)) { | ||
| 233 | tegra_gpio_disable(plat->power_gpio); | ||
| 234 | gpio_free(plat->power_gpio); | ||
| 235 | } | ||
| 236 | |||
| 237 | clk_disable(pltfm_host->clk); | ||
| 238 | clk_put(pltfm_host->clk); | ||
| 239 | } | ||
| 240 | |||
| 241 | static struct sdhci_ops tegra_sdhci_ops = { | ||
| 242 | .get_ro = tegra_sdhci_get_ro, | ||
| 243 | .read_l = tegra_sdhci_readl, | ||
| 244 | .read_w = tegra_sdhci_readw, | ||
| 245 | .write_l = tegra_sdhci_writel, | ||
| 246 | .platform_8bit_width = tegra_sdhci_8bit, | ||
| 247 | }; | ||
| 248 | |||
| 249 | struct sdhci_pltfm_data sdhci_tegra_pdata = { | ||
| 250 | .quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL | | ||
| 251 | SDHCI_QUIRK_SINGLE_POWER_WRITE | | ||
| 252 | SDHCI_QUIRK_NO_HISPD_BIT | | ||
| 253 | SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC, | ||
| 254 | .ops = &tegra_sdhci_ops, | ||
| 255 | .init = tegra_sdhci_pltfm_init, | ||
| 256 | .exit = tegra_sdhci_pltfm_exit, | ||
| 257 | }; | ||
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index a25db426c910..9e15f41f87be 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | 23 | ||
| 24 | #include <linux/leds.h> | 24 | #include <linux/leds.h> |
| 25 | 25 | ||
| 26 | #include <linux/mmc/mmc.h> | ||
| 26 | #include <linux/mmc/host.h> | 27 | #include <linux/mmc/host.h> |
| 27 | 28 | ||
| 28 | #include "sdhci.h" | 29 | #include "sdhci.h" |
| @@ -77,8 +78,11 @@ static void sdhci_dumpregs(struct sdhci_host *host) | |||
| 77 | printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", | 78 | printk(KERN_DEBUG DRIVER_NAME ": AC12 err: 0x%08x | Slot int: 0x%08x\n", |
| 78 | sdhci_readw(host, SDHCI_ACMD12_ERR), | 79 | sdhci_readw(host, SDHCI_ACMD12_ERR), |
| 79 | sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); | 80 | sdhci_readw(host, SDHCI_SLOT_INT_STATUS)); |
| 80 | printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Max curr: 0x%08x\n", | 81 | printk(KERN_DEBUG DRIVER_NAME ": Caps: 0x%08x | Caps_1: 0x%08x\n", |
| 81 | sdhci_readl(host, SDHCI_CAPABILITIES), | 82 | sdhci_readl(host, SDHCI_CAPABILITIES), |
| 83 | sdhci_readl(host, SDHCI_CAPABILITIES_1)); | ||
| 84 | printk(KERN_DEBUG DRIVER_NAME ": Cmd: 0x%08x | Max curr: 0x%08x\n", | ||
| 85 | sdhci_readw(host, SDHCI_COMMAND), | ||
| 82 | sdhci_readl(host, SDHCI_MAX_CURRENT)); | 86 | sdhci_readl(host, SDHCI_MAX_CURRENT)); |
| 83 | 87 | ||
| 84 | if (host->flags & SDHCI_USE_ADMA) | 88 | if (host->flags & SDHCI_USE_ADMA) |
| @@ -1518,7 +1522,11 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
| 1518 | 1522 | ||
| 1519 | if (intmask & SDHCI_INT_DATA_TIMEOUT) | 1523 | if (intmask & SDHCI_INT_DATA_TIMEOUT) |
| 1520 | host->data->error = -ETIMEDOUT; | 1524 | host->data->error = -ETIMEDOUT; |
| 1521 | else if (intmask & (SDHCI_INT_DATA_CRC | SDHCI_INT_DATA_END_BIT)) | 1525 | else if (intmask & SDHCI_INT_DATA_END_BIT) |
| 1526 | host->data->error = -EILSEQ; | ||
| 1527 | else if ((intmask & SDHCI_INT_DATA_CRC) && | ||
| 1528 | SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) | ||
| 1529 | != MMC_BUS_TEST_R) | ||
| 1522 | host->data->error = -EILSEQ; | 1530 | host->data->error = -EILSEQ; |
| 1523 | else if (intmask & SDHCI_INT_ADMA_ERROR) { | 1531 | else if (intmask & SDHCI_INT_ADMA_ERROR) { |
| 1524 | printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); | 1532 | printk(KERN_ERR "%s: ADMA error\n", mmc_hostname(host->mmc)); |
| @@ -1736,7 +1744,7 @@ EXPORT_SYMBOL_GPL(sdhci_alloc_host); | |||
| 1736 | int sdhci_add_host(struct sdhci_host *host) | 1744 | int sdhci_add_host(struct sdhci_host *host) |
| 1737 | { | 1745 | { |
| 1738 | struct mmc_host *mmc; | 1746 | struct mmc_host *mmc; |
| 1739 | unsigned int caps; | 1747 | unsigned int caps, ocr_avail; |
| 1740 | int ret; | 1748 | int ret; |
| 1741 | 1749 | ||
| 1742 | WARN_ON(host == NULL); | 1750 | WARN_ON(host == NULL); |
| @@ -1890,13 +1898,26 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 1890 | mmc_card_is_removable(mmc)) | 1898 | mmc_card_is_removable(mmc)) |
| 1891 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 1899 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
| 1892 | 1900 | ||
| 1893 | mmc->ocr_avail = 0; | 1901 | ocr_avail = 0; |
| 1894 | if (caps & SDHCI_CAN_VDD_330) | 1902 | if (caps & SDHCI_CAN_VDD_330) |
| 1895 | mmc->ocr_avail |= MMC_VDD_32_33|MMC_VDD_33_34; | 1903 | ocr_avail |= MMC_VDD_32_33 | MMC_VDD_33_34; |
| 1896 | if (caps & SDHCI_CAN_VDD_300) | 1904 | if (caps & SDHCI_CAN_VDD_300) |
| 1897 | mmc->ocr_avail |= MMC_VDD_29_30|MMC_VDD_30_31; | 1905 | ocr_avail |= MMC_VDD_29_30 | MMC_VDD_30_31; |
| 1898 | if (caps & SDHCI_CAN_VDD_180) | 1906 | if (caps & SDHCI_CAN_VDD_180) |
| 1899 | mmc->ocr_avail |= MMC_VDD_165_195; | 1907 | ocr_avail |= MMC_VDD_165_195; |
| 1908 | |||
| 1909 | mmc->ocr_avail = ocr_avail; | ||
| 1910 | mmc->ocr_avail_sdio = ocr_avail; | ||
| 1911 | if (host->ocr_avail_sdio) | ||
| 1912 | mmc->ocr_avail_sdio &= host->ocr_avail_sdio; | ||
| 1913 | mmc->ocr_avail_sd = ocr_avail; | ||
| 1914 | if (host->ocr_avail_sd) | ||
| 1915 | mmc->ocr_avail_sd &= host->ocr_avail_sd; | ||
| 1916 | else /* normal SD controllers don't support 1.8V */ | ||
| 1917 | mmc->ocr_avail_sd &= ~MMC_VDD_165_195; | ||
| 1918 | mmc->ocr_avail_mmc = ocr_avail; | ||
| 1919 | if (host->ocr_avail_mmc) | ||
| 1920 | mmc->ocr_avail_mmc &= host->ocr_avail_mmc; | ||
| 1900 | 1921 | ||
| 1901 | if (mmc->ocr_avail == 0) { | 1922 | if (mmc->ocr_avail == 0) { |
| 1902 | printk(KERN_ERR "%s: Hardware doesn't report any " | 1923 | printk(KERN_ERR "%s: Hardware doesn't report any " |
| @@ -1928,10 +1949,14 @@ int sdhci_add_host(struct sdhci_host *host) | |||
| 1928 | * of bytes. When doing hardware scatter/gather, each entry cannot | 1949 | * of bytes. When doing hardware scatter/gather, each entry cannot |
| 1929 | * be larger than 64 KiB though. | 1950 | * be larger than 64 KiB though. |
| 1930 | */ | 1951 | */ |
| 1931 | if (host->flags & SDHCI_USE_ADMA) | 1952 | if (host->flags & SDHCI_USE_ADMA) { |
| 1932 | mmc->max_seg_size = 65536; | 1953 | if (host->quirks & SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC) |
| 1933 | else | 1954 | mmc->max_seg_size = 65535; |
| 1955 | else | ||
| 1956 | mmc->max_seg_size = 65536; | ||
| 1957 | } else { | ||
| 1934 | mmc->max_seg_size = mmc->max_req_size; | 1958 | mmc->max_seg_size = mmc->max_req_size; |
| 1959 | } | ||
| 1935 | 1960 | ||
| 1936 | /* | 1961 | /* |
| 1937 | * Maximum block size. This varies from controller to controller and | 1962 | * Maximum block size. This varies from controller to controller and |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index e42d7f00c060..6e0969e40650 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #define SDHCI_CMD_RESP_SHORT_BUSY 0x03 | 52 | #define SDHCI_CMD_RESP_SHORT_BUSY 0x03 |
| 53 | 53 | ||
| 54 | #define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) | 54 | #define SDHCI_MAKE_CMD(c, f) (((c & 0xff) << 8) | (f & 0xff)) |
| 55 | #define SDHCI_GET_CMD(c) ((c>>8) & 0x3f) | ||
| 55 | 56 | ||
| 56 | #define SDHCI_RESPONSE 0x10 | 57 | #define SDHCI_RESPONSE 0x10 |
| 57 | 58 | ||
| @@ -165,7 +166,7 @@ | |||
| 165 | #define SDHCI_CAN_VDD_180 0x04000000 | 166 | #define SDHCI_CAN_VDD_180 0x04000000 |
| 166 | #define SDHCI_CAN_64BIT 0x10000000 | 167 | #define SDHCI_CAN_64BIT 0x10000000 |
| 167 | 168 | ||
| 168 | /* 44-47 reserved for more caps */ | 169 | #define SDHCI_CAPABILITIES_1 0x44 |
| 169 | 170 | ||
| 170 | #define SDHCI_MAX_CURRENT 0x48 | 171 | #define SDHCI_MAX_CURRENT 0x48 |
| 171 | 172 | ||
diff --git a/drivers/mmc/host/tmio_mmc.c b/drivers/mmc/host/tmio_mmc.c index e7765a89593e..e3c6ef208391 100644 --- a/drivers/mmc/host/tmio_mmc.c +++ b/drivers/mmc/host/tmio_mmc.c | |||
| @@ -25,16 +25,261 @@ | |||
| 25 | * double buffer support | 25 | * double buffer support |
| 26 | * | 26 | * |
| 27 | */ | 27 | */ |
| 28 | #include <linux/module.h> | 28 | |
| 29 | #include <linux/irq.h> | ||
| 30 | #include <linux/device.h> | ||
| 31 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
| 30 | #include <linux/device.h> | ||
| 32 | #include <linux/dmaengine.h> | 31 | #include <linux/dmaengine.h> |
| 33 | #include <linux/mmc/host.h> | 32 | #include <linux/highmem.h> |
| 33 | #include <linux/interrupt.h> | ||
| 34 | #include <linux/io.h> | ||
| 35 | #include <linux/irq.h> | ||
| 34 | #include <linux/mfd/core.h> | 36 | #include <linux/mfd/core.h> |
| 35 | #include <linux/mfd/tmio.h> | 37 | #include <linux/mfd/tmio.h> |
| 38 | #include <linux/mmc/host.h> | ||
| 39 | #include <linux/module.h> | ||
| 40 | #include <linux/pagemap.h> | ||
| 41 | #include <linux/scatterlist.h> | ||
| 42 | #include <linux/workqueue.h> | ||
| 43 | #include <linux/spinlock.h> | ||
| 44 | |||
| 45 | #define CTL_SD_CMD 0x00 | ||
| 46 | #define CTL_ARG_REG 0x04 | ||
| 47 | #define CTL_STOP_INTERNAL_ACTION 0x08 | ||
| 48 | #define CTL_XFER_BLK_COUNT 0xa | ||
| 49 | #define CTL_RESPONSE 0x0c | ||
| 50 | #define CTL_STATUS 0x1c | ||
| 51 | #define CTL_IRQ_MASK 0x20 | ||
| 52 | #define CTL_SD_CARD_CLK_CTL 0x24 | ||
| 53 | #define CTL_SD_XFER_LEN 0x26 | ||
| 54 | #define CTL_SD_MEM_CARD_OPT 0x28 | ||
| 55 | #define CTL_SD_ERROR_DETAIL_STATUS 0x2c | ||
| 56 | #define CTL_SD_DATA_PORT 0x30 | ||
| 57 | #define CTL_TRANSACTION_CTL 0x34 | ||
| 58 | #define CTL_SDIO_STATUS 0x36 | ||
| 59 | #define CTL_SDIO_IRQ_MASK 0x38 | ||
| 60 | #define CTL_RESET_SD 0xe0 | ||
| 61 | #define CTL_SDIO_REGS 0x100 | ||
| 62 | #define CTL_CLK_AND_WAIT_CTL 0x138 | ||
| 63 | #define CTL_RESET_SDIO 0x1e0 | ||
| 64 | |||
| 65 | /* Definitions for values the CTRL_STATUS register can take. */ | ||
| 66 | #define TMIO_STAT_CMDRESPEND 0x00000001 | ||
| 67 | #define TMIO_STAT_DATAEND 0x00000004 | ||
| 68 | #define TMIO_STAT_CARD_REMOVE 0x00000008 | ||
| 69 | #define TMIO_STAT_CARD_INSERT 0x00000010 | ||
| 70 | #define TMIO_STAT_SIGSTATE 0x00000020 | ||
| 71 | #define TMIO_STAT_WRPROTECT 0x00000080 | ||
| 72 | #define TMIO_STAT_CARD_REMOVE_A 0x00000100 | ||
| 73 | #define TMIO_STAT_CARD_INSERT_A 0x00000200 | ||
| 74 | #define TMIO_STAT_SIGSTATE_A 0x00000400 | ||
| 75 | #define TMIO_STAT_CMD_IDX_ERR 0x00010000 | ||
| 76 | #define TMIO_STAT_CRCFAIL 0x00020000 | ||
| 77 | #define TMIO_STAT_STOPBIT_ERR 0x00040000 | ||
| 78 | #define TMIO_STAT_DATATIMEOUT 0x00080000 | ||
| 79 | #define TMIO_STAT_RXOVERFLOW 0x00100000 | ||
| 80 | #define TMIO_STAT_TXUNDERRUN 0x00200000 | ||
| 81 | #define TMIO_STAT_CMDTIMEOUT 0x00400000 | ||
| 82 | #define TMIO_STAT_RXRDY 0x01000000 | ||
| 83 | #define TMIO_STAT_TXRQ 0x02000000 | ||
| 84 | #define TMIO_STAT_ILL_FUNC 0x20000000 | ||
| 85 | #define TMIO_STAT_CMD_BUSY 0x40000000 | ||
| 86 | #define TMIO_STAT_ILL_ACCESS 0x80000000 | ||
| 87 | |||
| 88 | /* Definitions for values the CTRL_SDIO_STATUS register can take. */ | ||
| 89 | #define TMIO_SDIO_STAT_IOIRQ 0x0001 | ||
| 90 | #define TMIO_SDIO_STAT_EXPUB52 0x4000 | ||
| 91 | #define TMIO_SDIO_STAT_EXWT 0x8000 | ||
| 92 | #define TMIO_SDIO_MASK_ALL 0xc007 | ||
| 93 | |||
| 94 | /* Define some IRQ masks */ | ||
| 95 | /* This is the mask used at reset by the chip */ | ||
| 96 | #define TMIO_MASK_ALL 0x837f031d | ||
| 97 | #define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND) | ||
| 98 | #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND) | ||
| 99 | #define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \ | ||
| 100 | TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT) | ||
| 101 | #define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD) | ||
| 102 | |||
| 103 | #define enable_mmc_irqs(host, i) \ | ||
| 104 | do { \ | ||
| 105 | u32 mask;\ | ||
| 106 | mask = sd_ctrl_read32((host), CTL_IRQ_MASK); \ | ||
| 107 | mask &= ~((i) & TMIO_MASK_IRQ); \ | ||
| 108 | sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \ | ||
| 109 | } while (0) | ||
| 110 | |||
| 111 | #define disable_mmc_irqs(host, i) \ | ||
| 112 | do { \ | ||
| 113 | u32 mask;\ | ||
| 114 | mask = sd_ctrl_read32((host), CTL_IRQ_MASK); \ | ||
| 115 | mask |= ((i) & TMIO_MASK_IRQ); \ | ||
| 116 | sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \ | ||
| 117 | } while (0) | ||
| 118 | |||
| 119 | #define ack_mmc_irqs(host, i) \ | ||
| 120 | do { \ | ||
| 121 | sd_ctrl_write32((host), CTL_STATUS, ~(i)); \ | ||
| 122 | } while (0) | ||
| 123 | |||
| 124 | /* This is arbitrary, just noone needed any higher alignment yet */ | ||
| 125 | #define MAX_ALIGN 4 | ||
| 126 | |||
| 127 | struct tmio_mmc_host { | ||
| 128 | void __iomem *ctl; | ||
| 129 | unsigned long bus_shift; | ||
| 130 | struct mmc_command *cmd; | ||
| 131 | struct mmc_request *mrq; | ||
| 132 | struct mmc_data *data; | ||
| 133 | struct mmc_host *mmc; | ||
| 134 | int irq; | ||
| 135 | unsigned int sdio_irq_enabled; | ||
| 136 | |||
| 137 | /* Callbacks for clock / power control */ | ||
| 138 | void (*set_pwr)(struct platform_device *host, int state); | ||
| 139 | void (*set_clk_div)(struct platform_device *host, int state); | ||
| 140 | |||
| 141 | /* pio related stuff */ | ||
| 142 | struct scatterlist *sg_ptr; | ||
| 143 | struct scatterlist *sg_orig; | ||
| 144 | unsigned int sg_len; | ||
| 145 | unsigned int sg_off; | ||
| 146 | |||
| 147 | struct platform_device *pdev; | ||
| 148 | |||
| 149 | /* DMA support */ | ||
| 150 | struct dma_chan *chan_rx; | ||
| 151 | struct dma_chan *chan_tx; | ||
| 152 | struct tasklet_struct dma_complete; | ||
| 153 | struct tasklet_struct dma_issue; | ||
| 154 | #ifdef CONFIG_TMIO_MMC_DMA | ||
| 155 | unsigned int dma_sglen; | ||
| 156 | u8 bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN))); | ||
| 157 | struct scatterlist bounce_sg; | ||
| 158 | #endif | ||
| 159 | |||
| 160 | /* Track lost interrupts */ | ||
| 161 | struct delayed_work delayed_reset_work; | ||
| 162 | spinlock_t lock; | ||
| 163 | unsigned long last_req_ts; | ||
| 164 | }; | ||
| 165 | |||
| 166 | static void tmio_check_bounce_buffer(struct tmio_mmc_host *host); | ||
| 167 | |||
| 168 | static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) | ||
| 169 | { | ||
| 170 | return readw(host->ctl + (addr << host->bus_shift)); | ||
| 171 | } | ||
| 172 | |||
| 173 | static void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, | ||
| 174 | u16 *buf, int count) | ||
| 175 | { | ||
| 176 | readsw(host->ctl + (addr << host->bus_shift), buf, count); | ||
| 177 | } | ||
| 36 | 178 | ||
| 37 | #include "tmio_mmc.h" | 179 | static u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) |
| 180 | { | ||
| 181 | return readw(host->ctl + (addr << host->bus_shift)) | | ||
| 182 | readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; | ||
| 183 | } | ||
| 184 | |||
| 185 | static void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val) | ||
| 186 | { | ||
| 187 | writew(val, host->ctl + (addr << host->bus_shift)); | ||
| 188 | } | ||
| 189 | |||
| 190 | static void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, | ||
| 191 | u16 *buf, int count) | ||
| 192 | { | ||
| 193 | writesw(host->ctl + (addr << host->bus_shift), buf, count); | ||
| 194 | } | ||
| 195 | |||
| 196 | static void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, u32 val) | ||
| 197 | { | ||
| 198 | writew(val, host->ctl + (addr << host->bus_shift)); | ||
| 199 | writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); | ||
| 200 | } | ||
| 201 | |||
| 202 | static void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data) | ||
| 203 | { | ||
| 204 | host->sg_len = data->sg_len; | ||
| 205 | host->sg_ptr = data->sg; | ||
| 206 | host->sg_orig = data->sg; | ||
| 207 | host->sg_off = 0; | ||
| 208 | } | ||
| 209 | |||
| 210 | static int tmio_mmc_next_sg(struct tmio_mmc_host *host) | ||
| 211 | { | ||
| 212 | host->sg_ptr = sg_next(host->sg_ptr); | ||
| 213 | host->sg_off = 0; | ||
| 214 | return --host->sg_len; | ||
| 215 | } | ||
| 216 | |||
| 217 | static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags) | ||
| 218 | { | ||
| 219 | local_irq_save(*flags); | ||
| 220 | return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | ||
| 221 | } | ||
| 222 | |||
| 223 | static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags) | ||
| 224 | { | ||
| 225 | kunmap_atomic(virt, KM_BIO_SRC_IRQ); | ||
| 226 | local_irq_restore(*flags); | ||
| 227 | } | ||
| 228 | |||
| 229 | #ifdef CONFIG_MMC_DEBUG | ||
| 230 | |||
| 231 | #define STATUS_TO_TEXT(a) \ | ||
| 232 | do { \ | ||
| 233 | if (status & TMIO_STAT_##a) \ | ||
| 234 | printk(#a); \ | ||
| 235 | } while (0) | ||
| 236 | |||
| 237 | void pr_debug_status(u32 status) | ||
| 238 | { | ||
| 239 | printk(KERN_DEBUG "status: %08x = ", status); | ||
| 240 | STATUS_TO_TEXT(CARD_REMOVE); | ||
| 241 | STATUS_TO_TEXT(CARD_INSERT); | ||
| 242 | STATUS_TO_TEXT(SIGSTATE); | ||
| 243 | STATUS_TO_TEXT(WRPROTECT); | ||
| 244 | STATUS_TO_TEXT(CARD_REMOVE_A); | ||
| 245 | STATUS_TO_TEXT(CARD_INSERT_A); | ||
| 246 | STATUS_TO_TEXT(SIGSTATE_A); | ||
| 247 | STATUS_TO_TEXT(CMD_IDX_ERR); | ||
| 248 | STATUS_TO_TEXT(STOPBIT_ERR); | ||
| 249 | STATUS_TO_TEXT(ILL_FUNC); | ||
| 250 | STATUS_TO_TEXT(CMD_BUSY); | ||
| 251 | STATUS_TO_TEXT(CMDRESPEND); | ||
| 252 | STATUS_TO_TEXT(DATAEND); | ||
| 253 | STATUS_TO_TEXT(CRCFAIL); | ||
| 254 | STATUS_TO_TEXT(DATATIMEOUT); | ||
| 255 | STATUS_TO_TEXT(CMDTIMEOUT); | ||
| 256 | STATUS_TO_TEXT(RXOVERFLOW); | ||
| 257 | STATUS_TO_TEXT(TXUNDERRUN); | ||
| 258 | STATUS_TO_TEXT(RXRDY); | ||
| 259 | STATUS_TO_TEXT(TXRQ); | ||
| 260 | STATUS_TO_TEXT(ILL_ACCESS); | ||
| 261 | printk("\n"); | ||
| 262 | } | ||
| 263 | |||
| 264 | #else | ||
| 265 | #define pr_debug_status(s) do { } while (0) | ||
| 266 | #endif | ||
| 267 | |||
| 268 | static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable) | ||
| 269 | { | ||
| 270 | struct tmio_mmc_host *host = mmc_priv(mmc); | ||
| 271 | |||
| 272 | if (enable) { | ||
| 273 | host->sdio_irq_enabled = 1; | ||
| 274 | sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001); | ||
| 275 | sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, | ||
| 276 | (TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ)); | ||
| 277 | } else { | ||
| 278 | sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL); | ||
| 279 | sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000); | ||
| 280 | host->sdio_irq_enabled = 0; | ||
| 281 | } | ||
| 282 | } | ||
| 38 | 283 | ||
| 39 | static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) | 284 | static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) |
| 40 | { | 285 | { |
| @@ -55,8 +300,23 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock) | |||
| 55 | 300 | ||
| 56 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | 301 | static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) |
| 57 | { | 302 | { |
| 303 | struct mfd_cell *cell = host->pdev->dev.platform_data; | ||
| 304 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
| 305 | |||
| 306 | /* | ||
| 307 | * Testing on sh-mobile showed that SDIO IRQs are unmasked when | ||
| 308 | * CTL_CLK_AND_WAIT_CTL gets written, so we have to disable the | ||
| 309 | * device IRQ here and restore the SDIO IRQ mask before | ||
| 310 | * re-enabling the device IRQ. | ||
| 311 | */ | ||
| 312 | if (pdata->flags & TMIO_MMC_SDIO_IRQ) | ||
| 313 | disable_irq(host->irq); | ||
| 58 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); | 314 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000); |
| 59 | msleep(10); | 315 | msleep(10); |
| 316 | if (pdata->flags & TMIO_MMC_SDIO_IRQ) { | ||
| 317 | tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled); | ||
| 318 | enable_irq(host->irq); | ||
| 319 | } | ||
| 60 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 & | 320 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 & |
| 61 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); | 321 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); |
| 62 | msleep(10); | 322 | msleep(10); |
| @@ -64,11 +324,21 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host) | |||
| 64 | 324 | ||
| 65 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) | 325 | static void tmio_mmc_clk_start(struct tmio_mmc_host *host) |
| 66 | { | 326 | { |
| 327 | struct mfd_cell *cell = host->pdev->dev.platform_data; | ||
| 328 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
| 329 | |||
| 67 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | | 330 | sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 | |
| 68 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); | 331 | sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL)); |
| 69 | msleep(10); | 332 | msleep(10); |
| 333 | /* see comment in tmio_mmc_clk_stop above */ | ||
| 334 | if (pdata->flags & TMIO_MMC_SDIO_IRQ) | ||
| 335 | disable_irq(host->irq); | ||
| 70 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); | 336 | sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100); |
| 71 | msleep(10); | 337 | msleep(10); |
| 338 | if (pdata->flags & TMIO_MMC_SDIO_IRQ) { | ||
| 339 | tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled); | ||
| 340 | enable_irq(host->irq); | ||
| 341 | } | ||
| 72 | } | 342 | } |
| 73 | 343 | ||
| 74 | static void reset(struct tmio_mmc_host *host) | 344 | static void reset(struct tmio_mmc_host *host) |
| @@ -82,15 +352,60 @@ static void reset(struct tmio_mmc_host *host) | |||
| 82 | msleep(10); | 352 | msleep(10); |
| 83 | } | 353 | } |
| 84 | 354 | ||
| 355 | static void tmio_mmc_reset_work(struct work_struct *work) | ||
| 356 | { | ||
| 357 | struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host, | ||
| 358 | delayed_reset_work.work); | ||
| 359 | struct mmc_request *mrq; | ||
| 360 | unsigned long flags; | ||
| 361 | |||
| 362 | spin_lock_irqsave(&host->lock, flags); | ||
| 363 | mrq = host->mrq; | ||
| 364 | |||
| 365 | /* request already finished */ | ||
| 366 | if (!mrq | ||
| 367 | || time_is_after_jiffies(host->last_req_ts + | ||
| 368 | msecs_to_jiffies(2000))) { | ||
| 369 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 370 | return; | ||
| 371 | } | ||
| 372 | |||
| 373 | dev_warn(&host->pdev->dev, | ||
| 374 | "timeout waiting for hardware interrupt (CMD%u)\n", | ||
| 375 | mrq->cmd->opcode); | ||
| 376 | |||
| 377 | if (host->data) | ||
| 378 | host->data->error = -ETIMEDOUT; | ||
| 379 | else if (host->cmd) | ||
| 380 | host->cmd->error = -ETIMEDOUT; | ||
| 381 | else | ||
| 382 | mrq->cmd->error = -ETIMEDOUT; | ||
| 383 | |||
| 384 | host->cmd = NULL; | ||
| 385 | host->data = NULL; | ||
| 386 | host->mrq = NULL; | ||
| 387 | |||
| 388 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 389 | |||
| 390 | reset(host); | ||
| 391 | |||
| 392 | mmc_request_done(host->mmc, mrq); | ||
| 393 | } | ||
| 394 | |||
| 85 | static void | 395 | static void |
| 86 | tmio_mmc_finish_request(struct tmio_mmc_host *host) | 396 | tmio_mmc_finish_request(struct tmio_mmc_host *host) |
| 87 | { | 397 | { |
| 88 | struct mmc_request *mrq = host->mrq; | 398 | struct mmc_request *mrq = host->mrq; |
| 89 | 399 | ||
| 400 | if (!mrq) | ||
| 401 | return; | ||
| 402 | |||
| 90 | host->mrq = NULL; | 403 | host->mrq = NULL; |
| 91 | host->cmd = NULL; | 404 | host->cmd = NULL; |
| 92 | host->data = NULL; | 405 | host->data = NULL; |
| 93 | 406 | ||
| 407 | cancel_delayed_work(&host->delayed_reset_work); | ||
| 408 | |||
| 94 | mmc_request_done(host->mmc, mrq); | 409 | mmc_request_done(host->mmc, mrq); |
| 95 | } | 410 | } |
| 96 | 411 | ||
| @@ -200,6 +515,7 @@ static void tmio_mmc_pio_irq(struct tmio_mmc_host *host) | |||
| 200 | return; | 515 | return; |
| 201 | } | 516 | } |
| 202 | 517 | ||
| 518 | /* needs to be called with host->lock held */ | ||
| 203 | static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) | 519 | static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) |
| 204 | { | 520 | { |
| 205 | struct mmc_data *data = host->data; | 521 | struct mmc_data *data = host->data; |
| @@ -233,6 +549,8 @@ static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) | |||
| 233 | if (data->flags & MMC_DATA_READ) { | 549 | if (data->flags & MMC_DATA_READ) { |
| 234 | if (!host->chan_rx) | 550 | if (!host->chan_rx) |
| 235 | disable_mmc_irqs(host, TMIO_MASK_READOP); | 551 | disable_mmc_irqs(host, TMIO_MASK_READOP); |
| 552 | else | ||
| 553 | tmio_check_bounce_buffer(host); | ||
| 236 | dev_dbg(&host->pdev->dev, "Complete Rx request %p\n", | 554 | dev_dbg(&host->pdev->dev, "Complete Rx request %p\n", |
| 237 | host->mrq); | 555 | host->mrq); |
| 238 | } else { | 556 | } else { |
| @@ -254,10 +572,12 @@ static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host) | |||
| 254 | 572 | ||
| 255 | static void tmio_mmc_data_irq(struct tmio_mmc_host *host) | 573 | static void tmio_mmc_data_irq(struct tmio_mmc_host *host) |
| 256 | { | 574 | { |
| 257 | struct mmc_data *data = host->data; | 575 | struct mmc_data *data; |
| 576 | spin_lock(&host->lock); | ||
| 577 | data = host->data; | ||
| 258 | 578 | ||
| 259 | if (!data) | 579 | if (!data) |
| 260 | return; | 580 | goto out; |
| 261 | 581 | ||
| 262 | if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) { | 582 | if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) { |
| 263 | /* | 583 | /* |
| @@ -278,6 +598,8 @@ static void tmio_mmc_data_irq(struct tmio_mmc_host *host) | |||
| 278 | } else { | 598 | } else { |
| 279 | tmio_mmc_do_data_irq(host); | 599 | tmio_mmc_do_data_irq(host); |
| 280 | } | 600 | } |
| 601 | out: | ||
| 602 | spin_unlock(&host->lock); | ||
| 281 | } | 603 | } |
| 282 | 604 | ||
| 283 | static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, | 605 | static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, |
| @@ -286,9 +608,11 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, | |||
| 286 | struct mmc_command *cmd = host->cmd; | 608 | struct mmc_command *cmd = host->cmd; |
| 287 | int i, addr; | 609 | int i, addr; |
| 288 | 610 | ||
| 611 | spin_lock(&host->lock); | ||
| 612 | |||
| 289 | if (!host->cmd) { | 613 | if (!host->cmd) { |
| 290 | pr_debug("Spurious CMD irq\n"); | 614 | pr_debug("Spurious CMD irq\n"); |
| 291 | return; | 615 | goto out; |
| 292 | } | 616 | } |
| 293 | 617 | ||
| 294 | host->cmd = NULL; | 618 | host->cmd = NULL; |
| @@ -324,8 +648,7 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, | |||
| 324 | if (!host->chan_rx) | 648 | if (!host->chan_rx) |
| 325 | enable_mmc_irqs(host, TMIO_MASK_READOP); | 649 | enable_mmc_irqs(host, TMIO_MASK_READOP); |
| 326 | } else { | 650 | } else { |
| 327 | struct dma_chan *chan = host->chan_tx; | 651 | if (!host->chan_tx) |
| 328 | if (!chan) | ||
| 329 | enable_mmc_irqs(host, TMIO_MASK_WRITEOP); | 652 | enable_mmc_irqs(host, TMIO_MASK_WRITEOP); |
| 330 | else | 653 | else |
| 331 | tasklet_schedule(&host->dma_issue); | 654 | tasklet_schedule(&host->dma_issue); |
| @@ -334,13 +657,19 @@ static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host, | |||
| 334 | tmio_mmc_finish_request(host); | 657 | tmio_mmc_finish_request(host); |
| 335 | } | 658 | } |
| 336 | 659 | ||
| 660 | out: | ||
| 661 | spin_unlock(&host->lock); | ||
| 662 | |||
| 337 | return; | 663 | return; |
| 338 | } | 664 | } |
| 339 | 665 | ||
| 340 | static irqreturn_t tmio_mmc_irq(int irq, void *devid) | 666 | static irqreturn_t tmio_mmc_irq(int irq, void *devid) |
| 341 | { | 667 | { |
| 342 | struct tmio_mmc_host *host = devid; | 668 | struct tmio_mmc_host *host = devid; |
| 669 | struct mfd_cell *cell = host->pdev->dev.platform_data; | ||
| 670 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
| 343 | unsigned int ireg, irq_mask, status; | 671 | unsigned int ireg, irq_mask, status; |
| 672 | unsigned int sdio_ireg, sdio_irq_mask, sdio_status; | ||
| 344 | 673 | ||
| 345 | pr_debug("MMC IRQ begin\n"); | 674 | pr_debug("MMC IRQ begin\n"); |
| 346 | 675 | ||
| @@ -348,6 +677,29 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid) | |||
| 348 | irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK); | 677 | irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK); |
| 349 | ireg = status & TMIO_MASK_IRQ & ~irq_mask; | 678 | ireg = status & TMIO_MASK_IRQ & ~irq_mask; |
| 350 | 679 | ||
| 680 | sdio_ireg = 0; | ||
| 681 | if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) { | ||
| 682 | sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS); | ||
| 683 | sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK); | ||
| 684 | sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask; | ||
| 685 | |||
| 686 | sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL); | ||
| 687 | |||
| 688 | if (sdio_ireg && !host->sdio_irq_enabled) { | ||
| 689 | pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n", | ||
| 690 | sdio_status, sdio_irq_mask, sdio_ireg); | ||
| 691 | tmio_mmc_enable_sdio_irq(host->mmc, 0); | ||
| 692 | goto out; | ||
| 693 | } | ||
| 694 | |||
| 695 | if (host->mmc->caps & MMC_CAP_SDIO_IRQ && | ||
| 696 | sdio_ireg & TMIO_SDIO_STAT_IOIRQ) | ||
| 697 | mmc_signal_sdio_irq(host->mmc); | ||
| 698 | |||
| 699 | if (sdio_ireg) | ||
| 700 | goto out; | ||
| 701 | } | ||
| 702 | |||
| 351 | pr_debug_status(status); | 703 | pr_debug_status(status); |
| 352 | pr_debug_status(ireg); | 704 | pr_debug_status(ireg); |
| 353 | 705 | ||
| @@ -375,8 +727,10 @@ static irqreturn_t tmio_mmc_irq(int irq, void *devid) | |||
| 375 | */ | 727 | */ |
| 376 | 728 | ||
| 377 | /* Command completion */ | 729 | /* Command completion */ |
| 378 | if (ireg & TMIO_MASK_CMD) { | 730 | if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) { |
| 379 | ack_mmc_irqs(host, TMIO_MASK_CMD); | 731 | ack_mmc_irqs(host, |
| 732 | TMIO_STAT_CMDRESPEND | | ||
| 733 | TMIO_STAT_CMDTIMEOUT); | ||
| 380 | tmio_mmc_cmd_irq(host, status); | 734 | tmio_mmc_cmd_irq(host, status); |
| 381 | } | 735 | } |
| 382 | 736 | ||
| @@ -407,6 +761,16 @@ out: | |||
| 407 | } | 761 | } |
| 408 | 762 | ||
| 409 | #ifdef CONFIG_TMIO_MMC_DMA | 763 | #ifdef CONFIG_TMIO_MMC_DMA |
| 764 | static void tmio_check_bounce_buffer(struct tmio_mmc_host *host) | ||
| 765 | { | ||
| 766 | if (host->sg_ptr == &host->bounce_sg) { | ||
| 767 | unsigned long flags; | ||
| 768 | void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags); | ||
| 769 | memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length); | ||
| 770 | tmio_mmc_kunmap_atomic(sg_vaddr, &flags); | ||
| 771 | } | ||
| 772 | } | ||
| 773 | |||
| 410 | static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) | 774 | static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable) |
| 411 | { | 775 | { |
| 412 | #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE) | 776 | #if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE) |
| @@ -427,12 +791,39 @@ static void tmio_dma_complete(void *arg) | |||
| 427 | enable_mmc_irqs(host, TMIO_STAT_DATAEND); | 791 | enable_mmc_irqs(host, TMIO_STAT_DATAEND); |
| 428 | } | 792 | } |
| 429 | 793 | ||
| 430 | static int tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | 794 | static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) |
| 431 | { | 795 | { |
| 432 | struct scatterlist *sg = host->sg_ptr; | 796 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
| 433 | struct dma_async_tx_descriptor *desc = NULL; | 797 | struct dma_async_tx_descriptor *desc = NULL; |
| 434 | struct dma_chan *chan = host->chan_rx; | 798 | struct dma_chan *chan = host->chan_rx; |
| 435 | int ret; | 799 | struct mfd_cell *cell = host->pdev->dev.platform_data; |
| 800 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
| 801 | dma_cookie_t cookie; | ||
| 802 | int ret, i; | ||
| 803 | bool aligned = true, multiple = true; | ||
| 804 | unsigned int align = (1 << pdata->dma->alignment_shift) - 1; | ||
| 805 | |||
| 806 | for_each_sg(sg, sg_tmp, host->sg_len, i) { | ||
| 807 | if (sg_tmp->offset & align) | ||
| 808 | aligned = false; | ||
| 809 | if (sg_tmp->length & align) { | ||
| 810 | multiple = false; | ||
| 811 | break; | ||
| 812 | } | ||
| 813 | } | ||
| 814 | |||
| 815 | if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE || | ||
| 816 | align >= MAX_ALIGN)) || !multiple) { | ||
| 817 | ret = -EINVAL; | ||
| 818 | goto pio; | ||
| 819 | } | ||
| 820 | |||
| 821 | /* The only sg element can be unaligned, use our bounce buffer then */ | ||
| 822 | if (!aligned) { | ||
| 823 | sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); | ||
| 824 | host->sg_ptr = &host->bounce_sg; | ||
| 825 | sg = host->sg_ptr; | ||
| 826 | } | ||
| 436 | 827 | ||
| 437 | ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE); | 828 | ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE); |
| 438 | if (ret > 0) { | 829 | if (ret > 0) { |
| @@ -442,21 +833,21 @@ static int tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | |||
| 442 | } | 833 | } |
| 443 | 834 | ||
| 444 | if (desc) { | 835 | if (desc) { |
| 445 | host->desc = desc; | ||
| 446 | desc->callback = tmio_dma_complete; | 836 | desc->callback = tmio_dma_complete; |
| 447 | desc->callback_param = host; | 837 | desc->callback_param = host; |
| 448 | host->cookie = desc->tx_submit(desc); | 838 | cookie = desc->tx_submit(desc); |
| 449 | if (host->cookie < 0) { | 839 | if (cookie < 0) { |
| 450 | host->desc = NULL; | 840 | desc = NULL; |
| 451 | ret = host->cookie; | 841 | ret = cookie; |
| 452 | } else { | 842 | } else { |
| 453 | chan->device->device_issue_pending(chan); | 843 | chan->device->device_issue_pending(chan); |
| 454 | } | 844 | } |
| 455 | } | 845 | } |
| 456 | dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n", | 846 | dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n", |
| 457 | __func__, host->sg_len, ret, host->cookie, host->mrq); | 847 | __func__, host->sg_len, ret, cookie, host->mrq); |
| 458 | 848 | ||
| 459 | if (!host->desc) { | 849 | pio: |
| 850 | if (!desc) { | ||
| 460 | /* DMA failed, fall back to PIO */ | 851 | /* DMA failed, fall back to PIO */ |
| 461 | if (ret >= 0) | 852 | if (ret >= 0) |
| 462 | ret = -EIO; | 853 | ret = -EIO; |
| @@ -471,24 +862,49 @@ static int tmio_mmc_start_dma_rx(struct tmio_mmc_host *host) | |||
| 471 | dev_warn(&host->pdev->dev, | 862 | dev_warn(&host->pdev->dev, |
| 472 | "DMA failed: %d, falling back to PIO\n", ret); | 863 | "DMA failed: %d, falling back to PIO\n", ret); |
| 473 | tmio_mmc_enable_dma(host, false); | 864 | tmio_mmc_enable_dma(host, false); |
| 474 | reset(host); | ||
| 475 | /* Fail this request, let above layers recover */ | ||
| 476 | host->mrq->cmd->error = ret; | ||
| 477 | tmio_mmc_finish_request(host); | ||
| 478 | } | 865 | } |
| 479 | 866 | ||
| 480 | dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, | 867 | dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__, |
| 481 | desc, host->cookie, host->sg_len); | 868 | desc, cookie, host->sg_len); |
| 482 | |||
| 483 | return ret > 0 ? 0 : ret; | ||
| 484 | } | 869 | } |
| 485 | 870 | ||
| 486 | static int tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) | 871 | static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) |
| 487 | { | 872 | { |
| 488 | struct scatterlist *sg = host->sg_ptr; | 873 | struct scatterlist *sg = host->sg_ptr, *sg_tmp; |
| 489 | struct dma_async_tx_descriptor *desc = NULL; | 874 | struct dma_async_tx_descriptor *desc = NULL; |
| 490 | struct dma_chan *chan = host->chan_tx; | 875 | struct dma_chan *chan = host->chan_tx; |
| 491 | int ret; | 876 | struct mfd_cell *cell = host->pdev->dev.platform_data; |
| 877 | struct tmio_mmc_data *pdata = cell->driver_data; | ||
| 878 | dma_cookie_t cookie; | ||
| 879 | int ret, i; | ||
| 880 | bool aligned = true, multiple = true; | ||
| 881 | unsigned int align = (1 << pdata->dma->alignment_shift) - 1; | ||
| 882 | |||
| 883 | for_each_sg(sg, sg_tmp, host->sg_len, i) { | ||
| 884 | if (sg_tmp->offset & align) | ||
| 885 | aligned = false; | ||
| 886 | if (sg_tmp->length & align) { | ||
| 887 | multiple = false; | ||
| 888 | break; | ||
| 889 | } | ||
| 890 | } | ||
| 891 | |||
| 892 | if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE || | ||
| 893 | align >= MAX_ALIGN)) || !multiple) { | ||
| 894 | ret = -EINVAL; | ||
| 895 | goto pio; | ||
| 896 | } | ||
| 897 | |||
| 898 | /* The only sg element can be unaligned, use our bounce buffer then */ | ||
| 899 | if (!aligned) { | ||
| 900 | unsigned long flags; | ||
| 901 | void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags); | ||
| 902 | sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length); | ||
| 903 | memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length); | ||
| 904 | tmio_mmc_kunmap_atomic(sg_vaddr, &flags); | ||
| 905 | host->sg_ptr = &host->bounce_sg; | ||
| 906 | sg = host->sg_ptr; | ||
| 907 | } | ||
| 492 | 908 | ||
| 493 | ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE); | 909 | ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE); |
| 494 | if (ret > 0) { | 910 | if (ret > 0) { |
| @@ -498,19 +914,19 @@ static int tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) | |||
| 498 | } | 914 | } |
| 499 | 915 | ||
| 500 | if (desc) { | 916 | if (desc) { |
| 501 | host->desc = desc; | ||
| 502 | desc->callback = tmio_dma_complete; | 917 | desc->callback = tmio_dma_complete; |
| 503 | desc->callback_param = host; | 918 | desc->callback_param = host; |
| 504 | host->cookie = desc->tx_submit(desc); | 919 | cookie = desc->tx_submit(desc); |
| 505 | if (host->cookie < 0) { | 920 | if (cookie < 0) { |
| 506 | host->desc = NULL; | 921 | desc = NULL; |
| 507 | ret = host->cookie; | 922 | ret = cookie; |
| 508 | } | 923 | } |
| 509 | } | 924 | } |
| 510 | dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n", | 925 | dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n", |
| 511 | __func__, host->sg_len, ret, host->cookie, host->mrq); | 926 | __func__, host->sg_len, ret, cookie, host->mrq); |
| 512 | 927 | ||
| 513 | if (!host->desc) { | 928 | pio: |
| 929 | if (!desc) { | ||
| 514 | /* DMA failed, fall back to PIO */ | 930 | /* DMA failed, fall back to PIO */ |
| 515 | if (ret >= 0) | 931 | if (ret >= 0) |
| 516 | ret = -EIO; | 932 | ret = -EIO; |
| @@ -525,30 +941,22 @@ static int tmio_mmc_start_dma_tx(struct tmio_mmc_host *host) | |||
| 525 | dev_warn(&host->pdev->dev, | 941 | dev_warn(&host->pdev->dev, |
| 526 | "DMA failed: %d, falling back to PIO\n", ret); | 942 | "DMA failed: %d, falling back to PIO\n", ret); |
| 527 | tmio_mmc_enable_dma(host, false); | 943 | tmio_mmc_enable_dma(host, false); |
| 528 | reset(host); | ||
| 529 | /* Fail this request, let above layers recover */ | ||
| 530 | host->mrq->cmd->error = ret; | ||
| 531 | tmio_mmc_finish_request(host); | ||
| 532 | } | 944 | } |
| 533 | 945 | ||
| 534 | dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__, | 946 | dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__, |
| 535 | desc, host->cookie); | 947 | desc, cookie); |
| 536 | |||
| 537 | return ret > 0 ? 0 : ret; | ||
| 538 | } | 948 | } |
| 539 | 949 | ||
| 540 | static int tmio_mmc_start_dma(struct tmio_mmc_host *host, | 950 | static void tmio_mmc_start_dma(struct tmio_mmc_host *host, |
| 541 | struct mmc_data *data) | 951 | struct mmc_data *data) |
| 542 | { | 952 | { |
| 543 | if (data->flags & MMC_DATA_READ) { | 953 | if (data->flags & MMC_DATA_READ) { |
| 544 | if (host->chan_rx) | 954 | if (host->chan_rx) |
| 545 | return tmio_mmc_start_dma_rx(host); | 955 | tmio_mmc_start_dma_rx(host); |
| 546 | } else { | 956 | } else { |
| 547 | if (host->chan_tx) | 957 | if (host->chan_tx) |
| 548 | return tmio_mmc_start_dma_tx(host); | 958 | tmio_mmc_start_dma_tx(host); |
| 549 | } | 959 | } |
| 550 | |||
| 551 | return 0; | ||
| 552 | } | 960 | } |
| 553 | 961 | ||
| 554 | static void tmio_issue_tasklet_fn(unsigned long priv) | 962 | static void tmio_issue_tasklet_fn(unsigned long priv) |
| @@ -562,6 +970,12 @@ static void tmio_issue_tasklet_fn(unsigned long priv) | |||
| 562 | static void tmio_tasklet_fn(unsigned long arg) | 970 | static void tmio_tasklet_fn(unsigned long arg) |
| 563 | { | 971 | { |
| 564 | struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg; | 972 | struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg; |
| 973 | unsigned long flags; | ||
| 974 | |||
| 975 | spin_lock_irqsave(&host->lock, flags); | ||
| 976 | |||
| 977 | if (!host->data) | ||
| 978 | goto out; | ||
| 565 | 979 | ||
| 566 | if (host->data->flags & MMC_DATA_READ) | 980 | if (host->data->flags & MMC_DATA_READ) |
| 567 | dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen, | 981 | dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen, |
| @@ -571,6 +985,8 @@ static void tmio_tasklet_fn(unsigned long arg) | |||
| 571 | DMA_TO_DEVICE); | 985 | DMA_TO_DEVICE); |
| 572 | 986 | ||
| 573 | tmio_mmc_do_data_irq(host); | 987 | tmio_mmc_do_data_irq(host); |
| 988 | out: | ||
| 989 | spin_unlock_irqrestore(&host->lock, flags); | ||
| 574 | } | 990 | } |
| 575 | 991 | ||
| 576 | /* It might be necessary to make filter MFD specific */ | 992 | /* It might be necessary to make filter MFD specific */ |
| @@ -584,9 +1000,6 @@ static bool tmio_mmc_filter(struct dma_chan *chan, void *arg) | |||
| 584 | static void tmio_mmc_request_dma(struct tmio_mmc_host *host, | 1000 | static void tmio_mmc_request_dma(struct tmio_mmc_host *host, |
| 585 | struct tmio_mmc_data *pdata) | 1001 | struct tmio_mmc_data *pdata) |
| 586 | { | 1002 | { |
| 587 | host->cookie = -EINVAL; | ||
| 588 | host->desc = NULL; | ||
| 589 | |||
| 590 | /* We can only either use DMA for both Tx and Rx or not use it at all */ | 1003 | /* We can only either use DMA for both Tx and Rx or not use it at all */ |
| 591 | if (pdata->dma) { | 1004 | if (pdata->dma) { |
| 592 | dma_cap_mask_t mask; | 1005 | dma_cap_mask_t mask; |
| @@ -632,15 +1045,15 @@ static void tmio_mmc_release_dma(struct tmio_mmc_host *host) | |||
| 632 | host->chan_rx = NULL; | 1045 | host->chan_rx = NULL; |
| 633 | dma_release_channel(chan); | 1046 | dma_release_channel(chan); |
| 634 | } | 1047 | } |
| 635 | |||
| 636 | host->cookie = -EINVAL; | ||
| 637 | host->desc = NULL; | ||
| 638 | } | 1048 | } |
| 639 | #else | 1049 | #else |
| 640 | static int tmio_mmc_start_dma(struct tmio_mmc_host *host, | 1050 | static void tmio_check_bounce_buffer(struct tmio_mmc_host *host) |
| 1051 | { | ||
| 1052 | } | ||
| 1053 | |||
| 1054 | static void tmio_mmc_start_dma(struct tmio_mmc_host *host, | ||
| 641 | struct mmc_data *data) | 1055 | struct mmc_data *data) |
| 642 | { | 1056 | { |
| 643 | return 0; | ||
| 644 | } | 1057 | } |
| 645 | 1058 | ||
| 646 | static void tmio_mmc_request_dma(struct tmio_mmc_host *host, | 1059 | static void tmio_mmc_request_dma(struct tmio_mmc_host *host, |
| @@ -682,7 +1095,9 @@ static int tmio_mmc_start_data(struct tmio_mmc_host *host, | |||
| 682 | sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); | 1095 | sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz); |
| 683 | sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks); | 1096 | sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks); |
| 684 | 1097 | ||
| 685 | return tmio_mmc_start_dma(host, data); | 1098 | tmio_mmc_start_dma(host, data); |
| 1099 | |||
| 1100 | return 0; | ||
| 686 | } | 1101 | } |
| 687 | 1102 | ||
| 688 | /* Process requests from the MMC layer */ | 1103 | /* Process requests from the MMC layer */ |
| @@ -694,6 +1109,8 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 694 | if (host->mrq) | 1109 | if (host->mrq) |
| 695 | pr_debug("request not null\n"); | 1110 | pr_debug("request not null\n"); |
| 696 | 1111 | ||
| 1112 | host->last_req_ts = jiffies; | ||
| 1113 | wmb(); | ||
| 697 | host->mrq = mrq; | 1114 | host->mrq = mrq; |
| 698 | 1115 | ||
| 699 | if (mrq->data) { | 1116 | if (mrq->data) { |
| @@ -703,10 +1120,14 @@ static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
| 703 | } | 1120 | } |
| 704 | 1121 | ||
| 705 | ret = tmio_mmc_start_command(host, mrq->cmd); | 1122 | ret = tmio_mmc_start_command(host, mrq->cmd); |
| 706 | if (!ret) | 1123 | if (!ret) { |
| 1124 | schedule_delayed_work(&host->delayed_reset_work, | ||
| 1125 | msecs_to_jiffies(2000)); | ||
| 707 | return; | 1126 | return; |
| 1127 | } | ||
| 708 | 1128 | ||
| 709 | fail: | 1129 | fail: |
| 1130 | host->mrq = NULL; | ||
| 710 | mrq->cmd->error = ret; | 1131 | mrq->cmd->error = ret; |
| 711 | mmc_request_done(mmc, mrq); | 1132 | mmc_request_done(mmc, mrq); |
| 712 | } | 1133 | } |
| @@ -780,6 +1201,7 @@ static const struct mmc_host_ops tmio_mmc_ops = { | |||
| 780 | .set_ios = tmio_mmc_set_ios, | 1201 | .set_ios = tmio_mmc_set_ios, |
| 781 | .get_ro = tmio_mmc_get_ro, | 1202 | .get_ro = tmio_mmc_get_ro, |
| 782 | .get_cd = tmio_mmc_get_cd, | 1203 | .get_cd = tmio_mmc_get_cd, |
| 1204 | .enable_sdio_irq = tmio_mmc_enable_sdio_irq, | ||
| 783 | }; | 1205 | }; |
| 784 | 1206 | ||
| 785 | #ifdef CONFIG_PM | 1207 | #ifdef CONFIG_PM |
| @@ -864,10 +1286,15 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) | |||
| 864 | goto host_free; | 1286 | goto host_free; |
| 865 | 1287 | ||
| 866 | mmc->ops = &tmio_mmc_ops; | 1288 | mmc->ops = &tmio_mmc_ops; |
| 867 | mmc->caps = MMC_CAP_4_BIT_DATA; | 1289 | mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities; |
| 868 | mmc->caps |= pdata->capabilities; | ||
| 869 | mmc->f_max = pdata->hclk; | 1290 | mmc->f_max = pdata->hclk; |
| 870 | mmc->f_min = mmc->f_max / 512; | 1291 | mmc->f_min = mmc->f_max / 512; |
| 1292 | mmc->max_segs = 32; | ||
| 1293 | mmc->max_blk_size = 512; | ||
| 1294 | mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) * | ||
| 1295 | mmc->max_segs; | ||
| 1296 | mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; | ||
| 1297 | mmc->max_seg_size = mmc->max_req_size; | ||
| 871 | if (pdata->ocr_mask) | 1298 | if (pdata->ocr_mask) |
| 872 | mmc->ocr_avail = pdata->ocr_mask; | 1299 | mmc->ocr_avail = pdata->ocr_mask; |
| 873 | else | 1300 | else |
| @@ -890,12 +1317,19 @@ static int __devinit tmio_mmc_probe(struct platform_device *dev) | |||
| 890 | goto cell_disable; | 1317 | goto cell_disable; |
| 891 | 1318 | ||
| 892 | disable_mmc_irqs(host, TMIO_MASK_ALL); | 1319 | disable_mmc_irqs(host, TMIO_MASK_ALL); |
| 1320 | if (pdata->flags & TMIO_MMC_SDIO_IRQ) | ||
| 1321 | tmio_mmc_enable_sdio_irq(mmc, 0); | ||
| 893 | 1322 | ||
| 894 | ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | | 1323 | ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED | |
| 895 | IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); | 1324 | IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host); |
| 896 | if (ret) | 1325 | if (ret) |
| 897 | goto cell_disable; | 1326 | goto cell_disable; |
| 898 | 1327 | ||
| 1328 | spin_lock_init(&host->lock); | ||
| 1329 | |||
| 1330 | /* Init delayed work for request timeouts */ | ||
| 1331 | INIT_DELAYED_WORK(&host->delayed_reset_work, tmio_mmc_reset_work); | ||
| 1332 | |||
| 899 | /* See if we also get DMA */ | 1333 | /* See if we also get DMA */ |
| 900 | tmio_mmc_request_dma(host, pdata); | 1334 | tmio_mmc_request_dma(host, pdata); |
| 901 | 1335 | ||
| @@ -934,6 +1368,7 @@ static int __devexit tmio_mmc_remove(struct platform_device *dev) | |||
| 934 | if (mmc) { | 1368 | if (mmc) { |
| 935 | struct tmio_mmc_host *host = mmc_priv(mmc); | 1369 | struct tmio_mmc_host *host = mmc_priv(mmc); |
| 936 | mmc_remove_host(mmc); | 1370 | mmc_remove_host(mmc); |
| 1371 | cancel_delayed_work_sync(&host->delayed_reset_work); | ||
| 937 | tmio_mmc_release_dma(host); | 1372 | tmio_mmc_release_dma(host); |
| 938 | free_irq(host->irq, host); | 1373 | free_irq(host->irq, host); |
| 939 | if (cell->disable) | 1374 | if (cell->disable) |
diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h deleted file mode 100644 index 0fedc78e3ea5..000000000000 --- a/drivers/mmc/host/tmio_mmc.h +++ /dev/null | |||
| @@ -1,228 +0,0 @@ | |||
| 1 | /* Definitons for use with the tmio_mmc.c | ||
| 2 | * | ||
| 3 | * (c) 2004 Ian Molton <spyro@f2s.com> | ||
| 4 | * (c) 2007 Ian Molton <spyro@f2s.com> | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/highmem.h> | ||
| 13 | #include <linux/interrupt.h> | ||
| 14 | #include <linux/dmaengine.h> | ||
| 15 | |||
| 16 | #define CTL_SD_CMD 0x00 | ||
| 17 | #define CTL_ARG_REG 0x04 | ||
| 18 | #define CTL_STOP_INTERNAL_ACTION 0x08 | ||
| 19 | #define CTL_XFER_BLK_COUNT 0xa | ||
| 20 | #define CTL_RESPONSE 0x0c | ||
| 21 | #define CTL_STATUS 0x1c | ||
| 22 | #define CTL_IRQ_MASK 0x20 | ||
| 23 | #define CTL_SD_CARD_CLK_CTL 0x24 | ||
| 24 | #define CTL_SD_XFER_LEN 0x26 | ||
| 25 | #define CTL_SD_MEM_CARD_OPT 0x28 | ||
| 26 | #define CTL_SD_ERROR_DETAIL_STATUS 0x2c | ||
| 27 | #define CTL_SD_DATA_PORT 0x30 | ||
| 28 | #define CTL_TRANSACTION_CTL 0x34 | ||
| 29 | #define CTL_RESET_SD 0xe0 | ||
| 30 | #define CTL_SDIO_REGS 0x100 | ||
| 31 | #define CTL_CLK_AND_WAIT_CTL 0x138 | ||
| 32 | #define CTL_RESET_SDIO 0x1e0 | ||
| 33 | |||
| 34 | /* Definitions for values the CTRL_STATUS register can take. */ | ||
| 35 | #define TMIO_STAT_CMDRESPEND 0x00000001 | ||
| 36 | #define TMIO_STAT_DATAEND 0x00000004 | ||
| 37 | #define TMIO_STAT_CARD_REMOVE 0x00000008 | ||
| 38 | #define TMIO_STAT_CARD_INSERT 0x00000010 | ||
| 39 | #define TMIO_STAT_SIGSTATE 0x00000020 | ||
| 40 | #define TMIO_STAT_WRPROTECT 0x00000080 | ||
| 41 | #define TMIO_STAT_CARD_REMOVE_A 0x00000100 | ||
| 42 | #define TMIO_STAT_CARD_INSERT_A 0x00000200 | ||
| 43 | #define TMIO_STAT_SIGSTATE_A 0x00000400 | ||
| 44 | #define TMIO_STAT_CMD_IDX_ERR 0x00010000 | ||
| 45 | #define TMIO_STAT_CRCFAIL 0x00020000 | ||
| 46 | #define TMIO_STAT_STOPBIT_ERR 0x00040000 | ||
| 47 | #define TMIO_STAT_DATATIMEOUT 0x00080000 | ||
| 48 | #define TMIO_STAT_RXOVERFLOW 0x00100000 | ||
| 49 | #define TMIO_STAT_TXUNDERRUN 0x00200000 | ||
| 50 | #define TMIO_STAT_CMDTIMEOUT 0x00400000 | ||
| 51 | #define TMIO_STAT_RXRDY 0x01000000 | ||
| 52 | #define TMIO_STAT_TXRQ 0x02000000 | ||
| 53 | #define TMIO_STAT_ILL_FUNC 0x20000000 | ||
| 54 | #define TMIO_STAT_CMD_BUSY 0x40000000 | ||
| 55 | #define TMIO_STAT_ILL_ACCESS 0x80000000 | ||
| 56 | |||
| 57 | /* Define some IRQ masks */ | ||
| 58 | /* This is the mask used at reset by the chip */ | ||
| 59 | #define TMIO_MASK_ALL 0x837f031d | ||
| 60 | #define TMIO_MASK_READOP (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND) | ||
| 61 | #define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND) | ||
| 62 | #define TMIO_MASK_CMD (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \ | ||
| 63 | TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT) | ||
| 64 | #define TMIO_MASK_IRQ (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD) | ||
| 65 | |||
| 66 | |||
| 67 | #define enable_mmc_irqs(host, i) \ | ||
| 68 | do { \ | ||
| 69 | u32 mask;\ | ||
| 70 | mask = sd_ctrl_read32((host), CTL_IRQ_MASK); \ | ||
| 71 | mask &= ~((i) & TMIO_MASK_IRQ); \ | ||
| 72 | sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \ | ||
| 73 | } while (0) | ||
| 74 | |||
| 75 | #define disable_mmc_irqs(host, i) \ | ||
| 76 | do { \ | ||
| 77 | u32 mask;\ | ||
| 78 | mask = sd_ctrl_read32((host), CTL_IRQ_MASK); \ | ||
| 79 | mask |= ((i) & TMIO_MASK_IRQ); \ | ||
| 80 | sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \ | ||
| 81 | } while (0) | ||
| 82 | |||
| 83 | #define ack_mmc_irqs(host, i) \ | ||
| 84 | do { \ | ||
| 85 | sd_ctrl_write32((host), CTL_STATUS, ~(i)); \ | ||
| 86 | } while (0) | ||
| 87 | |||
| 88 | |||
| 89 | struct tmio_mmc_host { | ||
| 90 | void __iomem *ctl; | ||
| 91 | unsigned long bus_shift; | ||
| 92 | struct mmc_command *cmd; | ||
| 93 | struct mmc_request *mrq; | ||
| 94 | struct mmc_data *data; | ||
| 95 | struct mmc_host *mmc; | ||
| 96 | int irq; | ||
| 97 | |||
| 98 | /* Callbacks for clock / power control */ | ||
| 99 | void (*set_pwr)(struct platform_device *host, int state); | ||
| 100 | void (*set_clk_div)(struct platform_device *host, int state); | ||
| 101 | |||
| 102 | /* pio related stuff */ | ||
| 103 | struct scatterlist *sg_ptr; | ||
| 104 | unsigned int sg_len; | ||
| 105 | unsigned int sg_off; | ||
| 106 | |||
| 107 | struct platform_device *pdev; | ||
| 108 | |||
| 109 | /* DMA support */ | ||
| 110 | struct dma_chan *chan_rx; | ||
| 111 | struct dma_chan *chan_tx; | ||
| 112 | struct tasklet_struct dma_complete; | ||
| 113 | struct tasklet_struct dma_issue; | ||
| 114 | #ifdef CONFIG_TMIO_MMC_DMA | ||
| 115 | struct dma_async_tx_descriptor *desc; | ||
| 116 | unsigned int dma_sglen; | ||
| 117 | dma_cookie_t cookie; | ||
| 118 | #endif | ||
| 119 | }; | ||
| 120 | |||
| 121 | #include <linux/io.h> | ||
| 122 | |||
| 123 | static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr) | ||
| 124 | { | ||
| 125 | return readw(host->ctl + (addr << host->bus_shift)); | ||
| 126 | } | ||
| 127 | |||
| 128 | static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr, | ||
| 129 | u16 *buf, int count) | ||
| 130 | { | ||
| 131 | readsw(host->ctl + (addr << host->bus_shift), buf, count); | ||
| 132 | } | ||
| 133 | |||
| 134 | static inline u32 sd_ctrl_read32(struct tmio_mmc_host *host, int addr) | ||
| 135 | { | ||
| 136 | return readw(host->ctl + (addr << host->bus_shift)) | | ||
| 137 | readw(host->ctl + ((addr + 2) << host->bus_shift)) << 16; | ||
| 138 | } | ||
| 139 | |||
| 140 | static inline void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, | ||
| 141 | u16 val) | ||
| 142 | { | ||
| 143 | writew(val, host->ctl + (addr << host->bus_shift)); | ||
| 144 | } | ||
| 145 | |||
| 146 | static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr, | ||
| 147 | u16 *buf, int count) | ||
| 148 | { | ||
| 149 | writesw(host->ctl + (addr << host->bus_shift), buf, count); | ||
| 150 | } | ||
| 151 | |||
| 152 | static inline void sd_ctrl_write32(struct tmio_mmc_host *host, int addr, | ||
| 153 | u32 val) | ||
| 154 | { | ||
| 155 | writew(val, host->ctl + (addr << host->bus_shift)); | ||
| 156 | writew(val >> 16, host->ctl + ((addr + 2) << host->bus_shift)); | ||
| 157 | } | ||
| 158 | |||
| 159 | #include <linux/scatterlist.h> | ||
| 160 | #include <linux/blkdev.h> | ||
| 161 | |||
| 162 | static inline void tmio_mmc_init_sg(struct tmio_mmc_host *host, | ||
| 163 | struct mmc_data *data) | ||
| 164 | { | ||
| 165 | host->sg_len = data->sg_len; | ||
| 166 | host->sg_ptr = data->sg; | ||
| 167 | host->sg_off = 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | static inline int tmio_mmc_next_sg(struct tmio_mmc_host *host) | ||
| 171 | { | ||
| 172 | host->sg_ptr = sg_next(host->sg_ptr); | ||
| 173 | host->sg_off = 0; | ||
| 174 | return --host->sg_len; | ||
| 175 | } | ||
| 176 | |||
| 177 | static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg, | ||
| 178 | unsigned long *flags) | ||
| 179 | { | ||
| 180 | local_irq_save(*flags); | ||
| 181 | return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset; | ||
| 182 | } | ||
| 183 | |||
| 184 | static inline void tmio_mmc_kunmap_atomic(void *virt, | ||
| 185 | unsigned long *flags) | ||
| 186 | { | ||
| 187 | kunmap_atomic(virt, KM_BIO_SRC_IRQ); | ||
| 188 | local_irq_restore(*flags); | ||
| 189 | } | ||
| 190 | |||
| 191 | #ifdef CONFIG_MMC_DEBUG | ||
| 192 | |||
| 193 | #define STATUS_TO_TEXT(a) \ | ||
| 194 | do { \ | ||
| 195 | if (status & TMIO_STAT_##a) \ | ||
| 196 | printk(#a); \ | ||
| 197 | } while (0) | ||
| 198 | |||
| 199 | void pr_debug_status(u32 status) | ||
| 200 | { | ||
| 201 | printk(KERN_DEBUG "status: %08x = ", status); | ||
| 202 | STATUS_TO_TEXT(CARD_REMOVE); | ||
| 203 | STATUS_TO_TEXT(CARD_INSERT); | ||
| 204 | STATUS_TO_TEXT(SIGSTATE); | ||
| 205 | STATUS_TO_TEXT(WRPROTECT); | ||
| 206 | STATUS_TO_TEXT(CARD_REMOVE_A); | ||
| 207 | STATUS_TO_TEXT(CARD_INSERT_A); | ||
| 208 | STATUS_TO_TEXT(SIGSTATE_A); | ||
| 209 | STATUS_TO_TEXT(CMD_IDX_ERR); | ||
| 210 | STATUS_TO_TEXT(STOPBIT_ERR); | ||
| 211 | STATUS_TO_TEXT(ILL_FUNC); | ||
| 212 | STATUS_TO_TEXT(CMD_BUSY); | ||
| 213 | STATUS_TO_TEXT(CMDRESPEND); | ||
| 214 | STATUS_TO_TEXT(DATAEND); | ||
| 215 | STATUS_TO_TEXT(CRCFAIL); | ||
| 216 | STATUS_TO_TEXT(DATATIMEOUT); | ||
| 217 | STATUS_TO_TEXT(CMDTIMEOUT); | ||
| 218 | STATUS_TO_TEXT(RXOVERFLOW); | ||
| 219 | STATUS_TO_TEXT(TXUNDERRUN); | ||
| 220 | STATUS_TO_TEXT(RXRDY); | ||
| 221 | STATUS_TO_TEXT(TXRQ); | ||
| 222 | STATUS_TO_TEXT(ILL_ACCESS); | ||
| 223 | printk("\n"); | ||
| 224 | } | ||
| 225 | |||
| 226 | #else | ||
| 227 | #define pr_debug_status(s) do { } while (0) | ||
| 228 | #endif | ||
