treewide: convert (void *)devfdt_get_addr() to dev_read_addr_ptr()
[platform/kernel/u-boot.git] / drivers / mmc / xenon_sdhci.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Driver for Marvell SOC Platform Group Xenon SDHC as a platform device
4  *
5  * Copyright (C) 2016 Marvell, All Rights Reserved.
6  *
7  * Author:      Victor Gu <xigu@marvell.com>
8  * Date:        2016-8-24
9  *
10  * Included parts of the Linux driver version which was written by:
11  * Hu Ziji <huziji@marvell.com>
12  *
13  * Ported to from Marvell 2015.01 to mainline U-Boot 2017.01:
14  * Stefan Roese <sr@denx.de>
15  */
16
17 #include <common.h>
18 #include <dm.h>
19 #include <fdtdec.h>
20 #include <linux/bitops.h>
21 #include <linux/delay.h>
22 #include <linux/libfdt.h>
23 #include <malloc.h>
24 #include <sdhci.h>
25
26 DECLARE_GLOBAL_DATA_PTR;
27
28 /* Register Offset of SD Host Controller SOCP self-defined register */
29 #define SDHC_SYS_CFG_INFO                       0x0104
30 #define SLOT_TYPE_SDIO_SHIFT                    24
31 #define SLOT_TYPE_EMMC_MASK                     0xFF
32 #define SLOT_TYPE_EMMC_SHIFT                    16
33 #define SLOT_TYPE_SD_SDIO_MMC_MASK              0xFF
34 #define SLOT_TYPE_SD_SDIO_MMC_SHIFT             8
35 #define NR_SUPPORTED_SLOT_MASK                  0x7
36
37 #define SDHC_SYS_OP_CTRL                        0x0108
38 #define AUTO_CLKGATE_DISABLE_MASK               BIT(20)
39 #define SDCLK_IDLEOFF_ENABLE_SHIFT              8
40 #define SLOT_ENABLE_SHIFT                       0
41
42 #define SDHC_SYS_EXT_OP_CTRL                    0x010C
43 #define MASK_CMD_CONFLICT_ERROR                 BIT(8)
44
45 #define SDHC_SLOT_RETUNING_REQ_CTRL             0x0144
46 /* retuning compatible */
47 #define RETUNING_COMPATIBLE                     0x1
48
49 /* Xenon specific Mode Select value */
50 #define XENON_SDHCI_CTRL_HS200                  0x5
51 #define XENON_SDHCI_CTRL_HS400                  0x6
52
53 #define EMMC_PHY_REG_BASE                       0x170
54 #define EMMC_PHY_TIMING_ADJUST                  EMMC_PHY_REG_BASE
55 #define OUTPUT_QSN_PHASE_SELECT                 BIT(17)
56 #define SAMPL_INV_QSP_PHASE_SELECT              BIT(18)
57 #define SAMPL_INV_QSP_PHASE_SELECT_SHIFT        18
58 #define EMMC_PHY_SLOW_MODE                      BIT(29)
59 #define PHY_INITIALIZAION                       BIT(31)
60 #define WAIT_CYCLE_BEFORE_USING_MASK            0xf
61 #define WAIT_CYCLE_BEFORE_USING_SHIFT           12
62 #define FC_SYNC_EN_DURATION_MASK                0xf
63 #define FC_SYNC_EN_DURATION_SHIFT               8
64 #define FC_SYNC_RST_EN_DURATION_MASK            0xf
65 #define FC_SYNC_RST_EN_DURATION_SHIFT           4
66 #define FC_SYNC_RST_DURATION_MASK               0xf
67 #define FC_SYNC_RST_DURATION_SHIFT              0
68
69 #define EMMC_PHY_FUNC_CONTROL                   (EMMC_PHY_REG_BASE + 0x4)
70 #define DQ_ASYNC_MODE                           BIT(4)
71 #define DQ_DDR_MODE_SHIFT                       8
72 #define DQ_DDR_MODE_MASK                        0xff
73 #define CMD_DDR_MODE                            BIT(16)
74
75 #define EMMC_PHY_PAD_CONTROL                    (EMMC_PHY_REG_BASE + 0x8)
76 #define REC_EN_SHIFT                            24
77 #define REC_EN_MASK                             0xf
78 #define FC_DQ_RECEN                             BIT(24)
79 #define FC_CMD_RECEN                            BIT(25)
80 #define FC_QSP_RECEN                            BIT(26)
81 #define FC_QSN_RECEN                            BIT(27)
82 #define OEN_QSN                                 BIT(28)
83 #define AUTO_RECEN_CTRL                         BIT(30)
84
85 #define EMMC_PHY_PAD_CONTROL1                   (EMMC_PHY_REG_BASE + 0xc)
86 #define EMMC5_1_FC_QSP_PD                       BIT(9)
87 #define EMMC5_1_FC_QSP_PU                       BIT(25)
88 #define EMMC5_1_FC_CMD_PD                       BIT(8)
89 #define EMMC5_1_FC_CMD_PU                       BIT(24)
90 #define EMMC5_1_FC_DQ_PD                        0xff
91 #define EMMC5_1_FC_DQ_PU                        (0xff << 16)
92
93 #define SDHCI_RETUNE_EVT_INTSIG                 0x00001000
94
95 /* Hyperion only have one slot 0 */
96 #define XENON_MMC_SLOT_ID_HYPERION              0
97
98 #define MMC_TIMING_LEGACY       0
99 #define MMC_TIMING_MMC_HS       1
100 #define MMC_TIMING_SD_HS        2
101 #define MMC_TIMING_UHS_SDR12    3
102 #define MMC_TIMING_UHS_SDR25    4
103 #define MMC_TIMING_UHS_SDR50    5
104 #define MMC_TIMING_UHS_SDR104   6
105 #define MMC_TIMING_UHS_DDR50    7
106 #define MMC_TIMING_MMC_DDR52    8
107 #define MMC_TIMING_MMC_HS200    9
108 #define MMC_TIMING_MMC_HS400    10
109
110 #define XENON_MMC_MAX_CLK       400000000
111
112 enum soc_pad_ctrl_type {
113         SOC_PAD_SD,
114         SOC_PAD_FIXED_1_8V,
115 };
116
117 struct xenon_sdhci_plat {
118         struct mmc_config cfg;
119         struct mmc mmc;
120 };
121
122 struct xenon_sdhci_priv {
123         struct sdhci_host host;
124
125         u8 timing;
126
127         unsigned int clock;
128
129         void *pad_ctrl_reg;
130         int pad_type;
131 };
132
133 static int xenon_mmc_phy_init(struct sdhci_host *host)
134 {
135         struct xenon_sdhci_priv *priv = host->mmc->priv;
136         u32 clock = priv->clock;
137         u32 time;
138         u32 var;
139
140         /* Enable QSP PHASE SELECT */
141         var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
142         var |= SAMPL_INV_QSP_PHASE_SELECT;
143         if ((priv->timing == MMC_TIMING_UHS_SDR50) ||
144             (priv->timing == MMC_TIMING_UHS_SDR25) ||
145             (priv->timing == MMC_TIMING_UHS_SDR12) ||
146             (priv->timing == MMC_TIMING_SD_HS) ||
147             (priv->timing == MMC_TIMING_LEGACY))
148                 var |= EMMC_PHY_SLOW_MODE;
149         sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST);
150
151         /* Poll for host MMC PHY clock init to be stable */
152         /* Wait up to 10ms */
153         time = 100;
154         while (time--) {
155                 var = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
156                 if (var & SDHCI_CLOCK_INT_STABLE)
157                         break;
158
159                 udelay(100);
160         }
161
162         if (time <= 0) {
163                 pr_err("Failed to enable MMC internal clock in time\n");
164                 return -ETIMEDOUT;
165         }
166
167         /* Init PHY */
168         var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
169         var |= PHY_INITIALIZAION;
170         sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST);
171
172         if (clock == 0) {
173                 /* Use the possibly slowest bus frequency value */
174                 clock = 100000;
175         }
176
177         /* Poll for host eMMC PHY init to complete */
178         /* Wait up to 10ms */
179         time = 100;
180         while (time--) {
181                 var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
182                 var &= PHY_INITIALIZAION;
183                 if (!var)
184                         break;
185
186                 /* wait for host eMMC PHY init to complete */
187                 udelay(100);
188         }
189
190         if (time <= 0) {
191                 pr_err("Failed to init MMC PHY in time\n");
192                 return -ETIMEDOUT;
193         }
194
195         return 0;
196 }
197
198 #define ARMADA_3700_SOC_PAD_1_8V        0x1
199 #define ARMADA_3700_SOC_PAD_3_3V        0x0
200
201 static void armada_3700_soc_pad_voltage_set(struct sdhci_host *host)
202 {
203         struct xenon_sdhci_priv *priv = host->mmc->priv;
204
205         if (priv->pad_type == SOC_PAD_FIXED_1_8V)
206                 writel(ARMADA_3700_SOC_PAD_1_8V, priv->pad_ctrl_reg);
207         else if (priv->pad_type == SOC_PAD_SD)
208                 writel(ARMADA_3700_SOC_PAD_3_3V, priv->pad_ctrl_reg);
209 }
210
211 static void xenon_mmc_phy_set(struct sdhci_host *host)
212 {
213         struct xenon_sdhci_priv *priv = host->mmc->priv;
214         u32 var;
215
216         /* Setup pad, set bit[30], bit[28] and bits[26:24] */
217         var = sdhci_readl(host, EMMC_PHY_PAD_CONTROL);
218         var |= AUTO_RECEN_CTRL | OEN_QSN | FC_QSP_RECEN |
219                 FC_CMD_RECEN | FC_DQ_RECEN;
220         sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL);
221
222         /* Set CMD and DQ Pull Up */
223         var = sdhci_readl(host, EMMC_PHY_PAD_CONTROL1);
224         var |= (EMMC5_1_FC_CMD_PU | EMMC5_1_FC_DQ_PU);
225         var &= ~(EMMC5_1_FC_CMD_PD | EMMC5_1_FC_DQ_PD);
226         sdhci_writel(host, var, EMMC_PHY_PAD_CONTROL1);
227
228         /*
229          * If timing belongs to high speed, set bit[17] of
230          * EMMC_PHY_TIMING_ADJUST register
231          */
232         if ((priv->timing == MMC_TIMING_MMC_HS400) ||
233             (priv->timing == MMC_TIMING_MMC_HS200) ||
234             (priv->timing == MMC_TIMING_UHS_SDR50) ||
235             (priv->timing == MMC_TIMING_UHS_SDR104) ||
236             (priv->timing == MMC_TIMING_UHS_DDR50) ||
237             (priv->timing == MMC_TIMING_UHS_SDR25) ||
238             (priv->timing == MMC_TIMING_MMC_DDR52)) {
239                 var = sdhci_readl(host, EMMC_PHY_TIMING_ADJUST);
240                 var |= OUTPUT_QSN_PHASE_SELECT;
241                 sdhci_writel(host, var, EMMC_PHY_TIMING_ADJUST);
242         }
243
244         /*
245          * When setting EMMC_PHY_FUNC_CONTROL register,
246          * SD clock should be disabled
247          */
248         var = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
249         var &= ~SDHCI_CLOCK_CARD_EN;
250         sdhci_writew(host, var, SDHCI_CLOCK_CONTROL);
251
252         var = sdhci_readl(host, EMMC_PHY_FUNC_CONTROL);
253         if (host->mmc->ddr_mode) {
254                 var |= (DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) | CMD_DDR_MODE;
255         } else {
256                 var &= ~((DQ_DDR_MODE_MASK << DQ_DDR_MODE_SHIFT) |
257                          CMD_DDR_MODE);
258         }
259         sdhci_writel(host, var, EMMC_PHY_FUNC_CONTROL);
260
261         /* Enable bus clock */
262         var = sdhci_readl(host, SDHCI_CLOCK_CONTROL);
263         var |= SDHCI_CLOCK_CARD_EN;
264         sdhci_writew(host, var, SDHCI_CLOCK_CONTROL);
265
266         xenon_mmc_phy_init(host);
267 }
268
269 /* Enable/Disable the Auto Clock Gating function of this slot */
270 static void xenon_mmc_set_acg(struct sdhci_host *host, bool enable)
271 {
272         u32 var;
273
274         var = sdhci_readl(host, SDHC_SYS_OP_CTRL);
275         if (enable)
276                 var &= ~AUTO_CLKGATE_DISABLE_MASK;
277         else
278                 var |= AUTO_CLKGATE_DISABLE_MASK;
279
280         sdhci_writel(host, var, SDHC_SYS_OP_CTRL);
281 }
282
283 #define SLOT_MASK(slot)         BIT(slot)
284
285 /* Enable specific slot */
286 static void xenon_mmc_enable_slot(struct sdhci_host *host, u8 slot)
287 {
288         u32 var;
289
290         var = sdhci_readl(host, SDHC_SYS_OP_CTRL);
291         var |= SLOT_MASK(slot) << SLOT_ENABLE_SHIFT;
292         sdhci_writel(host, var, SDHC_SYS_OP_CTRL);
293 }
294
295 /* Enable Parallel Transfer Mode */
296 static void xenon_mmc_enable_parallel_tran(struct sdhci_host *host, u8 slot)
297 {
298         u32 var;
299
300         var = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
301         var |= SLOT_MASK(slot);
302         sdhci_writel(host, var, SDHC_SYS_EXT_OP_CTRL);
303 }
304
305 static void xenon_mmc_disable_tuning(struct sdhci_host *host, u8 slot)
306 {
307         u32 var;
308
309         /* Clear the Re-Tuning Request functionality */
310         var = sdhci_readl(host, SDHC_SLOT_RETUNING_REQ_CTRL);
311         var &= ~RETUNING_COMPATIBLE;
312         sdhci_writel(host, var, SDHC_SLOT_RETUNING_REQ_CTRL);
313
314         /* Clear the Re-tuning Event Signal Enable */
315         var = sdhci_readl(host, SDHCI_SIGNAL_ENABLE);
316         var &= ~SDHCI_RETUNE_EVT_INTSIG;
317         sdhci_writel(host, var, SDHCI_SIGNAL_ENABLE);
318 }
319
320 /* Mask command conflict error */
321 static void xenon_mask_cmd_conflict_err(struct sdhci_host *host)
322 {
323         u32  reg;
324
325         reg = sdhci_readl(host, SDHC_SYS_EXT_OP_CTRL);
326         reg |= MASK_CMD_CONFLICT_ERROR;
327         sdhci_writel(host, reg, SDHC_SYS_EXT_OP_CTRL);
328 }
329
330 /* Platform specific function for post set_ios configuration */
331 static int xenon_sdhci_set_ios_post(struct sdhci_host *host)
332 {
333         struct xenon_sdhci_priv *priv = host->mmc->priv;
334         uint speed = host->mmc->tran_speed;
335         int pwr_18v = 0;
336
337         if ((sdhci_readb(host, SDHCI_POWER_CONTROL) & ~SDHCI_POWER_ON) ==
338             SDHCI_POWER_180)
339                 pwr_18v = 1;
340
341         /* Set timing variable according to the configured speed */
342         if (IS_SD(host->mmc)) {
343                 /* SD/SDIO */
344                 if (pwr_18v) {
345                         if (host->mmc->ddr_mode)
346                                 priv->timing = MMC_TIMING_UHS_DDR50;
347                         else if (speed <= 25000000)
348                                 priv->timing = MMC_TIMING_UHS_SDR25;
349                         else
350                                 priv->timing = MMC_TIMING_UHS_SDR50;
351                 } else {
352                         if (speed <= 25000000)
353                                 priv->timing = MMC_TIMING_LEGACY;
354                         else
355                                 priv->timing = MMC_TIMING_SD_HS;
356                 }
357         } else {
358                 /* eMMC */
359                 if (host->mmc->ddr_mode)
360                         priv->timing = MMC_TIMING_MMC_DDR52;
361                 else if (speed <= 26000000)
362                         priv->timing = MMC_TIMING_LEGACY;
363                 else
364                         priv->timing = MMC_TIMING_MMC_HS;
365         }
366
367         /* Re-init the PHY */
368         xenon_mmc_phy_set(host);
369
370         return 0;
371 }
372
373 /* Install a driver specific handler for post set_ios configuration */
374 static const struct sdhci_ops xenon_sdhci_ops = {
375         .set_ios_post = xenon_sdhci_set_ios_post
376 };
377
378 static int xenon_sdhci_probe(struct udevice *dev)
379 {
380         struct xenon_sdhci_plat *plat = dev_get_platdata(dev);
381         struct mmc_uclass_priv *upriv = dev_get_uclass_priv(dev);
382         struct xenon_sdhci_priv *priv = dev_get_priv(dev);
383         struct sdhci_host *host = dev_get_priv(dev);
384         int ret;
385
386         host->mmc = &plat->mmc;
387         host->mmc->priv = host;
388         host->mmc->dev = dev;
389         upriv->mmc = host->mmc;
390
391         /* Set quirks */
392         host->quirks = SDHCI_QUIRK_WAIT_SEND_CMD | SDHCI_QUIRK_32BIT_DMA_ADDR;
393
394         /* Set default timing */
395         priv->timing = MMC_TIMING_LEGACY;
396
397         /* Disable auto clock gating during init */
398         xenon_mmc_set_acg(host, false);
399
400         /* Enable slot */
401         xenon_mmc_enable_slot(host, XENON_MMC_SLOT_ID_HYPERION);
402
403         /*
404          * Set default power on SoC PHY PAD register (currently only
405          * available on the Armada 3700)
406          */
407         if (priv->pad_ctrl_reg)
408                 armada_3700_soc_pad_voltage_set(host);
409
410         host->host_caps = MMC_MODE_HS | MMC_MODE_HS_52MHz | MMC_MODE_DDR_52MHz;
411         switch (fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), "bus-width",
412                 1)) {
413         case 8:
414                 host->host_caps |= MMC_MODE_8BIT;
415                 break;
416         case 4:
417                 host->host_caps |= MMC_MODE_4BIT;
418                 break;
419         case 1:
420                 break;
421         default:
422                 printf("Invalid \"bus-width\" value\n");
423                 return -EINVAL;
424         }
425
426         host->ops = &xenon_sdhci_ops;
427
428         host->max_clk = XENON_MMC_MAX_CLK;
429         ret = sdhci_setup_cfg(&plat->cfg, host, 0, 0);
430         if (ret)
431                 return ret;
432
433         ret = sdhci_probe(dev);
434         if (ret)
435                 return ret;
436
437         /* Enable parallel transfer */
438         xenon_mmc_enable_parallel_tran(host, XENON_MMC_SLOT_ID_HYPERION);
439
440         /* Disable tuning functionality of this slot */
441         xenon_mmc_disable_tuning(host, XENON_MMC_SLOT_ID_HYPERION);
442
443         /* Enable auto clock gating after init */
444         xenon_mmc_set_acg(host, true);
445
446         xenon_mask_cmd_conflict_err(host);
447
448         return ret;
449 }
450
451 static int xenon_sdhci_ofdata_to_platdata(struct udevice *dev)
452 {
453         struct sdhci_host *host = dev_get_priv(dev);
454         struct xenon_sdhci_priv *priv = dev_get_priv(dev);
455         const char *name;
456
457         host->name = dev->name;
458         host->ioaddr = dev_read_addr_ptr(dev);
459
460         if (device_is_compatible(dev, "marvell,armada-3700-sdhci"))
461                 priv->pad_ctrl_reg = (void *)devfdt_get_addr_index(dev, 1);
462
463         name = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "marvell,pad-type",
464                            NULL);
465         if (name) {
466                 if (0 == strncmp(name, "sd", 2)) {
467                         priv->pad_type = SOC_PAD_SD;
468                 } else if (0 == strncmp(name, "fixed-1-8v", 10)) {
469                         priv->pad_type = SOC_PAD_FIXED_1_8V;
470                 } else {
471                         printf("Unsupported SOC PHY PAD ctrl type %s\n", name);
472                         return -EINVAL;
473                 }
474         }
475
476         return 0;
477 }
478
479 static int xenon_sdhci_bind(struct udevice *dev)
480 {
481         struct xenon_sdhci_plat *plat = dev_get_platdata(dev);
482
483         return sdhci_bind(dev, &plat->mmc, &plat->cfg);
484 }
485
486 static const struct udevice_id xenon_sdhci_ids[] = {
487         { .compatible = "marvell,armada-8k-sdhci",},
488         { .compatible = "marvell,armada-3700-sdhci",},
489         { }
490 };
491
492 U_BOOT_DRIVER(xenon_sdhci_drv) = {
493         .name           = "xenon_sdhci",
494         .id             = UCLASS_MMC,
495         .of_match       = xenon_sdhci_ids,
496         .ofdata_to_platdata = xenon_sdhci_ofdata_to_platdata,
497         .ops            = &sdhci_ops,
498         .bind           = xenon_sdhci_bind,
499         .probe          = xenon_sdhci_probe,
500         .priv_auto_alloc_size = sizeof(struct xenon_sdhci_priv),
501         .platdata_auto_alloc_size = sizeof(struct xenon_sdhci_plat),
502 };