diff options
author | Doug Anderson <dianders@chromium.org> | 2014-08-22 09:47:51 -0400 |
---|---|---|
committer | Ulf Hansson <ulf.hansson@linaro.org> | 2014-09-09 07:59:18 -0400 |
commit | 0173055842cd1d9ed3984e70891c22dbf2f29372 (patch) | |
tree | d3f35f45b4a78e36b5426d49baadebc79401fb01 /drivers/mmc/host/dw_mmc.c | |
parent | 51da2240906cb94e8f6ba55e403b6206df6fb2dd (diff) |
mmc: dw_mmc: Support voltage changes
For UHS cards we need the ability to switch voltages from 3.3V to
1.8V. Add support to the dw_mmc driver to handle this. Note that
dw_mmc needs a little bit of extra code since the interface needs a
special bit programmed to the CMD register while CMD11 is progressing.
This means adding a few extra states to the state machine to track.
Signed-off-by: Doug Anderson <dianders@chromium.org>
Signed-off-by: Yuvaraj Kumar C D <yuvaraj.cd@samsung.com>
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
Diffstat (limited to 'drivers/mmc/host/dw_mmc.c')
-rw-r--r-- | drivers/mmc/host/dw_mmc.c | 137 |
1 files changed, 128 insertions, 9 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c index aadb0d6aa63f..23719249182b 100644 --- a/drivers/mmc/host/dw_mmc.c +++ b/drivers/mmc/host/dw_mmc.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/irq.h> | 29 | #include <linux/irq.h> |
30 | #include <linux/mmc/host.h> | 30 | #include <linux/mmc/host.h> |
31 | #include <linux/mmc/mmc.h> | 31 | #include <linux/mmc/mmc.h> |
32 | #include <linux/mmc/sd.h> | ||
32 | #include <linux/mmc/sdio.h> | 33 | #include <linux/mmc/sdio.h> |
33 | #include <linux/mmc/dw_mmc.h> | 34 | #include <linux/mmc/dw_mmc.h> |
34 | #include <linux/bitops.h> | 35 | #include <linux/bitops.h> |
@@ -234,10 +235,13 @@ err: | |||
234 | } | 235 | } |
235 | #endif /* defined(CONFIG_DEBUG_FS) */ | 236 | #endif /* defined(CONFIG_DEBUG_FS) */ |
236 | 237 | ||
238 | static void mci_send_cmd(struct dw_mci_slot *slot, u32 cmd, u32 arg); | ||
239 | |||
237 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | 240 | static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) |
238 | { | 241 | { |
239 | struct mmc_data *data; | 242 | struct mmc_data *data; |
240 | struct dw_mci_slot *slot = mmc_priv(mmc); | 243 | struct dw_mci_slot *slot = mmc_priv(mmc); |
244 | struct dw_mci *host = slot->host; | ||
241 | const struct dw_mci_drv_data *drv_data = slot->host->drv_data; | 245 | const struct dw_mci_drv_data *drv_data = slot->host->drv_data; |
242 | u32 cmdr; | 246 | u32 cmdr; |
243 | cmd->error = -EINPROGRESS; | 247 | cmd->error = -EINPROGRESS; |
@@ -253,6 +257,34 @@ static u32 dw_mci_prepare_command(struct mmc_host *mmc, struct mmc_command *cmd) | |||
253 | else if (cmd->opcode != MMC_SEND_STATUS && cmd->data) | 257 | else if (cmd->opcode != MMC_SEND_STATUS && cmd->data) |
254 | cmdr |= SDMMC_CMD_PRV_DAT_WAIT; | 258 | cmdr |= SDMMC_CMD_PRV_DAT_WAIT; |
255 | 259 | ||
260 | if (cmd->opcode == SD_SWITCH_VOLTAGE) { | ||
261 | u32 clk_en_a; | ||
262 | |||
263 | /* Special bit makes CMD11 not die */ | ||
264 | cmdr |= SDMMC_CMD_VOLT_SWITCH; | ||
265 | |||
266 | /* Change state to continue to handle CMD11 weirdness */ | ||
267 | WARN_ON(slot->host->state != STATE_SENDING_CMD); | ||
268 | slot->host->state = STATE_SENDING_CMD11; | ||
269 | |||
270 | /* | ||
271 | * We need to disable low power mode (automatic clock stop) | ||
272 | * while doing voltage switch so we don't confuse the card, | ||
273 | * since stopping the clock is a specific part of the UHS | ||
274 | * voltage change dance. | ||
275 | * | ||
276 | * Note that low power mode (SDMMC_CLKEN_LOW_PWR) will be | ||
277 | * unconditionally turned back on in dw_mci_setup_bus() if it's | ||
278 | * ever called with a non-zero clock. That shouldn't happen | ||
279 | * until the voltage change is all done. | ||
280 | */ | ||
281 | clk_en_a = mci_readl(host, CLKENA); | ||
282 | clk_en_a &= ~(SDMMC_CLKEN_LOW_PWR << slot->id); | ||
283 | mci_writel(host, CLKENA, clk_en_a); | ||
284 | mci_send_cmd(slot, SDMMC_CMD_UPD_CLK | | ||
285 | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
286 | } | ||
287 | |||
256 | if (cmd->flags & MMC_RSP_PRESENT) { | 288 | if (cmd->flags & MMC_RSP_PRESENT) { |
257 | /* We expect a response, so set this bit */ | 289 | /* We expect a response, so set this bit */ |
258 | cmdr |= SDMMC_CMD_RESP_EXP; | 290 | cmdr |= SDMMC_CMD_RESP_EXP; |
@@ -775,11 +807,15 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) | |||
775 | unsigned int clock = slot->clock; | 807 | unsigned int clock = slot->clock; |
776 | u32 div; | 808 | u32 div; |
777 | u32 clk_en_a; | 809 | u32 clk_en_a; |
810 | u32 sdmmc_cmd_bits = SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT; | ||
811 | |||
812 | /* We must continue to set bit 28 in CMD until the change is complete */ | ||
813 | if (host->state == STATE_WAITING_CMD11_DONE) | ||
814 | sdmmc_cmd_bits |= SDMMC_CMD_VOLT_SWITCH; | ||
778 | 815 | ||
779 | if (!clock) { | 816 | if (!clock) { |
780 | mci_writel(host, CLKENA, 0); | 817 | mci_writel(host, CLKENA, 0); |
781 | mci_send_cmd(slot, | 818 | mci_send_cmd(slot, sdmmc_cmd_bits, 0); |
782 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
783 | } else if (clock != host->current_speed || force_clkinit) { | 819 | } else if (clock != host->current_speed || force_clkinit) { |
784 | div = host->bus_hz / clock; | 820 | div = host->bus_hz / clock; |
785 | if (host->bus_hz % clock && host->bus_hz > clock) | 821 | if (host->bus_hz % clock && host->bus_hz > clock) |
@@ -803,15 +839,13 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) | |||
803 | mci_writel(host, CLKSRC, 0); | 839 | mci_writel(host, CLKSRC, 0); |
804 | 840 | ||
805 | /* inform CIU */ | 841 | /* inform CIU */ |
806 | mci_send_cmd(slot, | 842 | mci_send_cmd(slot, sdmmc_cmd_bits, 0); |
807 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
808 | 843 | ||
809 | /* set clock to desired speed */ | 844 | /* set clock to desired speed */ |
810 | mci_writel(host, CLKDIV, div); | 845 | mci_writel(host, CLKDIV, div); |
811 | 846 | ||
812 | /* inform CIU */ | 847 | /* inform CIU */ |
813 | mci_send_cmd(slot, | 848 | mci_send_cmd(slot, sdmmc_cmd_bits, 0); |
814 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
815 | 849 | ||
816 | /* enable clock; only low power if no SDIO */ | 850 | /* enable clock; only low power if no SDIO */ |
817 | clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; | 851 | clk_en_a = SDMMC_CLKEN_ENABLE << slot->id; |
@@ -820,8 +854,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot, bool force_clkinit) | |||
820 | mci_writel(host, CLKENA, clk_en_a); | 854 | mci_writel(host, CLKENA, clk_en_a); |
821 | 855 | ||
822 | /* inform CIU */ | 856 | /* inform CIU */ |
823 | mci_send_cmd(slot, | 857 | mci_send_cmd(slot, sdmmc_cmd_bits, 0); |
824 | SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0); | ||
825 | 858 | ||
826 | /* keep the clock with reflecting clock dividor */ | 859 | /* keep the clock with reflecting clock dividor */ |
827 | slot->__clk_old = clock << div; | 860 | slot->__clk_old = clock << div; |
@@ -897,6 +930,17 @@ static void dw_mci_queue_request(struct dw_mci *host, struct dw_mci_slot *slot, | |||
897 | 930 | ||
898 | slot->mrq = mrq; | 931 | slot->mrq = mrq; |
899 | 932 | ||
933 | if (host->state == STATE_WAITING_CMD11_DONE) { | ||
934 | dev_warn(&slot->mmc->class_dev, | ||
935 | "Voltage change didn't complete\n"); | ||
936 | /* | ||
937 | * this case isn't expected to happen, so we can | ||
938 | * either crash here or just try to continue on | ||
939 | * in the closest possible state | ||
940 | */ | ||
941 | host->state = STATE_IDLE; | ||
942 | } | ||
943 | |||
900 | if (host->state == STATE_IDLE) { | 944 | if (host->state == STATE_IDLE) { |
901 | host->state = STATE_SENDING_CMD; | 945 | host->state = STATE_SENDING_CMD; |
902 | dw_mci_start_request(host, slot); | 946 | dw_mci_start_request(host, slot); |
@@ -973,6 +1017,9 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
973 | /* Slot specific timing and width adjustment */ | 1017 | /* Slot specific timing and width adjustment */ |
974 | dw_mci_setup_bus(slot, false); | 1018 | dw_mci_setup_bus(slot, false); |
975 | 1019 | ||
1020 | if (slot->host->state == STATE_WAITING_CMD11_DONE && ios->clock != 0) | ||
1021 | slot->host->state = STATE_IDLE; | ||
1022 | |||
976 | switch (ios->power_mode) { | 1023 | switch (ios->power_mode) { |
977 | case MMC_POWER_UP: | 1024 | case MMC_POWER_UP: |
978 | if (!IS_ERR(mmc->supply.vmmc)) { | 1025 | if (!IS_ERR(mmc->supply.vmmc)) { |
@@ -1016,6 +1063,59 @@ static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1016 | } | 1063 | } |
1017 | } | 1064 | } |
1018 | 1065 | ||
1066 | static int dw_mci_card_busy(struct mmc_host *mmc) | ||
1067 | { | ||
1068 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
1069 | u32 status; | ||
1070 | |||
1071 | /* | ||
1072 | * Check the busy bit which is low when DAT[3:0] | ||
1073 | * (the data lines) are 0000 | ||
1074 | */ | ||
1075 | status = mci_readl(slot->host, STATUS); | ||
1076 | |||
1077 | return !!(status & SDMMC_STATUS_BUSY); | ||
1078 | } | ||
1079 | |||
1080 | static int dw_mci_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | ||
1081 | { | ||
1082 | struct dw_mci_slot *slot = mmc_priv(mmc); | ||
1083 | struct dw_mci *host = slot->host; | ||
1084 | u32 uhs; | ||
1085 | u32 v18 = SDMMC_UHS_18V << slot->id; | ||
1086 | int min_uv, max_uv; | ||
1087 | int ret; | ||
1088 | |||
1089 | /* | ||
1090 | * Program the voltage. Note that some instances of dw_mmc may use | ||
1091 | * the UHS_REG for this. For other instances (like exynos) the UHS_REG | ||
1092 | * does no harm but you need to set the regulator directly. Try both. | ||
1093 | */ | ||
1094 | uhs = mci_readl(host, UHS_REG); | ||
1095 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) { | ||
1096 | min_uv = 2700000; | ||
1097 | max_uv = 3600000; | ||
1098 | uhs &= ~v18; | ||
1099 | } else { | ||
1100 | min_uv = 1700000; | ||
1101 | max_uv = 1950000; | ||
1102 | uhs |= v18; | ||
1103 | } | ||
1104 | if (!IS_ERR(mmc->supply.vqmmc)) { | ||
1105 | ret = regulator_set_voltage(mmc->supply.vqmmc, min_uv, max_uv); | ||
1106 | |||
1107 | if (ret) { | ||
1108 | dev_err(&mmc->class_dev, | ||
1109 | "Regulator set error %d: %d - %d\n", | ||
1110 | ret, min_uv, max_uv); | ||
1111 | return ret; | ||
1112 | } | ||
1113 | } | ||
1114 | mci_writel(host, UHS_REG, uhs); | ||
1115 | |||
1116 | return 0; | ||
1117 | } | ||
1118 | |||
1019 | static int dw_mci_get_ro(struct mmc_host *mmc) | 1119 | static int dw_mci_get_ro(struct mmc_host *mmc) |
1020 | { | 1120 | { |
1021 | int read_only; | 1121 | int read_only; |
@@ -1158,6 +1258,9 @@ static const struct mmc_host_ops dw_mci_ops = { | |||
1158 | .get_cd = dw_mci_get_cd, | 1258 | .get_cd = dw_mci_get_cd, |
1159 | .enable_sdio_irq = dw_mci_enable_sdio_irq, | 1259 | .enable_sdio_irq = dw_mci_enable_sdio_irq, |
1160 | .execute_tuning = dw_mci_execute_tuning, | 1260 | .execute_tuning = dw_mci_execute_tuning, |
1261 | .card_busy = dw_mci_card_busy, | ||
1262 | .start_signal_voltage_switch = dw_mci_switch_voltage, | ||
1263 | |||
1161 | }; | 1264 | }; |
1162 | 1265 | ||
1163 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | 1266 | static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) |
@@ -1181,7 +1284,11 @@ static void dw_mci_request_end(struct dw_mci *host, struct mmc_request *mrq) | |||
1181 | dw_mci_start_request(host, slot); | 1284 | dw_mci_start_request(host, slot); |
1182 | } else { | 1285 | } else { |
1183 | dev_vdbg(host->dev, "list empty\n"); | 1286 | dev_vdbg(host->dev, "list empty\n"); |
1184 | host->state = STATE_IDLE; | 1287 | |
1288 | if (host->state == STATE_SENDING_CMD11) | ||
1289 | host->state = STATE_WAITING_CMD11_DONE; | ||
1290 | else | ||
1291 | host->state = STATE_IDLE; | ||
1185 | } | 1292 | } |
1186 | 1293 | ||
1187 | spin_unlock(&host->lock); | 1294 | spin_unlock(&host->lock); |
@@ -1292,8 +1399,10 @@ static void dw_mci_tasklet_func(unsigned long priv) | |||
1292 | 1399 | ||
1293 | switch (state) { | 1400 | switch (state) { |
1294 | case STATE_IDLE: | 1401 | case STATE_IDLE: |
1402 | case STATE_WAITING_CMD11_DONE: | ||
1295 | break; | 1403 | break; |
1296 | 1404 | ||
1405 | case STATE_SENDING_CMD11: | ||
1297 | case STATE_SENDING_CMD: | 1406 | case STATE_SENDING_CMD: |
1298 | if (!test_and_clear_bit(EVENT_CMD_COMPLETE, | 1407 | if (!test_and_clear_bit(EVENT_CMD_COMPLETE, |
1299 | &host->pending_events)) | 1408 | &host->pending_events)) |
@@ -1894,6 +2003,14 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id) | |||
1894 | } | 2003 | } |
1895 | 2004 | ||
1896 | if (pending) { | 2005 | if (pending) { |
2006 | /* Check volt switch first, since it can look like an error */ | ||
2007 | if ((host->state == STATE_SENDING_CMD11) && | ||
2008 | (pending & SDMMC_INT_VOLT_SWITCH)) { | ||
2009 | mci_writel(host, RINTSTS, SDMMC_INT_VOLT_SWITCH); | ||
2010 | pending &= ~SDMMC_INT_VOLT_SWITCH; | ||
2011 | dw_mci_cmd_interrupt(host, pending); | ||
2012 | } | ||
2013 | |||
1897 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { | 2014 | if (pending & DW_MCI_CMD_ERROR_FLAGS) { |
1898 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); | 2015 | mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS); |
1899 | host->cmd_status = pending; | 2016 | host->cmd_status = pending; |
@@ -1999,7 +2116,9 @@ static void dw_mci_work_routine_card(struct work_struct *work) | |||
1999 | 2116 | ||
2000 | switch (host->state) { | 2117 | switch (host->state) { |
2001 | case STATE_IDLE: | 2118 | case STATE_IDLE: |
2119 | case STATE_WAITING_CMD11_DONE: | ||
2002 | break; | 2120 | break; |
2121 | case STATE_SENDING_CMD11: | ||
2003 | case STATE_SENDING_CMD: | 2122 | case STATE_SENDING_CMD: |
2004 | mrq->cmd->error = -ENOMEDIUM; | 2123 | mrq->cmd->error = -ENOMEDIUM; |
2005 | if (!mrq->data) | 2124 | if (!mrq->data) |