diff options
-rw-r--r-- | drivers/mmc/host/msm_sdcc.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c index 67f536ca31d3..81ed16fb42b5 100644 --- a/drivers/mmc/host/msm_sdcc.c +++ b/drivers/mmc/host/msm_sdcc.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <mach/mmc.h> | 44 | #include <mach/mmc.h> |
45 | #include <mach/msm_iomap.h> | 45 | #include <mach/msm_iomap.h> |
46 | #include <mach/dma.h> | 46 | #include <mach/dma.h> |
47 | #include <mach/clk.h> | ||
47 | 48 | ||
48 | #include "msm_sdcc.h" | 49 | #include "msm_sdcc.h" |
49 | 50 | ||
@@ -126,6 +127,40 @@ static void | |||
126 | msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, | 127 | msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, |
127 | u32 c); | 128 | u32 c); |
128 | 129 | ||
130 | static void msmsdcc_reset_and_restore(struct msmsdcc_host *host) | ||
131 | { | ||
132 | u32 mci_clk = 0; | ||
133 | u32 mci_mask0 = 0; | ||
134 | int ret = 0; | ||
135 | |||
136 | /* Save the controller state */ | ||
137 | mci_clk = readl(host->base + MMCICLOCK); | ||
138 | mci_mask0 = readl(host->base + MMCIMASK0); | ||
139 | |||
140 | /* Reset the controller */ | ||
141 | ret = clk_reset(host->clk, CLK_RESET_ASSERT); | ||
142 | if (ret) | ||
143 | pr_err("%s: Clock assert failed at %u Hz with err %d\n", | ||
144 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
145 | |||
146 | ret = clk_reset(host->clk, CLK_RESET_DEASSERT); | ||
147 | if (ret) | ||
148 | pr_err("%s: Clock deassert failed at %u Hz with err %d\n", | ||
149 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
150 | |||
151 | pr_info("%s: Controller has been re-initialiazed\n", | ||
152 | mmc_hostname(host->mmc)); | ||
153 | |||
154 | /* Restore the contoller state */ | ||
155 | writel(host->pwr, host->base + MMCIPOWER); | ||
156 | writel(mci_clk, host->base + MMCICLOCK); | ||
157 | writel(mci_mask0, host->base + MMCIMASK0); | ||
158 | ret = clk_set_rate(host->clk, host->clk_rate); | ||
159 | if (ret) | ||
160 | pr_err("%s: Failed to set clk rate %u Hz (%d)\n", | ||
161 | mmc_hostname(host->mmc), host->clk_rate, ret); | ||
162 | } | ||
163 | |||
129 | static void | 164 | static void |
130 | msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) | 165 | msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) |
131 | { | 166 | { |
@@ -223,6 +258,8 @@ msmsdcc_dma_complete_tlet(unsigned long data) | |||
223 | pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", | 258 | pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", |
224 | err.flush[0], err.flush[1], err.flush[2], | 259 | err.flush[0], err.flush[1], err.flush[2], |
225 | err.flush[3], err.flush[4], err.flush[5]); | 260 | err.flush[3], err.flush[4], err.flush[5]); |
261 | |||
262 | msmsdcc_reset_and_restore(host); | ||
226 | if (!mrq->data->error) | 263 | if (!mrq->data->error) |
227 | mrq->data->error = -EIO; | 264 | mrq->data->error = -EIO; |
228 | } | 265 | } |
@@ -723,6 +760,7 @@ static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status) | |||
723 | msm_dmov_stop_cmd(host->dma.channel, | 760 | msm_dmov_stop_cmd(host->dma.channel, |
724 | &host->dma.hdr, 0); | 761 | &host->dma.hdr, 0); |
725 | else if (host->curr.data) { /* Non DMA */ | 762 | else if (host->curr.data) { /* Non DMA */ |
763 | msmsdcc_reset_and_restore(host); | ||
726 | msmsdcc_stop_data(host); | 764 | msmsdcc_stop_data(host); |
727 | msmsdcc_request_end(host, cmd->mrq); | 765 | msmsdcc_request_end(host, cmd->mrq); |
728 | } else { /* host->data == NULL */ | 766 | } else { /* host->data == NULL */ |
@@ -771,6 +809,7 @@ msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status, | |||
771 | msm_dmov_stop_cmd(host->dma.channel, | 809 | msm_dmov_stop_cmd(host->dma.channel, |
772 | &host->dma.hdr, 0); | 810 | &host->dma.hdr, 0); |
773 | else { | 811 | else { |
812 | msmsdcc_reset_and_restore(host); | ||
774 | if (host->curr.data) | 813 | if (host->curr.data) |
775 | msmsdcc_stop_data(host); | 814 | msmsdcc_stop_data(host); |
776 | if (!data->stop) | 815 | if (!data->stop) |