diff options
-rw-r--r-- | drivers/mmc/host/sdhci.c | 57 | ||||
-rw-r--r-- | drivers/mmc/host/sdhci.h | 1 | ||||
-rw-r--r-- | include/linux/mmc/sdhci.h | 1 |
3 files changed, 44 insertions, 15 deletions
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index 0636e9a587b1..96f4e548ba22 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -49,7 +49,7 @@ static void sdhci_finish_data(struct sdhci_host *); | |||
49 | 49 | ||
50 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); | 50 | static void sdhci_send_command(struct sdhci_host *, struct mmc_command *); |
51 | static void sdhci_finish_command(struct sdhci_host *); | 51 | static void sdhci_finish_command(struct sdhci_host *); |
52 | static int sdhci_execute_tuning(struct mmc_host *mmc); | 52 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode); |
53 | static void sdhci_tuning_timer(unsigned long data); | 53 | static void sdhci_tuning_timer(unsigned long data); |
54 | 54 | ||
55 | #ifdef CONFIG_PM_RUNTIME | 55 | #ifdef CONFIG_PM_RUNTIME |
@@ -1014,7 +1014,8 @@ static void sdhci_send_command(struct sdhci_host *host, struct mmc_command *cmd) | |||
1014 | flags |= SDHCI_CMD_INDEX; | 1014 | flags |= SDHCI_CMD_INDEX; |
1015 | 1015 | ||
1016 | /* CMD19 is special in that the Data Present Select should be set */ | 1016 | /* CMD19 is special in that the Data Present Select should be set */ |
1017 | if (cmd->data || (cmd->opcode == MMC_SEND_TUNING_BLOCK)) | 1017 | if (cmd->data || cmd->opcode == MMC_SEND_TUNING_BLOCK || |
1018 | cmd->opcode == MMC_SEND_TUNING_BLOCK_HS200) | ||
1018 | flags |= SDHCI_CMD_DATA; | 1019 | flags |= SDHCI_CMD_DATA; |
1019 | 1020 | ||
1020 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); | 1021 | sdhci_writew(host, SDHCI_MAKE_CMD(cmd->opcode, flags), SDHCI_COMMAND); |
@@ -1287,7 +1288,7 @@ static void sdhci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
1287 | if ((host->flags & SDHCI_NEEDS_RETUNING) && | 1288 | if ((host->flags & SDHCI_NEEDS_RETUNING) && |
1288 | !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { | 1289 | !(present_state & (SDHCI_DOING_WRITE | SDHCI_DOING_READ))) { |
1289 | spin_unlock_irqrestore(&host->lock, flags); | 1290 | spin_unlock_irqrestore(&host->lock, flags); |
1290 | sdhci_execute_tuning(mmc); | 1291 | sdhci_execute_tuning(mmc, mrq->cmd->opcode); |
1291 | spin_lock_irqsave(&host->lock, flags); | 1292 | spin_lock_irqsave(&host->lock, flags); |
1292 | 1293 | ||
1293 | /* Restore original mmc_request structure */ | 1294 | /* Restore original mmc_request structure */ |
@@ -1382,7 +1383,8 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1382 | unsigned int clock; | 1383 | unsigned int clock; |
1383 | 1384 | ||
1384 | /* In case of UHS-I modes, set High Speed Enable */ | 1385 | /* In case of UHS-I modes, set High Speed Enable */ |
1385 | if ((ios->timing == MMC_TIMING_UHS_SDR50) || | 1386 | if ((ios->timing == MMC_TIMING_MMC_HS200) || |
1387 | (ios->timing == MMC_TIMING_UHS_SDR50) || | ||
1386 | (ios->timing == MMC_TIMING_UHS_SDR104) || | 1388 | (ios->timing == MMC_TIMING_UHS_SDR104) || |
1387 | (ios->timing == MMC_TIMING_UHS_DDR50) || | 1389 | (ios->timing == MMC_TIMING_UHS_DDR50) || |
1388 | (ios->timing == MMC_TIMING_UHS_SDR25)) | 1390 | (ios->timing == MMC_TIMING_UHS_SDR25)) |
@@ -1435,7 +1437,9 @@ static void sdhci_do_set_ios(struct sdhci_host *host, struct mmc_ios *ios) | |||
1435 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1437 | ctrl_2 = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1436 | /* Select Bus Speed Mode for host */ | 1438 | /* Select Bus Speed Mode for host */ |
1437 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; | 1439 | ctrl_2 &= ~SDHCI_CTRL_UHS_MASK; |
1438 | if (ios->timing == MMC_TIMING_UHS_SDR12) | 1440 | if (ios->timing == MMC_TIMING_MMC_HS200) |
1441 | ctrl_2 |= SDHCI_CTRL_HS_SDR200; | ||
1442 | else if (ios->timing == MMC_TIMING_UHS_SDR12) | ||
1439 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12; | 1443 | ctrl_2 |= SDHCI_CTRL_UHS_SDR12; |
1440 | else if (ios->timing == MMC_TIMING_UHS_SDR25) | 1444 | else if (ios->timing == MMC_TIMING_UHS_SDR25) |
1441 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25; | 1445 | ctrl_2 |= SDHCI_CTRL_UHS_SDR25; |
@@ -1682,7 +1686,7 @@ static int sdhci_start_signal_voltage_switch(struct mmc_host *mmc, | |||
1682 | return err; | 1686 | return err; |
1683 | } | 1687 | } |
1684 | 1688 | ||
1685 | static int sdhci_execute_tuning(struct mmc_host *mmc) | 1689 | static int sdhci_execute_tuning(struct mmc_host *mmc, u32 opcode) |
1686 | { | 1690 | { |
1687 | struct sdhci_host *host; | 1691 | struct sdhci_host *host; |
1688 | u16 ctrl; | 1692 | u16 ctrl; |
@@ -1690,6 +1694,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1690 | int tuning_loop_counter = MAX_TUNING_LOOP; | 1694 | int tuning_loop_counter = MAX_TUNING_LOOP; |
1691 | unsigned long timeout; | 1695 | unsigned long timeout; |
1692 | int err = 0; | 1696 | int err = 0; |
1697 | bool requires_tuning_nonuhs = false; | ||
1693 | 1698 | ||
1694 | host = mmc_priv(mmc); | 1699 | host = mmc_priv(mmc); |
1695 | 1700 | ||
@@ -1700,13 +1705,19 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1700 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); | 1705 | ctrl = sdhci_readw(host, SDHCI_HOST_CONTROL2); |
1701 | 1706 | ||
1702 | /* | 1707 | /* |
1703 | * Host Controller needs tuning only in case of SDR104 mode | 1708 | * The Host Controller needs tuning only in case of SDR104 mode |
1704 | * and for SDR50 mode when Use Tuning for SDR50 is set in | 1709 | * and for SDR50 mode when Use Tuning for SDR50 is set in the |
1705 | * Capabilities register. | 1710 | * Capabilities register. |
1711 | * If the Host Controller supports the HS200 mode then the | ||
1712 | * tuning function has to be executed. | ||
1706 | */ | 1713 | */ |
1714 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | ||
1715 | (host->flags & SDHCI_SDR50_NEEDS_TUNING || | ||
1716 | host->flags & SDHCI_HS200_NEEDS_TUNING)) | ||
1717 | requires_tuning_nonuhs = true; | ||
1718 | |||
1707 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || | 1719 | if (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR104) || |
1708 | (((ctrl & SDHCI_CTRL_UHS_MASK) == SDHCI_CTRL_UHS_SDR50) && | 1720 | requires_tuning_nonuhs) |
1709 | (host->flags & SDHCI_SDR50_NEEDS_TUNING))) | ||
1710 | ctrl |= SDHCI_CTRL_EXEC_TUNING; | 1721 | ctrl |= SDHCI_CTRL_EXEC_TUNING; |
1711 | else { | 1722 | else { |
1712 | spin_unlock(&host->lock); | 1723 | spin_unlock(&host->lock); |
@@ -1742,7 +1753,7 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1742 | if (!tuning_loop_counter && !timeout) | 1753 | if (!tuning_loop_counter && !timeout) |
1743 | break; | 1754 | break; |
1744 | 1755 | ||
1745 | cmd.opcode = MMC_SEND_TUNING_BLOCK; | 1756 | cmd.opcode = opcode; |
1746 | cmd.arg = 0; | 1757 | cmd.arg = 0; |
1747 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; | 1758 | cmd.flags = MMC_RSP_R1 | MMC_CMD_ADTC; |
1748 | cmd.retries = 0; | 1759 | cmd.retries = 0; |
@@ -1757,7 +1768,17 @@ static int sdhci_execute_tuning(struct mmc_host *mmc) | |||
1757 | * block to the Host Controller. So we set the block size | 1768 | * block to the Host Controller. So we set the block size |
1758 | * to 64 here. | 1769 | * to 64 here. |
1759 | */ | 1770 | */ |
1760 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), SDHCI_BLOCK_SIZE); | 1771 | if (cmd.opcode == MMC_SEND_TUNING_BLOCK_HS200) { |
1772 | if (mmc->ios.bus_width == MMC_BUS_WIDTH_8) | ||
1773 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 128), | ||
1774 | SDHCI_BLOCK_SIZE); | ||
1775 | else if (mmc->ios.bus_width == MMC_BUS_WIDTH_4) | ||
1776 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
1777 | SDHCI_BLOCK_SIZE); | ||
1778 | } else { | ||
1779 | sdhci_writew(host, SDHCI_MAKE_BLKSZ(7, 64), | ||
1780 | SDHCI_BLOCK_SIZE); | ||
1781 | } | ||
1761 | 1782 | ||
1762 | /* | 1783 | /* |
1763 | * The tuning block is sent by the card to the host controller. | 1784 | * The tuning block is sent by the card to the host controller. |
@@ -2140,12 +2161,14 @@ static void sdhci_show_adma_error(struct sdhci_host *host) { } | |||
2140 | 2161 | ||
2141 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | 2162 | static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) |
2142 | { | 2163 | { |
2164 | u32 command; | ||
2143 | BUG_ON(intmask == 0); | 2165 | BUG_ON(intmask == 0); |
2144 | 2166 | ||
2145 | /* CMD19 generates _only_ Buffer Read Ready interrupt */ | 2167 | /* CMD19 generates _only_ Buffer Read Ready interrupt */ |
2146 | if (intmask & SDHCI_INT_DATA_AVAIL) { | 2168 | if (intmask & SDHCI_INT_DATA_AVAIL) { |
2147 | if (SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)) == | 2169 | command = SDHCI_GET_CMD(sdhci_readw(host, SDHCI_COMMAND)); |
2148 | MMC_SEND_TUNING_BLOCK) { | 2170 | if (command == MMC_SEND_TUNING_BLOCK || |
2171 | command == MMC_SEND_TUNING_BLOCK_HS200) { | ||
2149 | host->tuning_done = 1; | 2172 | host->tuning_done = 1; |
2150 | wake_up(&host->buf_ready_int); | 2173 | wake_up(&host->buf_ready_int); |
2151 | return; | 2174 | return; |
@@ -2747,10 +2770,14 @@ int sdhci_add_host(struct sdhci_host *host) | |||
2747 | if (caps[1] & SDHCI_SUPPORT_DDR50) | 2770 | if (caps[1] & SDHCI_SUPPORT_DDR50) |
2748 | mmc->caps |= MMC_CAP_UHS_DDR50; | 2771 | mmc->caps |= MMC_CAP_UHS_DDR50; |
2749 | 2772 | ||
2750 | /* Does the host needs tuning for SDR50? */ | 2773 | /* Does the host need tuning for SDR50? */ |
2751 | if (caps[1] & SDHCI_USE_SDR50_TUNING) | 2774 | if (caps[1] & SDHCI_USE_SDR50_TUNING) |
2752 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; | 2775 | host->flags |= SDHCI_SDR50_NEEDS_TUNING; |
2753 | 2776 | ||
2777 | /* Does the host need tuning for HS200? */ | ||
2778 | if (mmc->caps2 & MMC_CAP2_HS200) | ||
2779 | host->flags |= SDHCI_HS200_NEEDS_TUNING; | ||
2780 | |||
2754 | /* Driver Type(s) (A, C, D) supported by the host */ | 2781 | /* Driver Type(s) (A, C, D) supported by the host */ |
2755 | if (caps[1] & SDHCI_DRIVER_TYPE_A) | 2782 | if (caps[1] & SDHCI_DRIVER_TYPE_A) |
2756 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; | 2783 | mmc->caps |= MMC_CAP_DRIVER_TYPE_A; |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index a04d4d0c6fd2..ad265b96b75b 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -158,6 +158,7 @@ | |||
158 | #define SDHCI_CTRL_UHS_SDR50 0x0002 | 158 | #define SDHCI_CTRL_UHS_SDR50 0x0002 |
159 | #define SDHCI_CTRL_UHS_SDR104 0x0003 | 159 | #define SDHCI_CTRL_UHS_SDR104 0x0003 |
160 | #define SDHCI_CTRL_UHS_DDR50 0x0004 | 160 | #define SDHCI_CTRL_UHS_DDR50 0x0004 |
161 | #define SDHCI_CTRL_HS_SDR200 0x0005 /* reserved value in SDIO spec */ | ||
161 | #define SDHCI_CTRL_VDD_180 0x0008 | 162 | #define SDHCI_CTRL_VDD_180 0x0008 |
162 | #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 | 163 | #define SDHCI_CTRL_DRV_TYPE_MASK 0x0030 |
163 | #define SDHCI_CTRL_DRV_TYPE_B 0x0000 | 164 | #define SDHCI_CTRL_DRV_TYPE_B 0x0000 |
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h index dad7a469f09c..c750f85177d9 100644 --- a/include/linux/mmc/sdhci.h +++ b/include/linux/mmc/sdhci.h | |||
@@ -119,6 +119,7 @@ struct sdhci_host { | |||
119 | #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ | 119 | #define SDHCI_AUTO_CMD23 (1<<7) /* Auto CMD23 support */ |
120 | #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ | 120 | #define SDHCI_PV_ENABLED (1<<8) /* Preset value enabled */ |
121 | #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ | 121 | #define SDHCI_SDIO_IRQ_ENABLED (1<<9) /* SDIO irq enabled */ |
122 | #define SDHCI_HS200_NEEDS_TUNING (1<<10) /* HS200 needs tuning */ | ||
122 | 123 | ||
123 | unsigned int version; /* SDHCI spec. version */ | 124 | unsigned int version; /* SDHCI spec. version */ |
124 | 125 | ||