1 From 9d1d9be70ed3cf6670ae12a1caed337833f7bba8 Mon Sep 17 00:00:00 2001
2 From: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
3 Date: Thu, 18 May 2017 17:38:11 +0900
4 Subject: [PATCH 08/15] Add rcar mmc hibernation code
6 Signed-off-by: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
8 drivers/mmc/host/sh_mmcif.c | 65 +++++++++++++++++++++-
9 drivers/mmc/host/sh_mobile_sdhi.c | 112 +++++++++++++++++++++++++++++++++++++-
10 drivers/mmc/host/tmio_mmc.h | 1 +
11 drivers/mmc/host/tmio_mmc_pio.c | 49 ++++++++++++-----
12 4 files changed, 210 insertions(+), 17 deletions(-)
14 diff --git a/drivers/mmc/host/sh_mmcif.c b/drivers/mmc/host/sh_mmcif.c
15 index 7290e6e..4ecf62c 100644
16 --- a/drivers/mmc/host/sh_mmcif.c
17 +++ b/drivers/mmc/host/sh_mmcif.c
18 @@ -232,6 +232,7 @@ struct sh_mmcif_host {
19 struct platform_device *pd;
26 @@ -257,6 +258,8 @@ struct sh_mmcif_host {
27 struct dma_chan *chan_tx;
28 struct completion dma_complete;
34 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
35 @@ -1457,6 +1460,8 @@ static int sh_mmcif_probe(struct platform_device *pdev)
39 + host->clkrate = clk_get_rate(host->hclk);
41 ret = sh_mmcif_clk_update(host);
44 @@ -1503,6 +1508,7 @@ static int sh_mmcif_probe(struct platform_device *pdev)
45 dev_info(&pdev->dev, "driver version %s\n", DRIVER_VERSION);
46 dev_dbg(&pdev->dev, "chip ver H'%04x\n",
47 sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
48 + device_enable_async_suspend(&pdev->dev);
52 @@ -1574,15 +1580,68 @@ static int sh_mmcif_suspend(struct device *dev)
53 sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
57 + return mmc_suspend_host(host->mmc);
60 static int sh_mmcif_resume(struct device *dev)
63 + struct sh_mmcif_host *host = dev_get_drvdata(dev);
64 + return mmc_resume_host(host->mmc);
69 +static int sh_mmcif_restore(struct device *dev)
71 + struct sh_mmcif_host *host = dev_get_drvdata(dev);
73 + ret = clk_set_rate(host->hclk, host->clkrate);
76 + ret = sh_mmcif_clk_update(host);
79 + ret = pm_runtime_resume(dev);
82 + sh_mmcif_sync_reset(host);
83 +#ifdef CONFIG_MACH_FTEN
84 + sh_mmcif_writel(host->addr, 0x00000080, 0x00000100);
86 + sh_mmcif_writel(host->addr, MMCIF_CE_INT_MASK, MASK_ALL);
87 + clk_disable_unprepare(host->hclk);
88 + dev_info(dev, "restore: chip ver H'%04x\n",
89 + sh_mmcif_readl(host->addr, MMCIF_CE_VERSION) & 0x0000ffff);
90 + sh_mmcif_writel(host->addr, MMCIF_CE_CMD_CTRL, host->regs[0]);
91 + sh_mmcif_writel(host->addr, MMCIF_CE_BLOCK_SET, host->regs[1]);
92 + sh_mmcif_writel(host->addr, MMCIF_CE_CLK_CTRL, host->regs[2]);
93 + sh_mmcif_writel(host->addr, MMCIF_CE_BUF_ACC, host->regs[3]);
94 + sh_mmcif_release_dma(host);
95 + return mmc_resume_host(host->mmc);
97 + pr_info("Can't set clock\n");
100 + pr_info("Can't resume PM\n");
104 +static int sh_mmcif_freeze(struct device *dev)
106 + struct sh_mmcif_host *host = dev_get_drvdata(dev);
107 + int ret = mmc_suspend_host(host->mmc);
108 + host->regs[0] = sh_mmcif_readl(host->addr, MMCIF_CE_CMD_CTRL);
109 + host->regs[1] = sh_mmcif_readl(host->addr, MMCIF_CE_BLOCK_SET);
110 + host->regs[2] = sh_mmcif_readl(host->addr, MMCIF_CE_CLK_CTRL);
111 + host->regs[3] = sh_mmcif_readl(host->addr, MMCIF_CE_BUF_ACC);
115 +#define sh_mmcif_restore NULL
116 +#define sh_mmcif_freeze NULL
120 static const struct of_device_id mmcif_of_match[] = {
121 { .compatible = "renesas,sh-mmcif" },
123 @@ -1591,6 +1650,8 @@ MODULE_DEVICE_TABLE(of, mmcif_of_match);
125 static const struct dev_pm_ops sh_mmcif_dev_pm_ops = {
126 SET_SYSTEM_SLEEP_PM_OPS(sh_mmcif_suspend, sh_mmcif_resume)
127 + .restore = sh_mmcif_restore,
128 + .freeze = sh_mmcif_freeze,
131 static struct platform_driver sh_mmcif_driver = {
132 diff --git a/drivers/mmc/host/sh_mobile_sdhi.c b/drivers/mmc/host/sh_mobile_sdhi.c
133 index 1b59cdf..c7f3abf 100644
134 --- a/drivers/mmc/host/sh_mobile_sdhi.c
135 +++ b/drivers/mmc/host/sh_mobile_sdhi.c
136 @@ -156,6 +156,8 @@ struct sh_mobile_sdhi {
137 struct tmio_mmc_dma dma_priv;
139 struct sh_mobile_sdhi_vlt vlt;
144 static int sh_mobile_sdhi_clk_enable(struct platform_device *pdev, unsigned int *f)
145 @@ -647,6 +649,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
148 "cannot set clock rate: %d\n", ret);
149 + priv->save_clk_rate = clk_rate;
151 clk_disable_unprepare(priv->clk);
153 @@ -841,6 +844,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
157 + device_enable_async_suspend(&pdev->dev);
158 dev_info(&pdev->dev, "%s base at 0x%08lx clock rate %u MHz\n",
159 mmc_hostname(host->mmc), (unsigned long)
160 (platform_get_resource(pdev, IORESOURCE_MEM, 0)->start),
161 @@ -865,17 +869,123 @@ static int sh_mobile_sdhi_remove(struct platform_device *pdev)
162 struct mmc_host *mmc = platform_get_drvdata(pdev);
163 struct tmio_mmc_host *host = mmc_priv(mmc);
164 struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
165 +#ifdef CONFIG_MACH_FTEN_DT
167 + struct sh_mobile_sdhi *priv = container_of(host->pdata,
168 + struct sh_mobile_sdhi,
172 tmio_mmc_host_remove(host);
177 +#ifdef CONFIG_MACH_FTEN_DT
178 + ret = gpio_request(priv->wifi_xrst, "sh_mobile_sdhi");
180 + dev_err(&pdev->dev,
181 + "gpio_request(%d) failed(%d) remove\n",
182 + priv->wifi_xrst, ret);
185 + ret = gpio_direction_output(priv->wifi_xrst, 0);
187 + dev_err(&pdev->dev,
188 + "gpio_direction_output(%d) failed(%d) remove\n",
189 + priv->wifi_xrst, ret);
191 + gpio_free(priv->wifi_xrst);
198 +static int sh_mobile_sdhi_restore_noirq(struct device *dev)
200 + struct mmc_host *mmc = dev_get_drvdata(dev);
201 + struct tmio_mmc_host *host = mmc_priv(mmc);
203 + sd_ctrl_write32(host, CTL_IRQ_MASK, 0x8b7f031d);
204 + sd_ctrl_write32(host, CTL_STATUS, 0);
206 + sh_mobile_sdhi_enable_sdbuf_acc32(host, false);
207 + /* FIXME - should we set stop clock reg here */
208 + sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
209 + /* implicit BUG_ON(!res) */
210 + if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG)
211 + sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
213 + sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
214 + if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG)
215 + sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
217 + sd_ctrl_write32(host, CTL_IRQ_MASK, 0x8b7f031d);
218 + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0040);
219 + sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80E0);
220 + sd_ctrl_write16(host, CTL_DMA_ENABLE, 0x1002);
225 +static int sh_mobile_sdhi_restore(struct device *dev)
227 + struct mmc_host *mmc = dev_get_drvdata(dev);
228 + struct tmio_mmc_host *host = mmc_priv(mmc);
229 + struct sh_mobile_sdhi *priv = container_of(host->pdata,
230 + struct sh_mobile_sdhi,
232 +#if defined(CONFIG_MACH_FTEN_DT) || defined(CONFIG_PM_SLEEP)
236 + host->restore = true;
238 +#ifdef CONFIG_MACH_FTEN_DT
239 + /* priv->wifi_xrst is 0 or more. */
240 + if (priv->wifi_xrst >= 0) {
241 + ret = gpio_request(priv->wifi_xrst, "sh_mobile_sdhi");
243 + dev_err(dev, "gpio_request(%d) failed(%d) restore\n",
244 + priv->wifi_xrst, ret);
247 + ret = gpio_direction_output(priv->wifi_xrst, 1);
249 + dev_err(dev, "gpio_direction_output(%d) failed(%d) restore\n",
250 + priv->wifi_xrst, ret);
252 + gpio_free(priv->wifi_xrst);
257 + dma_size = sh_mobile_sdhi_get_xmit_size(priv->type,
258 + priv->dma_priv.alignment_shift);
260 + sd_ctrl_write16(host, SD_DMACR(priv->type), dma_size);
262 +#ifdef CONFIG_PM_SLEEP
263 + ret = tmio_mmc_host_resume(dev);
264 + host->restore = false;
267 + host->restore = false;
272 static const struct dev_pm_ops tmio_mmc_dev_pm_ops = {
273 - SET_SYSTEM_SLEEP_PM_OPS(tmio_mmc_host_suspend, tmio_mmc_host_resume)
274 +#ifdef CONFIG_PM_SLEEP
275 + .suspend = tmio_mmc_host_suspend,
276 + .resume = tmio_mmc_host_resume,
277 + .freeze = tmio_mmc_host_suspend,
278 + .thaw = tmio_mmc_host_resume,
279 + .poweroff = tmio_mmc_host_suspend,
281 + .restore = sh_mobile_sdhi_restore,
282 + .restore_noirq = sh_mobile_sdhi_restore_noirq,
283 SET_RUNTIME_PM_OPS(tmio_mmc_host_runtime_suspend,
284 tmio_mmc_host_runtime_resume,
286 diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
287 index c5b12ad..3efe03d 100644
288 --- a/drivers/mmc/host/tmio_mmc.h
289 +++ b/drivers/mmc/host/tmio_mmc.h
290 @@ -104,6 +104,7 @@ struct tmio_mmc_host {
293 struct completion completion;
297 int tmio_mmc_host_probe(struct tmio_mmc_host **host,
298 diff --git a/drivers/mmc/host/tmio_mmc_pio.c b/drivers/mmc/host/tmio_mmc_pio.c
299 index 09c0c08..514af15 100644
300 --- a/drivers/mmc/host/tmio_mmc_pio.c
301 +++ b/drivers/mmc/host/tmio_mmc_pio.c
302 @@ -167,8 +167,20 @@ static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
303 if (host->set_clk_div)
304 host->set_clk_div(host->pdev, (clk>>22) & 1);
306 +#ifdef CONFIG_MACH_FTEN
307 + clk |= sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL) & 0x0100;
308 + if (host->pdata->flags & TMIO_MMC_SDCLK_AUTO_CONTROL &&
309 + new_clock > host->mmc->f_init)
311 + dev_dbg(&host->pdev->dev,
312 + "clock=%d, clk=%08x, new_clock=%d, f_init=%d\n",
313 + clock, clk, new_clock, host->mmc->f_init);
314 + sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x3ff);
316 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
319 + if (!host->restore)
323 static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
324 @@ -176,13 +188,15 @@ static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
325 /* implicit BUG_ON(!res) */
326 if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) {
327 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
328 - if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP))
329 + if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP)
334 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, ~0x0100 &
335 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
336 - if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP))
337 + if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP)
342 @@ -190,14 +204,16 @@ static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
344 sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
345 sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
346 - if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP))
348 + if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP)
352 /* implicit BUG_ON(!res) */
353 if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG) {
354 sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
355 - if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP))
357 + if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP)
363 @@ -208,11 +224,11 @@ static void tmio_mmc_reset(struct tmio_mmc_host *host)
364 /* implicit BUG_ON(!res) */
365 if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG)
366 sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
369 sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
370 if (host->pdata->flags & TMIO_MMC_HAVE_HIGH_REG)
371 sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
376 static void tmio_mmc_reset_work(struct work_struct *work)
377 @@ -1134,16 +1150,21 @@ static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
378 * is kept positive, so no suspending actually takes place.
380 if (ios->power_mode == MMC_POWER_ON && ios->clock) {
381 + int reset_needed = 0;
382 if (host->power != TMIO_MMC_ON_RUN) {
383 tmio_mmc_clk_update(mmc);
384 pm_runtime_get_sync(dev);
385 - if (host->resuming) {
386 - tmio_mmc_reset(host);
387 - host->resuming = false;
389 + if (host->resuming)
393 if (host->power == TMIO_MMC_OFF_STOP)
395 + if (reset_needed) {
396 tmio_mmc_reset(host);
397 + if (host->resuming)
398 + host->resuming = false;
400 tmio_mmc_set_clock(host, ios->clock);
401 if (host->power == TMIO_MMC_OFF_STOP)
402 /* power up SD card and the bus */
403 @@ -1497,7 +1518,7 @@ int tmio_mmc_host_resume(struct device *dev)
405 /* The MMC core will perform the complete set up */
406 host->resuming = true;
407 - return mmc_resume_host(mmc);
408 + return mmc_resume_host(mmc);
410 EXPORT_SYMBOL(tmio_mmc_host_resume);