Merge git://git.denx.de/u-boot-uniphier
[oweals/u-boot.git] / drivers / mmc / renesas-sdhi.c
1 /*
2  * Copyright (C) 2018 Marek Vasut <marek.vasut@gmail.com>
3  *
4  * SPDX-License-Identifier:     GPL-2.0+
5  */
6
7 #include <common.h>
8 #include <clk.h>
9 #include <fdtdec.h>
10 #include <mmc.h>
11 #include <dm.h>
12 #include <linux/compat.h>
13 #include <linux/dma-direction.h>
14 #include <linux/io.h>
15 #include <linux/sizes.h>
16 #include <power/regulator.h>
17 #include <asm/unaligned.h>
18
19 #include "tmio-common.h"
20
21 #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
22
23 /* SCC registers */
24 #define RENESAS_SDHI_SCC_DTCNTL                 0x800
25 #define   RENESAS_SDHI_SCC_DTCNTL_TAPEN         BIT(0)
26 #define   RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT  16
27 #define   RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK           0xff
28 #define RENESAS_SDHI_SCC_TAPSET                 0x804
29 #define RENESAS_SDHI_SCC_DT2FF                  0x808
30 #define RENESAS_SDHI_SCC_CKSEL                  0x80c
31 #define   RENESAS_SDHI_SCC_CKSEL_DTSEL          BIT(0)
32 #define RENESAS_SDHI_SCC_RVSCNTL                        0x810
33 #define   RENESAS_SDHI_SCC_RVSCNTL_RVSEN                BIT(0)
34 #define RENESAS_SDHI_SCC_RVSREQ                 0x814
35 #define   RENESAS_SDHI_SCC_RVSREQ_RVSERR                BIT(2)
36 #define RENESAS_SDHI_SCC_SMPCMP                 0x818
37 #define RENESAS_SDHI_SCC_TMPPORT2                       0x81c
38
39 #define RENESAS_SDHI_MAX_TAP 3
40
41 static unsigned int renesas_sdhi_init_tuning(struct tmio_sd_priv *priv)
42 {
43         u32 reg;
44
45         /* Initialize SCC */
46         tmio_sd_writel(priv, 0, TMIO_SD_INFO1);
47
48         reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
49         reg &= ~TMIO_SD_CLKCTL_SCLKEN;
50         tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
51
52         /* Set sampling clock selection range */
53         tmio_sd_writel(priv, 0x8 << RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT,
54                            RENESAS_SDHI_SCC_DTCNTL);
55
56         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL);
57         reg |= RENESAS_SDHI_SCC_DTCNTL_TAPEN;
58         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_DTCNTL);
59
60         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
61         reg |= RENESAS_SDHI_SCC_CKSEL_DTSEL;
62         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
63
64         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
65         reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
66         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
67
68         tmio_sd_writel(priv, 0x300 /* scc_tappos */,
69                            RENESAS_SDHI_SCC_DT2FF);
70
71         reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
72         reg |= TMIO_SD_CLKCTL_SCLKEN;
73         tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
74
75         /* Read TAPNUM */
76         return (tmio_sd_readl(priv, RENESAS_SDHI_SCC_DTCNTL) >>
77                 RENESAS_SDHI_SCC_DTCNTL_TAPNUM_SHIFT) &
78                 RENESAS_SDHI_SCC_DTCNTL_TAPNUM_MASK;
79 }
80
81 static void renesas_sdhi_reset_tuning(struct tmio_sd_priv *priv)
82 {
83         u32 reg;
84
85         /* Reset SCC */
86         reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
87         reg &= ~TMIO_SD_CLKCTL_SCLKEN;
88         tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
89
90         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_CKSEL);
91         reg &= ~RENESAS_SDHI_SCC_CKSEL_DTSEL;
92         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_CKSEL);
93
94         reg = tmio_sd_readl(priv, TMIO_SD_CLKCTL);
95         reg |= TMIO_SD_CLKCTL_SCLKEN;
96         tmio_sd_writel(priv, reg, TMIO_SD_CLKCTL);
97
98         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
99         reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
100         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
101
102         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
103         reg &= ~RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
104         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
105 }
106
107 static void renesas_sdhi_prepare_tuning(struct tmio_sd_priv *priv,
108                                        unsigned long tap)
109 {
110         /* Set sampling clock position */
111         tmio_sd_writel(priv, tap, RENESAS_SDHI_SCC_TAPSET);
112 }
113
114 static unsigned int renesas_sdhi_compare_scc_data(struct tmio_sd_priv *priv)
115 {
116         /* Get comparison of sampling data */
117         return tmio_sd_readl(priv, RENESAS_SDHI_SCC_SMPCMP);
118 }
119
120 static int renesas_sdhi_select_tuning(struct tmio_sd_priv *priv,
121                                      unsigned int tap_num, unsigned int taps,
122                                      unsigned int smpcmp)
123 {
124         unsigned long tap_cnt;  /* counter of tuning success */
125         unsigned long tap_set;  /* tap position */
126         unsigned long tap_start;/* start position of tuning success */
127         unsigned long tap_end;  /* end position of tuning success */
128         unsigned long ntap;     /* temporary counter of tuning success */
129         unsigned long match_cnt;/* counter of matching data */
130         unsigned long i;
131         bool select = false;
132         u32 reg;
133
134         /* Clear SCC_RVSREQ */
135         tmio_sd_writel(priv, 0, RENESAS_SDHI_SCC_RVSREQ);
136
137         /* Merge the results */
138         for (i = 0; i < tap_num * 2; i++) {
139                 if (!(taps & BIT(i))) {
140                         taps &= ~BIT(i % tap_num);
141                         taps &= ~BIT((i % tap_num) + tap_num);
142                 }
143                 if (!(smpcmp & BIT(i))) {
144                         smpcmp &= ~BIT(i % tap_num);
145                         smpcmp &= ~BIT((i % tap_num) + tap_num);
146                 }
147         }
148
149         /*
150          * Find the longest consecutive run of successful probes.  If that
151          * is more than RENESAS_SDHI_MAX_TAP probes long then use the
152          * center index as the tap.
153          */
154         tap_cnt = 0;
155         ntap = 0;
156         tap_start = 0;
157         tap_end = 0;
158         for (i = 0; i < tap_num * 2; i++) {
159                 if (taps & BIT(i))
160                         ntap++;
161                 else {
162                         if (ntap > tap_cnt) {
163                                 tap_start = i - ntap;
164                                 tap_end = i - 1;
165                                 tap_cnt = ntap;
166                         }
167                         ntap = 0;
168                 }
169         }
170
171         if (ntap > tap_cnt) {
172                 tap_start = i - ntap;
173                 tap_end = i - 1;
174                 tap_cnt = ntap;
175         }
176
177         /*
178          * If all of the TAP is OK, the sampling clock position is selected by
179          * identifying the change point of data.
180          */
181         if (tap_cnt == tap_num * 2) {
182                 match_cnt = 0;
183                 ntap = 0;
184                 tap_start = 0;
185                 tap_end = 0;
186                 for (i = 0; i < tap_num * 2; i++) {
187                         if (smpcmp & BIT(i))
188                                 ntap++;
189                         else {
190                                 if (ntap > match_cnt) {
191                                         tap_start = i - ntap;
192                                         tap_end = i - 1;
193                                         match_cnt = ntap;
194                                 }
195                                 ntap = 0;
196                         }
197                 }
198                 if (ntap > match_cnt) {
199                         tap_start = i - ntap;
200                         tap_end = i - 1;
201                         match_cnt = ntap;
202                 }
203                 if (match_cnt)
204                         select = true;
205         } else if (tap_cnt >= RENESAS_SDHI_MAX_TAP)
206                 select = true;
207
208         if (select)
209                 tap_set = ((tap_start + tap_end) / 2) % tap_num;
210         else
211                 return -EIO;
212
213         /* Set SCC */
214         tmio_sd_writel(priv, tap_set, RENESAS_SDHI_SCC_TAPSET);
215
216         /* Enable auto re-tuning */
217         reg = tmio_sd_readl(priv, RENESAS_SDHI_SCC_RVSCNTL);
218         reg |= RENESAS_SDHI_SCC_RVSCNTL_RVSEN;
219         tmio_sd_writel(priv, reg, RENESAS_SDHI_SCC_RVSCNTL);
220
221         return 0;
222 }
223
224 int renesas_sdhi_execute_tuning(struct udevice *dev, uint opcode)
225 {
226         struct tmio_sd_priv *priv = dev_get_priv(dev);
227         struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
228         struct mmc *mmc = upriv->mmc;
229         unsigned int tap_num;
230         unsigned int taps = 0, smpcmp = 0;
231         int i, ret = 0;
232         u32 caps;
233
234         /* Only supported on Renesas RCar */
235         if (!(priv->caps & TMIO_SD_CAP_RCAR_UHS))
236                 return -EINVAL;
237
238         /* clock tuning is not needed for upto 52MHz */
239         if (!((mmc->selected_mode == MMC_HS_200) ||
240               (mmc->selected_mode == UHS_SDR104) ||
241               (mmc->selected_mode == UHS_SDR50)))
242                 return 0;
243
244         tap_num = renesas_sdhi_init_tuning(priv);
245         if (!tap_num)
246                 /* Tuning is not supported */
247                 goto out;
248
249         if (tap_num * 2 >= sizeof(taps) * 8) {
250                 dev_err(dev,
251                         "Too many taps, skipping tuning. Please consider updating size of taps field of tmio_mmc_host\n");
252                 goto out;
253         }
254
255         /* Issue CMD19 twice for each tap */
256         for (i = 0; i < 2 * tap_num; i++) {
257                 renesas_sdhi_prepare_tuning(priv, i % tap_num);
258
259                 /* Force PIO for the tuning */
260                 caps = priv->caps;
261                 priv->caps &= ~TMIO_SD_CAP_DMA_INTERNAL;
262
263                 ret = mmc_send_tuning(mmc, opcode, NULL);
264
265                 priv->caps = caps;
266
267                 if (ret == 0)
268                         taps |= BIT(i);
269
270                 ret = renesas_sdhi_compare_scc_data(priv);
271                 if (ret == 0)
272                         smpcmp |= BIT(i);
273
274                 mdelay(1);
275         }
276
277         ret = renesas_sdhi_select_tuning(priv, tap_num, taps, smpcmp);
278
279 out:
280         if (ret < 0) {
281                 dev_warn(dev, "Tuning procedure failed\n");
282                 renesas_sdhi_reset_tuning(priv);
283         }
284
285         return ret;
286 }
287 #endif
288
289 static int renesas_sdhi_set_ios(struct udevice *dev)
290 {
291         int ret = tmio_sd_set_ios(dev);
292
293         mdelay(10);
294
295 #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
296         struct tmio_sd_priv *priv = dev_get_priv(dev);
297
298         renesas_sdhi_reset_tuning(priv);
299 #endif
300
301         return ret;
302 }
303
304 static const struct dm_mmc_ops renesas_sdhi_ops = {
305         .send_cmd = tmio_sd_send_cmd,
306         .set_ios = renesas_sdhi_set_ios,
307         .get_cd = tmio_sd_get_cd,
308 #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
309         .execute_tuning = renesas_sdhi_execute_tuning,
310 #endif
311 };
312
313 #define RENESAS_GEN2_QUIRKS     TMIO_SD_CAP_RCAR_GEN2
314 #define RENESAS_GEN3_QUIRKS                             \
315         TMIO_SD_CAP_64BIT | TMIO_SD_CAP_RCAR_GEN3 | TMIO_SD_CAP_RCAR_UHS
316
317 static const struct udevice_id renesas_sdhi_match[] = {
318         { .compatible = "renesas,sdhi-r8a7790", .data = RENESAS_GEN2_QUIRKS },
319         { .compatible = "renesas,sdhi-r8a7791", .data = RENESAS_GEN2_QUIRKS },
320         { .compatible = "renesas,sdhi-r8a7792", .data = RENESAS_GEN2_QUIRKS },
321         { .compatible = "renesas,sdhi-r8a7793", .data = RENESAS_GEN2_QUIRKS },
322         { .compatible = "renesas,sdhi-r8a7794", .data = RENESAS_GEN2_QUIRKS },
323         { .compatible = "renesas,sdhi-r8a7795", .data = RENESAS_GEN3_QUIRKS },
324         { .compatible = "renesas,sdhi-r8a7796", .data = RENESAS_GEN3_QUIRKS },
325         { .compatible = "renesas,sdhi-r8a77965", .data = RENESAS_GEN3_QUIRKS },
326         { .compatible = "renesas,sdhi-r8a77970", .data = RENESAS_GEN3_QUIRKS },
327         { .compatible = "renesas,sdhi-r8a77995", .data = RENESAS_GEN3_QUIRKS },
328         { /* sentinel */ }
329 };
330
331 static int renesas_sdhi_probe(struct udevice *dev)
332 {
333         struct tmio_sd_priv *priv = dev_get_priv(dev);
334         u32 quirks = dev_get_driver_data(dev);
335         struct fdt_resource reg_res;
336         struct clk clk;
337         DECLARE_GLOBAL_DATA_PTR;
338         int ret;
339
340         if (quirks == RENESAS_GEN2_QUIRKS) {
341                 ret = fdt_get_resource(gd->fdt_blob, dev_of_offset(dev),
342                                        "reg", 0, &reg_res);
343                 if (ret < 0) {
344                         dev_err(dev, "\"reg\" resource not found, ret=%i\n",
345                                 ret);
346                         return ret;
347                 }
348
349                 if (fdt_resource_size(&reg_res) == 0x100)
350                         quirks |= TMIO_SD_CAP_16BIT;
351         }
352
353         ret = clk_get_by_index(dev, 0, &clk);
354         if (ret < 0) {
355                 dev_err(dev, "failed to get host clock\n");
356                 return ret;
357         }
358
359         /* set to max rate */
360         priv->mclk = clk_set_rate(&clk, ULONG_MAX);
361         if (IS_ERR_VALUE(priv->mclk)) {
362                 dev_err(dev, "failed to set rate for host clock\n");
363                 clk_free(&clk);
364                 return priv->mclk;
365         }
366
367         ret = clk_enable(&clk);
368         clk_free(&clk);
369         if (ret) {
370                 dev_err(dev, "failed to enable host clock\n");
371                 return ret;
372         }
373
374         ret = tmio_sd_probe(dev, quirks);
375 #if CONFIG_IS_ENABLED(MMC_HS200_SUPPORT)
376         if (!ret)
377                 renesas_sdhi_reset_tuning(dev_get_priv(dev));
378 #endif
379         return ret;
380 }
381
382 U_BOOT_DRIVER(renesas_sdhi) = {
383         .name = "renesas-sdhi",
384         .id = UCLASS_MMC,
385         .of_match = renesas_sdhi_match,
386         .bind = tmio_sd_bind,
387         .probe = renesas_sdhi_probe,
388         .priv_auto_alloc_size = sizeof(struct tmio_sd_priv),
389         .platdata_auto_alloc_size = sizeof(struct tmio_sd_plat),
390         .ops = &renesas_sdhi_ops,
391 };