summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGuodong Xu <guodong.xu@linaro.org>2016-08-12 04:51:26 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2016-09-26 15:31:19 -0400
commitd6786fefe816ba60c794f8a41a73b0dd3a4df097 (patch)
tree46ce80c9a93c70976c91a61580d9c11c4ad3d4a1
parentfdc22b6b1f259d939ace88dff21f167e79eadd67 (diff)
mmc: dw_mmc: add reset support to dwmmc host controller
Dwmmc host controller may in unknown state when entering kernel boot. One example is when booting from eMMC, bootloader need initialize MMC host controller into some state so it can read. In order to make sure MMC host controller in a clean initial state, this reset support is added. With this patch, a 'resets' property can be added into dw_mmc device tree node. The hardware logic is: dwmmc host controller IP receives a reset signal from a 'reset provider' (eg. power management unit). The 'resets' property points to this reset signal. So, during dwmmc driver probe, it can use this signal to reset itself. Refer to [1] for more information. [1] Documentation/devicetree/bindings/reset/reset.txt Signed-off-by: Guodong Xu <guodong.xu@linaro.org> Signed-off-by: Xinwei Kong <kong.kongxinwei@hisilicon.com> Signed-off-by: Zhangfei Gao <zhangfei.gao@linaro.org> Reviewed-by: Shawn Lin <shawn.lin@rock-chips.com> Signed-off-by: Jaehoon Chung <jh80.chung@samsung.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/dw_mmc.c23
-rw-r--r--include/linux/mmc/dw_mmc.h2
2 files changed, 24 insertions, 1 deletions
diff --git a/drivers/mmc/host/dw_mmc.c b/drivers/mmc/host/dw_mmc.c
index 1a1e1e1ac7c1..e7eef75a65ef 100644
--- a/drivers/mmc/host/dw_mmc.c
+++ b/drivers/mmc/host/dw_mmc.c
@@ -2876,6 +2876,13 @@ static struct dw_mci_board *dw_mci_parse_dt(struct dw_mci *host)
2876 if (!pdata) 2876 if (!pdata)
2877 return ERR_PTR(-ENOMEM); 2877 return ERR_PTR(-ENOMEM);
2878 2878
2879 /* find reset controller when exist */
2880 pdata->rstc = devm_reset_control_get_optional(dev, NULL);
2881 if (IS_ERR(pdata->rstc)) {
2882 if (PTR_ERR(pdata->rstc) == -EPROBE_DEFER)
2883 return ERR_PTR(-EPROBE_DEFER);
2884 }
2885
2879 /* find out number of slots supported */ 2886 /* find out number of slots supported */
2880 of_property_read_u32(np, "num-slots", &pdata->num_slots); 2887 of_property_read_u32(np, "num-slots", &pdata->num_slots);
2881 2888
@@ -2947,7 +2954,9 @@ int dw_mci_probe(struct dw_mci *host)
2947 2954
2948 if (!host->pdata) { 2955 if (!host->pdata) {
2949 host->pdata = dw_mci_parse_dt(host); 2956 host->pdata = dw_mci_parse_dt(host);
2950 if (IS_ERR(host->pdata)) { 2957 if (PTR_ERR(host->pdata) == -EPROBE_DEFER) {
2958 return -EPROBE_DEFER;
2959 } else if (IS_ERR(host->pdata)) {
2951 dev_err(host->dev, "platform data not available\n"); 2960 dev_err(host->dev, "platform data not available\n");
2952 return -EINVAL; 2961 return -EINVAL;
2953 } 2962 }
@@ -3001,6 +3010,12 @@ int dw_mci_probe(struct dw_mci *host)
3001 } 3010 }
3002 } 3011 }
3003 3012
3013 if (!IS_ERR(host->pdata->rstc)) {
3014 reset_control_assert(host->pdata->rstc);
3015 usleep_range(10, 50);
3016 reset_control_deassert(host->pdata->rstc);
3017 }
3018
3004 setup_timer(&host->cmd11_timer, 3019 setup_timer(&host->cmd11_timer,
3005 dw_mci_cmd11_timer, (unsigned long)host); 3020 dw_mci_cmd11_timer, (unsigned long)host);
3006 3021
@@ -3150,6 +3165,9 @@ err_dmaunmap:
3150 if (host->use_dma && host->dma_ops->exit) 3165 if (host->use_dma && host->dma_ops->exit)
3151 host->dma_ops->exit(host); 3166 host->dma_ops->exit(host);
3152 3167
3168 if (!IS_ERR(host->pdata->rstc))
3169 reset_control_assert(host->pdata->rstc);
3170
3153err_clk_ciu: 3171err_clk_ciu:
3154 clk_disable_unprepare(host->ciu_clk); 3172 clk_disable_unprepare(host->ciu_clk);
3155 3173
@@ -3180,6 +3198,9 @@ void dw_mci_remove(struct dw_mci *host)
3180 if (host->use_dma && host->dma_ops->exit) 3198 if (host->use_dma && host->dma_ops->exit)
3181 host->dma_ops->exit(host); 3199 host->dma_ops->exit(host);
3182 3200
3201 if (!IS_ERR(host->pdata->rstc))
3202 reset_control_assert(host->pdata->rstc);
3203
3183 clk_disable_unprepare(host->ciu_clk); 3204 clk_disable_unprepare(host->ciu_clk);
3184 clk_disable_unprepare(host->biu_clk); 3205 clk_disable_unprepare(host->biu_clk);
3185} 3206}
diff --git a/include/linux/mmc/dw_mmc.h b/include/linux/mmc/dw_mmc.h
index 83b0edfce471..f5af2bd35e7f 100644
--- a/include/linux/mmc/dw_mmc.h
+++ b/include/linux/mmc/dw_mmc.h
@@ -17,6 +17,7 @@
17#include <linux/scatterlist.h> 17#include <linux/scatterlist.h>
18#include <linux/mmc/core.h> 18#include <linux/mmc/core.h>
19#include <linux/dmaengine.h> 19#include <linux/dmaengine.h>
20#include <linux/reset.h>
20 21
21#define MAX_MCI_SLOTS 2 22#define MAX_MCI_SLOTS 2
22 23
@@ -259,6 +260,7 @@ struct dw_mci_board {
259 /* delay in mS before detecting cards after interrupt */ 260 /* delay in mS before detecting cards after interrupt */
260 u32 detect_delay_ms; 261 u32 detect_delay_ms;
261 262
263 struct reset_control *rstc;
262 struct dw_mci_dma_ops *dma_ops; 264 struct dw_mci_dma_ops *dma_ops;
263 struct dma_pdata *data; 265 struct dma_pdata *data;
264}; 266};