diff options
-rw-r--r-- | drivers/mmc/core/sd.c | 6 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.c | 168 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 3 | ||||
-rw-r--r-- | include/linux/mmc/host.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/mmc.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/sdhci.h | 4 |
6 files changed, 182 insertions, 1 deletions
diff --git a/drivers/mmc/core/sd.c b/drivers/mmc/core/sd.c index 732c3171ceca..fc65475a26ee 100644 --- a/drivers/mmc/core/sd.c +++ b/drivers/mmc/core/sd.c | |||
@@ -618,6 +618,12 @@ static int mmc_sd_init_uhs_card(struct mmc_card *card) | |||
618 | 618 | ||
619 | /* Set current limit for the card */ | 619 | /* Set current limit for the card */ |
620 | err = sd_set_current_limit(card, status); | 620 | err = sd_set_current_limit(card, status); |
621 | if (err) | ||
622 | goto out; | ||
623 | |||
624 | /* SPI mode doesn't define CMD19 */ | ||
625 | if (!mmc_host_is_spi(card->host) && card->host->ops->execute_tuning) | ||
626 | err = card->host->ops->execute_tuning(card->host); | ||
621 | 627 | ||
622 | out: | 628 | out: |
623 | kfree(status); | 629 | kfree(status); |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 2a15aad2eba5..8a56eacea34d 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -38,6 +38,8 @@ | |||
38 | #define SDHCI_USE_LEDS_CLASS | 38 | #define SDHCI_USE_LEDS_CLASS |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | #define MAX_TUNING_LOOP 40 | ||
42 | |||
41 | static unsigned int debug_quirks = 0; | 43 | static unsigned int debug_quirks = 0; |
42 | 44 | ||
43 | static void sdhci_finish_data(struct sdhci_host *); | 45 | static void sdhci_finish_data(struct sdhci_host *); |
@@ -968,7 +970,9 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
968 | flags |= SDHCI_CMD_CRC; | 970 | flags |= SDHCI_CMD_CRC; |
969 | if (cmd->flags & MMC_RSP_OPCODE) | 971 | if (cmd->flags & MMC_RSP_OPCODE) |
970 | flags |= SDHCI_CMD_INDEX; | 972 | flags |= SDHCI_CMD_INDEX; |
971 | if (cmd->data) | 973 | |
974 | /* CMD19 is special in that the Data Present Select should be set */ | ||
975 | if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) | ||
972 | flags |= SDHCI_CMD_DATA; | 976 | flags |= SDHCI_CMD_DATA; |
973 | 977 | ||
974 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); | 978 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); |
@@ -1501,12 +1505,157 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, | |||
1501 | return 0; | 1505 | return 0; |
1502 | } | 1506 | } |
1503 | 1507 | ||
1508 | static int sdhci_execute_tuning(struct mmc_host *mmc) | ||
1509 | { | ||
1510 | struct sdhci_host *host; | ||
1511 | u16 ctrl; | ||
1512 | u32 ier; | ||
1513 | int tuning_loop_counter = MAX_TUNING_LOOP; | ||
1514 | unsigned long timeout; | ||
1515 | int err = 0; | ||
1516 | |||
1517 | host = mmc_priv(mmc); | ||
1518 | |||
1519 | disable_irq(host->irq); | ||
1520 | spin_lock(&host->lock); | ||
1521 | |||
1522 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1523 | |||
1524 | /* | ||
1525 | * Host Controller needs tuning only in case of SDR104 mode | ||
1526 | * and for SDR50 mode when Use Tuning for SDR50 is set in | ||
1527 | * Capabilities register. | ||
1528 | */ | ||
1529 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || | ||
1530 | (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | ||
1531 | (host->flags & SDHCI_SDR50_NEEDS_TUNING))) | ||
1532 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | ||
1533 | else { | ||
1534 | spin_unlock(&host->lock); | ||
1535 | enable_irq(host->irq); | ||
1536 | return 0; | ||
1537 | } | ||
1538 | |||
1539 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1540 | |||
1541 | /* | ||
1542 | * As per the Host Controller spec v3.00, tuning command | ||
1543 | * generates Buffer Read Ready interrupt, so enable that. | ||
1544 | * | ||
1545 | * Note: The spec clearly says that when tuning sequence | ||
1546 | * is being performed, the controller does not generate | ||
1547 | * interrupts other than Buffer Read Ready interrupt. But | ||
1548 | * to make sure we don't hit a controller bug, we _only_ | ||
1549 | * enable Buffer Read Ready interrupt here. | ||
1550 | */ | ||
1551 | ier = sdhci_readl(host, SDHCI_INT_ENABLE); | ||
1552 | sdhci_clear_set_irqs(host, ier, SDHCI_INT_DATA_AVAIL); | ||
1553 | |||
1554 | /* | ||
1555 | * Issue CMD19 repeatedly till Execute Tuning is set to 0 or the number | ||
1556 | * of loops reaches 40 times or a timeout of 150ms occurs. | ||
1557 | */ | ||
1558 | timeout = 150; | ||
1559 | do { | ||
1560 | struct mmc_command cmd = {0}; | ||
1561 | struct mmc_request mrq = {0}; | ||
1562 | |||
1563 | if (!tuning_loop_counter && !timeout) | ||
1564 | break; | ||
1565 | |||
1566 | cmd.opcode = MMC_SEND_TUNING_BLOCK; | ||
1567 | cmd.arg = 0; | ||
1568 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | ||
1569 | cmd.retries = 0; | ||
1570 | cmd.data = NULL; | ||
1571 | cmd.error = 0; | ||
1572 | |||
1573 | mrq.cmd = &cmd; | ||
1574 | host->mrq = &mrq; | ||
1575 | |||
1576 | /* | ||
1577 | * In response to CMD19, the card sends 64 bytes of tuning | ||
1578 | * block to the Host Controller. So we set the block size | ||
1579 | * to 64 here. | ||
1580 | */ | ||
1581 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); | ||
1582 | |||
1583 | /* | ||
1584 | * The tuning block is sent by the card to the host controller. | ||
1585 | * So we set the TRNS_READ bit in the Transfer Mode register. | ||
1586 | * This also takes care of setting DMA Enable and Multi Block | ||
1587 | * Select in the same register to 0. | ||
1588 | */ | ||
1589 | sdhci_writew(host, SDHCI_TRNS_READ, SDHCI_TRANSFER_MODE); | ||
1590 | |||
1591 | sdhci_send_command(host, &cmd); | ||
1592 | |||
1593 | host->cmd = NULL; | ||
1594 | host->mrq = NULL; | ||
1595 | |||
1596 | spin_unlock(&host->lock); | ||
1597 | enable_irq(host->irq); | ||
1598 | |||
1599 | /* Wait for Buffer Read Ready interrupt */ | ||
1600 | wait_event_interruptible_timeout(host->buf_ready_int, | ||
1601 | (host->tuning_done == 1), | ||
1602 | msecs_to_jiffies(50)); | ||
1603 | disable_irq(host->irq); | ||
1604 | spin_lock(&host->lock); | ||
1605 | |||
1606 | if (!host->tuning_done) { | ||
1607 | printk(KERN_INFO DRIVER_NAME ": Timeout waiting for " | ||
1608 | "Buffer Read Ready interrupt during tuning " | ||
1609 | "procedure, falling back to fixed sampling " | ||
1610 | "clock\n"); | ||
1611 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1612 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | ||
1613 | ctrl &= ~SDHCI_CTRL_EXEC_TUNING; | ||
1614 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1615 | |||
1616 | err = -EIO; | ||
1617 | goto out; | ||
1618 | } | ||
1619 | |||
1620 | host->tuning_done = 0; | ||
1621 | |||
1622 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | ||
1623 | tuning_loop_counter--; | ||
1624 | timeout--; | ||
1625 | mdelay(1); | ||
1626 | } while (ctrl & SDHCI_CTRL_EXEC_TUNING); | ||
1627 | |||
1628 | /* | ||
1629 | * The Host Driver has exhausted the maximum number of loops allowed, | ||
1630 | * so use fixed sampling frequency. | ||
1631 | */ | ||
1632 | if (!tuning_loop_counter || !timeout) { | ||
1633 | ctrl &= ~SDHCI_CTRL_TUNED_CLK; | ||
1634 | sdhci_writew(host, ctrl, SDHCI_HOST_CONTROL2); | ||
1635 | } else { | ||
1636 | if (!(ctrl & SDHCI_CTRL_TUNED_CLK)) { | ||
1637 | printk(KERN_INFO DRIVER_NAME ": Tuning procedure" | ||
1638 | " failed, falling back to fixed sampling" | ||
1639 | " clock\n"); | ||
1640 | err = -EIO; | ||
1641 | } | ||
1642 | } | ||
1643 | |||
1644 | out: | ||
1645 | sdhci_clear_set_irqs(host, SDHCI_INT_DATA_AVAIL, ier); | ||
1646 | spin_unlock(&host->lock); | ||
1647 | enable_irq(host->irq); | ||
1648 | |||
1649 | return err; | ||
1650 | } | ||
1651 | |||
1504 | static const struct mmc_host_ops sdhci_ops = { | 1652 | static const struct mmc_host_ops sdhci_ops = { |
1505 | .request = sdhci_request, | 1653 | .request = sdhci_request, |
1506 | .set_ios = sdhci_set_ios, | 1654 | .set_ios = sdhci_set_ios, |
1507 | .get_ro = sdhci_get_ro, | 1655 | .get_ro = sdhci_get_ro, |
1508 | .enable_sdio_irq = sdhci_enable_sdio_irq, | 1656 | .enable_sdio_irq = sdhci_enable_sdio_irq, |
1509 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, | 1657 | .start_signal_voltage_switch = sdhci_start_signal_voltage_switch, |
1658 | .execute_tuning = sdhci_execute_tuning, | ||
1510 | }; | 1659 | }; |
1511 | 1660 | ||
1512 | /*****************************************************************************\ | 1661 | /*****************************************************************************\ |
@@ -1724,6 +1873,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1724 | { | 1873 | { |
1725 | BUG_ON(intmask == 0); | 1874 | BUG_ON(intmask == 0); |
1726 | 1875 | ||
1876 | /* CMD19 generates _only_ Buffer Read Ready interrupt */ | ||
1877 | if (intmask & SDHCI_INT_DATA_AVAIL) { | ||
1878 | if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == | ||
1879 | MMC_SEND_TUNING_BLOCK) { | ||
1880 | host->tuning_done = 1; | ||
1881 | wake_up(&host->buf_ready_int); | ||
1882 | return; | ||
1883 | } | ||
1884 | } | ||
1885 | |||
1727 | if (!host->data) { | 1886 | if (!host->data) { |
1728 | /* | 1887 | /* |
1729 | * The "data complete" interrupt is also used to | 1888 | * The "data complete" interrupt is also used to |
@@ -2160,6 +2319,10 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2160 | if (caps[1] & SDHCI_SUPPORT_DDR50) | 2319 | if (caps[1] & SDHCI_SUPPORT_DDR50) |
2161 | mmc->caps |= MMC_CAP_UHS_DDR50; | 2320 | mmc->caps |= MMC_CAP_UHS_DDR50; |
2162 | 2321 | ||
2322 | /* Does the host needs tuning for SDR50? */ | ||
2323 | if (caps[1] & SDHCI_USE_SDR50_TUNING) | ||
2324 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; | ||
2325 | |||
2163 | /* Driver Type(s) (A, C, D) supported by the host */ | 2326 | /* Driver Type(s) (A, C, D) supported by the host */ |
2164 | if (caps[1] & SDHCI_DRIVER_TYPE_A) | 2327 | if (caps[1] & SDHCI_DRIVER_TYPE_A) |
2165 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; | 2328 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; |
@@ -2313,6 +2476,9 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2313 | 2476 | ||
2314 | setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); | 2477 | setup_timer(&host->timer, sdhci_timeout_timer, (unsigned long)host); |
2315 | 2478 | ||
2479 | if (host->version >= SDHCI_SPEC_300) | ||
2480 | init_waitqueue_head(&host->buf_ready_int); | ||
2481 | |||
2316 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, | 2482 | ret = request_irq(host->irq, sdhci_irq, IRQF_SHARED, |
2317 | mmc_hostname(mmc), host); | 2483 | mmc_hostname(mmc), host); |
2318 | if (ret) | 2484 | if (ret) |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index d96f6afcca1f..e62367491eee 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -161,6 +161,8 @@ | |||
161 | #define SDHCI_CTRL_DRV_TYPE_A 0x0010 | 161 | #define SDHCI_CTRL_DRV_TYPE_A 0x0010 |
162 | #define SDHCI_CTRL_DRV_TYPE_C 0x0020 | 162 | #define SDHCI_CTRL_DRV_TYPE_C 0x0020 |
163 | #define SDHCI_CTRL_DRV_TYPE_D 0x0030 | 163 | #define SDHCI_CTRL_DRV_TYPE_D 0x0030 |
164 | #define SDHCI_CTRL_EXEC_TUNING 0x0040 | ||
165 | #define SDHCI_CTRL_TUNED_CLK 0x0080 | ||
164 | #define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 | 166 | #define SDHCI_CTRL_PRESET_VAL_ENABLE 0x8000 |
165 | 167 | ||
166 | #define SDHCI_CAPABILITIES 0x40 | 168 | #define SDHCI_CAPABILITIES 0x40 |
@@ -188,6 +190,7 @@ | |||
188 | #define SDHCI_DRIVER_TYPE_A 0x00000010 | 190 | #define SDHCI_DRIVER_TYPE_A 0x00000010 |
189 | #define SDHCI_DRIVER_TYPE_C 0x00000020 | 191 | #define SDHCI_DRIVER_TYPE_C 0x00000020 |
190 | #define SDHCI_DRIVER_TYPE_D 0x00000040 | 192 | #define SDHCI_DRIVER_TYPE_D 0x00000040 |
193 | #define SDHCI_USE_SDR50_TUNING 0x00002000 | ||
191 | 194 | ||
192 | #define SDHCI_CAPABILITIES_1 0x44 | 195 | #define SDHCI_CAPABILITIES_1 0x44 |
193 | 196 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 52b5dc914a8c..ca7007fdb399 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -136,6 +136,7 @@ struct mmc_host_ops { | |||
136 | void (*init_card)(struct mmc_host *host, struct mmc_card *card); | 136 | void (*init_card)(struct mmc_host *host, struct mmc_card *card); |
137 | 137 | ||
138 | int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios); | 138 | int (*start_signal_voltage_switch)(struct mmc_host *host, struct mmc_ios *ios); |
139 | int (*execute_tuning)(struct mmc_host *host); | ||
139 | }; | 140 | }; |
140 | 141 | ||
141 | struct mmc_card; | 142 | struct mmc_card; |
diff --git a/include/linux/mmc/mmc.h b/include/linux/mmc/mmc.h index 373b2bf5e5b5..9fa5a73f393d 100644 --- a/include/linux/mmc/mmc.h +++ b/include/linux/mmc/mmc.h | |||
@@ -50,6 +50,7 @@ | |||
50 | #define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ | 50 | #define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */ |
51 | #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ | 51 | #define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */ |
52 | #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ | 52 | #define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */ |
53 | #define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */ | ||
53 | 54 | ||
54 | /* class 3 */ | 55 | /* class 3 */ |
55 | #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ | 56 | #define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */ |
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index 92e1c9ad126c..b74c8530e959 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
@@ -111,6 +111,7 @@ struct sdhci_host { | |||
111 | #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ | 111 | #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ |
112 | #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ | 112 | #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ |
113 | #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ | 113 | #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ |
114 | #define SDHCI_SDR50_NEEDS_TUNING (1<<4) /* SDR50 needs tuning */ | ||
114 | 115 | ||
115 | unsigned int version; /* SDHCI spec. version */ | 116 | unsigned int version; /* SDHCI spec. version */ |
116 | 117 | ||
@@ -147,6 +148,9 @@ struct sdhci_host { | |||
147 | unsigned int ocr_avail_sd; | 148 | unsigned int ocr_avail_sd; |
148 | unsigned int ocr_avail_mmc; | 149 | unsigned int ocr_avail_mmc; |
149 | 150 | ||
151 | wait_queue_head_t buf_ready_int; /* Waitqueue for Buffer Read Ready interrupt */ | ||
152 | unsigned int tuning_done; /* Condition flag set when CMD19 succeeds */ | ||
153 | |||
150 | unsigned long private[0] ____cacheline_aligned; | 154 | unsigned long private[0] ____cacheline_aligned; |
151 | }; | 155 | }; |
152 | #endif /* __SDHCI_H */ | 156 | #endif /* __SDHCI_H */ |