aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Griffin <peter.griffin@linaro.org>2015-04-10 05:40:24 -0400
committerUlf Hansson <ulf.hansson@linaro.org>2015-04-10 06:55:39 -0400
commit406c24310a7bd7ce152662647fcb76c4a67971a5 (patch)
treea53431cffc619c036e595845412e47903104fb51
parent8bef7178a630dc41ca5868e6bb54ffee91e1c83a (diff)
mmc: sdhci-st: Add support for de-asserting reset signal and top regs resource
STiH407 family SoC's can have a reset signal for the controller which needs to be managed. Also the eMMC controller has some additional 'top' memory mapped registers which are used to manage the dynamic and static delay required for UHS modes. This patch adds support for creating the mapping, which will be used by subsequent patches. Signed-off-by: Peter Griffin <peter.griffin@linaro.org> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Acked-by: Maxime Coquelin <maxime.coquelin@st.com> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
-rw-r--r--drivers/mmc/host/sdhci-st.c60
1 files changed, 57 insertions, 3 deletions
diff --git a/drivers/mmc/host/sdhci-st.c b/drivers/mmc/host/sdhci-st.c
index a80de9305c4b..74213b0bc94f 100644
--- a/drivers/mmc/host/sdhci-st.c
+++ b/drivers/mmc/host/sdhci-st.c
@@ -23,9 +23,14 @@
23#include <linux/module.h> 23#include <linux/module.h>
24#include <linux/err.h> 24#include <linux/err.h>
25#include <linux/mmc/host.h> 25#include <linux/mmc/host.h>
26 26#include <linux/reset.h>
27#include "sdhci-pltfm.h" 27#include "sdhci-pltfm.h"
28 28
29struct st_mmc_platform_data {
30 struct reset_control *rstc;
31 void __iomem *top_ioaddr;
32};
33
29/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */ 34/* MMCSS glue logic to setup the HC on some ST SoCs (e.g. STiH407 family) */
30 35
31#define ST_MMC_CCONFIG_REG_1 0x400 36#define ST_MMC_CCONFIG_REG_1 0x400
@@ -151,10 +156,16 @@ static const struct sdhci_pltfm_data sdhci_st_pdata = {
151static int sdhci_st_probe(struct platform_device *pdev) 156static int sdhci_st_probe(struct platform_device *pdev)
152{ 157{
153 struct sdhci_host *host; 158 struct sdhci_host *host;
159 struct st_mmc_platform_data *pdata;
154 struct sdhci_pltfm_host *pltfm_host; 160 struct sdhci_pltfm_host *pltfm_host;
155 struct clk *clk; 161 struct clk *clk;
156 int ret = 0; 162 int ret = 0;
157 u16 host_version; 163 u16 host_version;
164 struct resource *res;
165
166 pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
167 if (!pdata)
168 return -ENOMEM;
158 169
159 clk = devm_clk_get(&pdev->dev, "mmc"); 170 clk = devm_clk_get(&pdev->dev, "mmc");
160 if (IS_ERR(clk)) { 171 if (IS_ERR(clk)) {
@@ -162,10 +173,17 @@ static int sdhci_st_probe(struct platform_device *pdev)
162 return PTR_ERR(clk); 173 return PTR_ERR(clk);
163 } 174 }
164 175
176 pdata->rstc = devm_reset_control_get(&pdev->dev, NULL);
177 if (IS_ERR(pdata->rstc))
178 pdata->rstc = NULL;
179 else
180 reset_control_deassert(pdata->rstc);
181
165 host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0); 182 host = sdhci_pltfm_init(pdev, &sdhci_st_pdata, 0);
166 if (IS_ERR(host)) { 183 if (IS_ERR(host)) {
167 dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n"); 184 dev_err(&pdev->dev, "Failed sdhci_pltfm_init\n");
168 return PTR_ERR(host); 185 ret = PTR_ERR(host);
186 goto err_pltfm_init;
169 } 187 }
170 188
171 ret = mmc_of_parse(host->mmc); 189 ret = mmc_of_parse(host->mmc);
@@ -176,7 +194,17 @@ static int sdhci_st_probe(struct platform_device *pdev)
176 194
177 clk_prepare_enable(clk); 195 clk_prepare_enable(clk);
178 196
197 /* Configure the FlashSS Top registers for setting eMMC TX/RX delay */
198 res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
199 "top-mmc-delay");
200 pdata->top_ioaddr = devm_ioremap_resource(&pdev->dev, res);
201 if (IS_ERR(pdata->top_ioaddr)) {
202 dev_warn(&pdev->dev, "FlashSS Top Dly registers not available");
203 pdata->top_ioaddr = NULL;
204 }
205
179 pltfm_host = sdhci_priv(host); 206 pltfm_host = sdhci_priv(host);
207 pltfm_host->priv = pdata;
180 pltfm_host->clk = clk; 208 pltfm_host->clk = clk;
181 209
182 ret = sdhci_add_host(host); 210 ret = sdhci_add_host(host);
@@ -200,6 +228,24 @@ err_out:
200 clk_disable_unprepare(clk); 228 clk_disable_unprepare(clk);
201err_of: 229err_of:
202 sdhci_pltfm_free(pdev); 230 sdhci_pltfm_free(pdev);
231err_pltfm_init:
232 if (pdata->rstc)
233 reset_control_assert(pdata->rstc);
234
235 return ret;
236}
237
238static int sdhci_st_remove(struct platform_device *pdev)
239{
240 struct sdhci_host *host = platform_get_drvdata(pdev);
241 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
242 struct st_mmc_platform_data *pdata = pltfm_host->priv;
243 int ret;
244
245 ret = sdhci_pltfm_unregister(pdev);
246
247 if (pdata->rstc)
248 reset_control_assert(pdata->rstc);
203 249
204 return ret; 250 return ret;
205} 251}
@@ -209,11 +255,15 @@ static int sdhci_st_suspend(struct device *dev)
209{ 255{
210 struct sdhci_host *host = dev_get_drvdata(dev); 256 struct sdhci_host *host = dev_get_drvdata(dev);
211 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 257 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
258 struct st_mmc_platform_data *pdata = pltfm_host->priv;
212 int ret = sdhci_suspend_host(host); 259 int ret = sdhci_suspend_host(host);
213 260
214 if (ret) 261 if (ret)
215 goto out; 262 goto out;
216 263
264 if (pdata->rstc)
265 reset_control_assert(pdata->rstc);
266
217 clk_disable_unprepare(pltfm_host->clk); 267 clk_disable_unprepare(pltfm_host->clk);
218out: 268out:
219 return ret; 269 return ret;
@@ -223,9 +273,13 @@ static int sdhci_st_resume(struct device *dev)
223{ 273{
224 struct sdhci_host *host = dev_get_drvdata(dev); 274 struct sdhci_host *host = dev_get_drvdata(dev);
225 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host); 275 struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
276 struct st_mmc_platform_data *pdata = pltfm_host->priv;
226 277
227 clk_prepare_enable(pltfm_host->clk); 278 clk_prepare_enable(pltfm_host->clk);
228 279
280 if (pdata->rstc)
281 reset_control_deassert(pdata->rstc);
282
229 return sdhci_resume_host(host); 283 return sdhci_resume_host(host);
230} 284}
231#endif 285#endif
@@ -241,7 +295,7 @@ MODULE_DEVICE_TABLE(of, st_sdhci_match);
241 295
242static struct platform_driver sdhci_st_driver = { 296static struct platform_driver sdhci_st_driver = {
243 .probe = sdhci_st_probe, 297 .probe = sdhci_st_probe,
244 .remove = sdhci_pltfm_unregister, 298 .remove = sdhci_st_remove,
245 .driver = { 299 .driver = {
246 .name = "sdhci-st", 300 .name = "sdhci-st",
247 .pm = &sdhci_st_pmops, 301 .pm = &sdhci_st_pmops,