Add hibernation image area
[AGL/meta-agl.git] / meta-agl-bsp / meta-renesas / recipes-kernel / linux / linux / hibernation / 0008-Add-rcar-mmc-hibernation-code.patch
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
5
6 Signed-off-by: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
7 ---
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(-)
13
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;
20         struct clk *hclk;
21         unsigned int clk;
22 +       int clkrate;
23         int bus_width;
24         unsigned char timing;
25         bool sd_error;
26 @@ -257,6 +258,8 @@ struct sh_mmcif_host {
27         struct dma_chan         *chan_tx;
28         struct completion       dma_complete;
29         bool                    dma_active;
30 +#define N_REGS         10
31 +       u32                     regs[N_REGS];
32  };
33  
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)
36                 }
37         }
38  
39 +       host->clkrate = clk_get_rate(host->hclk);
40 +
41         ret = sh_mmcif_clk_update(host);
42         if (ret < 0)
43                 goto eclkupdate;
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);
49         return ret;
50  
51  emmcaddh:
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);
54         pm_runtime_put(dev);
55  
56 -       return 0;
57 +       return mmc_suspend_host(host->mmc);
58  }
59  
60  static int sh_mmcif_resume(struct device *dev)
61  {
62 -       return 0;
63 +       struct sh_mmcif_host *host = dev_get_drvdata(dev);
64 +       return mmc_resume_host(host->mmc);
65 +}
66 +#endif
67 +
68 +#ifdef CONFIG_PM
69 +static int sh_mmcif_restore(struct device *dev)
70 +{
71 +       struct sh_mmcif_host *host = dev_get_drvdata(dev);
72 +       int ret;
73 +       ret = clk_set_rate(host->hclk, host->clkrate);
74 +       if (ret < 0)
75 +               goto eclkupdate;
76 +       ret = sh_mmcif_clk_update(host);
77 +       if (ret < 0)
78 +               goto eclkupdate;
79 +       ret = pm_runtime_resume(dev);
80 +       if (ret < 0)
81 +               goto eresume;
82 +       sh_mmcif_sync_reset(host);
83 +#ifdef CONFIG_MACH_FTEN
84 +       sh_mmcif_writel(host->addr, 0x00000080, 0x00000100);
85 +#endif
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);
96 +eclkupdate:
97 +       pr_info("Can't set clock\n");
98 +       return -EINVAL;
99 +eresume:
100 +       pr_info("Can't resume PM\n");
101 +       return -ENODEV;
102  }
103 +
104 +static int sh_mmcif_freeze(struct device *dev)
105 +{
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);
112 +       return ret;
113 +}
114 +#else
115 +#define sh_mmcif_restore NULL
116 +#define sh_mmcif_freeze NULL
117  #endif
118  
119 +
120  static const struct of_device_id mmcif_of_match[] = {
121         { .compatible = "renesas,sh-mmcif" },
122         { }
123 @@ -1591,6 +1650,8 @@ MODULE_DEVICE_TABLE(of, mmcif_of_match);
124  
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,
129  };
130  
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;
138         unsigned int type;
139         struct sh_mobile_sdhi_vlt vlt;
140 +       int wifi_xrst;
141 +       int save_clk_rate;
142  };
143  
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)
146                         if (ret < 0)
147                                 dev_err(&pdev->dev,
148                                         "cannot set clock rate: %d\n", ret);
149 +                       priv->save_clk_rate = clk_rate;
150  
151                         clk_disable_unprepare(priv->clk);
152                 }
153 @@ -841,6 +844,7 @@ static int sh_mobile_sdhi_probe(struct platform_device *pdev)
154                 }
155         }
156  
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
166 +       int ret;
167 +       struct sh_mobile_sdhi *priv = container_of(host->pdata,
168 +                                                  struct sh_mobile_sdhi,
169 +                                                  mmc_data);
170 +#endif
171  
172         tmio_mmc_host_remove(host);
173  
174         if (p && p->cleanup)
175                 p->cleanup(pdev);
176  
177 +#ifdef CONFIG_MACH_FTEN_DT
178 +       ret = gpio_request(priv->wifi_xrst, "sh_mobile_sdhi");
179 +       if (ret != 0) {
180 +               dev_err(&pdev->dev,
181 +                       "gpio_request(%d) failed(%d) remove\n",
182 +                       priv->wifi_xrst, ret);
183 +               goto skip_wifi;
184 +       }
185 +       ret = gpio_direction_output(priv->wifi_xrst, 0);
186 +       if (ret != 0) {
187 +               dev_err(&pdev->dev,
188 +                       "gpio_direction_output(%d) failed(%d) remove\n",
189 +                       priv->wifi_xrst, ret);
190 +       }
191 +       gpio_free(priv->wifi_xrst);
192 +skip_wifi:
193 +#endif
194 +
195 +       return 0;
196 +}
197 +
198 +static int sh_mobile_sdhi_restore_noirq(struct device *dev)
199 +{
200 +       struct mmc_host *mmc = dev_get_drvdata(dev);
201 +       struct tmio_mmc_host *host = mmc_priv(mmc);
202 +
203 +       sd_ctrl_write32(host, CTL_IRQ_MASK, 0x8b7f031d);
204 +       sd_ctrl_write32(host, CTL_STATUS, 0);
205 +#if 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);
212 +       msleep(2);
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);
216 +       msleep(2);
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);
221 +#endif
222 +       return 0;
223 +}
224 +
225 +static int sh_mobile_sdhi_restore(struct device *dev)
226 +{
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,
231 +                                                  mmc_data);
232 +#if defined(CONFIG_MACH_FTEN_DT) || defined(CONFIG_PM_SLEEP)
233 +       int ret;
234 +#endif
235 +       int dma_size;
236 +       host->restore = true;
237 +
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");
242 +               if (ret != 0) {
243 +                       dev_err(dev, "gpio_request(%d) failed(%d) restore\n",
244 +                               priv->wifi_xrst, ret);
245 +                       goto skip_wifi;
246 +               }
247 +               ret = gpio_direction_output(priv->wifi_xrst, 1);
248 +               if (ret != 0) {
249 +                       dev_err(dev, "gpio_direction_output(%d) failed(%d) restore\n",
250 +                               priv->wifi_xrst, ret);
251 +               }
252 +               gpio_free(priv->wifi_xrst);
253 +       }
254 +skip_wifi:
255 +#endif
256 +
257 +       dma_size = sh_mobile_sdhi_get_xmit_size(priv->type,
258 +                               priv->dma_priv.alignment_shift);
259 +
260 +       sd_ctrl_write16(host, SD_DMACR(priv->type), dma_size);
261 +
262 +#ifdef CONFIG_PM_SLEEP
263 +       ret = tmio_mmc_host_resume(dev);
264 +       host->restore = false;
265 +       return ret;
266 +#else
267 +       host->restore = false;
268         return 0;
269 +#endif
270  }
271  
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,
280 +#endif
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,
285                         NULL)
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 {
291         bool                    resuming;
292         bool                    done_tuning;
293         struct completion       completion;
294 +       bool                    restore;
295  };
296  
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);
305  
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)
310 +               clk |= SDCLKOFFEN;
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);
315 +#else
316         sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
317 -       msleep(10);
318 +#endif
319 +       if (!host->restore)
320 +               msleep(2);
321  }
322  
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)
330 +                       && !host->restore)
331                         msleep(10);
332         }
333  
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)
338 +               && !host->restore)
339                 msleep(10);
340  }
341  
342 @@ -190,14 +204,16 @@ static void tmio_mmc_clk_start(struct tmio_mmc_host *host)
343  {
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))
347 -               msleep(10);
348 +       if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP)
349 +               && !host->restore)
350 +               msleep(2);
351  
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))
356 -                       msleep(10);
357 +               if (!(host->pdata->flags & TMIO_MMC_CLK_NO_SLEEP)
358 +                       && !host->restore)
359 +                       msleep(2);
360         }
361  }
362  
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);
367 -       msleep(10);
368 +       msleep(2);
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);
372 -       msleep(10);
373 +       msleep(2);
374  }
375  
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.
379          */
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;
388 -                       }
389 +                       if (host->resuming)
390 +                               reset_needed = 1;
391                 }
392 +
393                 if (host->power == TMIO_MMC_OFF_STOP)
394 +                       reset_needed = 1;
395 +               if (reset_needed) {
396                         tmio_mmc_reset(host);
397 +                       if (host->resuming)
398 +                               host->resuming = false;
399 +               }
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)
404  
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);
409  }
410  EXPORT_SYMBOL(tmio_mmc_host_resume);
411  #endif
412 -- 
413 1.8.3.1
414