hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
u-boot/drivers/mmc/rockchip_sdhci.c
....@@ -39,6 +39,12 @@
3939 ((((x) >> PHYCTRL_DLLRDY_SHIFT) & PHYCTRL_DLLRDY_MASK) ==\
4040 PHYCTRL_DLLRDY_DONE)
4141
42
+#define ARASAN_VENDOR_REGISTER 0x78
43
+#define ARASAN_VENDOR_ENHANCED_STROBE BIT(0)
44
+
45
+/* DWC IP vendor area 1 pointer */
46
+#define DWCMSHC_P_VENDOR_AREA1 0xe8
47
+#define DWCMSHC_AREA1_MASK GENMASK(11, 0)
4248 /* Rockchip specific Registers */
4349 #define DWCMSHC_CTRL_HS400 0x7
4450 #define DWCMSHC_CARD_IS_EMMC BIT(0)
....@@ -46,6 +52,7 @@
4652
4753 #define DWCMSHC_HOST_CTRL3 0x508
4854 #define DWCMSHC_EMMC_CONTROL 0x52c
55
+#define DWCMSHC_EMMC_ATCTRL 0x540
4956 #define DWCMSHC_EMMC_DLL_CTRL 0x800
5057 #define DWCMSHC_EMMC_DLL_CTRL_RESET BIT(1)
5158 #define DWCMSHC_EMMC_DLL_RXCLK 0x804
....@@ -55,25 +62,31 @@
5562 #define DWCMSHC_EMMC_DLL_STATUS0 0x840
5663 #define DWCMSHC_EMMC_DLL_STATUS1 0x844
5764 #define DWCMSHC_EMMC_DLL_START BIT(0)
58
-#define DWCMSHC_EMMC_DLL_RXCLK_SRCSEL 29
5965 #define DWCMSHC_EMMC_DLL_START_POINT 16
6066 #define DWCMSHC_EMMC_DLL_START_DEFAULT 5
6167 #define DWCMSHC_EMMC_DLL_INC_VALUE 2
6268 #define DWCMSHC_EMMC_DLL_INC 8
69
+#define DWCMSHC_EMMC_DLL_BYPASS BIT(24)
6370 #define DWCMSHC_EMMC_DLL_DLYENA BIT(27)
6471 #define DLL_TXCLK_TAPNUM_DEFAULT 0x10
65
-#define DLL_TXCLK_TAPNUM_90_DEGREES 0x8
66
-#define DLL_STRBIN_TAPNUM_DEFAULT 0x3
72
+#define DLL_TXCLK_TAPNUM_90_DEGREES 0x9
73
+#define DLL_STRBIN_TAPNUM_DEFAULT 0x4
74
+#define DLL_STRBIN_DELAY_NUM_OFFSET 16
75
+#define DLL_STRBIN_TAPNUM_FROM_SW BIT(24)
76
+#define DLL_STRBIN_DELAY_NUM_SEL BIT(26)
6777 #define DLL_TXCLK_TAPNUM_FROM_SW BIT(24)
6878 #define DLL_TXCLK_NO_INVERTER BIT(29)
6979 #define DWCMSHC_EMMC_DLL_LOCKED BIT(8)
7080 #define DWCMSHC_EMMC_DLL_TIMEOUT BIT(9)
71
-#define DLL_RXCLK_NO_INVERTER 1
72
-#define DLL_RXCLK_INVERTER 0
81
+#define DLL_TAP_VALUE_SEL BIT(25)
82
+#define DLL_TAP_VALUE_OFFSET 8
83
+#define DLL_RXCLK_NO_INVERTER BIT(29)
84
+#define DLL_RXCLK_ORI_GATE BIT(31)
7385 #define DLL_CMDOUT_TAPNUM_90_DEGREES 0x8
7486 #define DLL_CMDOUT_TAPNUM_FROM_SW BIT(24)
7587 #define DLL_CMDOUT_SRC_CLK_NEG BIT(28)
7688 #define DLL_CMDOUT_EN_SRC_CLK_NEG BIT(29)
89
+#define DLL_CMDOUT_BOTH_CLK_EDGE BIT(30)
7790
7891 #define DWCMSHC_ENHANCED_STROBE BIT(8)
7992 #define DLL_LOCK_WO_TMOUT(x) \
....@@ -106,10 +119,18 @@
106119 struct sdhci_data {
107120 int (*emmc_set_clock)(struct sdhci_host *host, unsigned int clock);
108121 void (*set_ios_post)(struct sdhci_host *host);
122
+ int (*set_enhanced_strobe)(struct sdhci_host *host);
109123 int (*get_phy)(struct udevice *dev);
110124 u32 flags;
111125 #define RK_DLL_CMD_OUT BIT(1)
112126 #define RK_RXCLK_NO_INVERTER BIT(2)
127
+#define RK_TAP_VALUE_SEL BIT(3)
128
+
129
+ u8 hs200_tx_tap;
130
+ u8 hs400_tx_tap;
131
+ u8 hs400_cmd_tap;
132
+ u8 hs400_strbin_tap;
133
+ u8 ddr50_strbin_delay_num;
113134 };
114135
115136 static void rk3399_emmc_phy_power_on(struct rockchip_emmc_phy *phy, u32 clock)
....@@ -254,21 +275,7 @@
254275 clk |= SDHCI_CLOCK_INT_EN;
255276 sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
256277
257
- /* Wait max 20 ms */
258
- timeout = 20;
259
- while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL))
260
- & SDHCI_CLOCK_INT_STABLE)) {
261
- if (timeout == 0) {
262
- printf("%s: Internal clock never stabilised.\n",
263
- __func__);
264
- return -EBUSY;
265
- }
266
- timeout--;
267
- udelay(1000);
268
- }
269
- clk |= SDHCI_CLOCK_CARD_EN;
270
- sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL);
271
- host->clock = clock;
278
+ sdhci_enable_clk(host, clk);
272279
273280 return 0;
274281 }
....@@ -323,16 +330,24 @@
323330 {
324331 struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
325332 struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
326
- u32 extra;
333
+ u32 txclk_tapnum, extra, dll_lock_value;
327334 int timeout = 500, ret;
328335
329336 ret = rockchip_emmc_set_clock(host, clock);
337
+
338
+ /* Disable output clock while config DLL */
339
+ sdhci_writew(host, 0, SDHCI_CLOCK_CONTROL);
330340
331341 if (clock >= 100 * MHz) {
332342 /* reset DLL */
333343 sdhci_writel(host, DWCMSHC_EMMC_DLL_CTRL_RESET, DWCMSHC_EMMC_DLL_CTRL);
334344 udelay(1);
335345 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
346
+
347
+ extra = 0x1 << 16 | /* tune clock stop en */
348
+ 0x2 << 17 | /* pre-change delay */
349
+ 0x3 << 19; /* post-change delay */
350
+ sdhci_writel(host, extra, DWCMSHC_EMMC_ATCTRL);
336351
337352 /* Init DLL settings */
338353 extra = DWCMSHC_EMMC_DLL_START_DEFAULT << DWCMSHC_EMMC_DLL_START_POINT |
....@@ -341,48 +356,106 @@
341356 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_CTRL);
342357
343358 while (1) {
344
- if (timeout < 0)
345
- return -ETIMEDOUT;
359
+ if (timeout < 0) {
360
+ ret = -ETIMEDOUT;
361
+ goto exit;
362
+ }
346363 if (DLL_LOCK_WO_TMOUT((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0))))
347364 break;
348365 udelay(1);
349366 timeout--;
350367 }
351
- extra = DWCMSHC_EMMC_DLL_DLYENA;
368
+ dll_lock_value = ((sdhci_readl(host, DWCMSHC_EMMC_DLL_STATUS0) & 0xFF) * 2 ) & 0xFF;
369
+ extra = DWCMSHC_EMMC_DLL_DLYENA | DLL_RXCLK_ORI_GATE;
352370 if (data->flags & RK_RXCLK_NO_INVERTER)
353
- extra |= DLL_RXCLK_NO_INVERTER << DWCMSHC_EMMC_DLL_RXCLK_SRCSEL;
371
+ extra |= DLL_RXCLK_NO_INVERTER;
372
+ if (data->flags & RK_TAP_VALUE_SEL)
373
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
354374 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_RXCLK);
375
+
376
+ txclk_tapnum = data->hs200_tx_tap;
377
+ if ((data->flags & RK_DLL_CMD_OUT) &&
378
+ (host->mmc->timing == MMC_TIMING_MMC_HS400 ||
379
+ host->mmc->timing == MMC_TIMING_MMC_HS400ES)) {
380
+ txclk_tapnum = data->hs400_tx_tap;
381
+
382
+ extra = DLL_CMDOUT_SRC_CLK_NEG |
383
+ DLL_CMDOUT_BOTH_CLK_EDGE |
384
+ DWCMSHC_EMMC_DLL_DLYENA |
385
+ data->hs400_cmd_tap |
386
+ DLL_CMDOUT_TAPNUM_FROM_SW;
387
+ if (data->flags & RK_TAP_VALUE_SEL)
388
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
389
+ sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
390
+ }
355391
356392 extra = DWCMSHC_EMMC_DLL_DLYENA |
357393 DLL_TXCLK_TAPNUM_FROM_SW |
358394 DLL_TXCLK_NO_INVERTER|
359
- DLL_TXCLK_TAPNUM_DEFAULT;
360
-
395
+ txclk_tapnum;
396
+ if (data->flags & RK_TAP_VALUE_SEL)
397
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
361398 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
362399
363400 extra = DWCMSHC_EMMC_DLL_DLYENA |
364
- DLL_STRBIN_TAPNUM_DEFAULT;
401
+ data->hs400_strbin_tap |
402
+ DLL_STRBIN_TAPNUM_FROM_SW;
403
+ if (data->flags & RK_TAP_VALUE_SEL)
404
+ extra |= DLL_TAP_VALUE_SEL | (dll_lock_value << DLL_TAP_VALUE_OFFSET);
365405 sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
366406 } else {
407
+ /* disable dll */
408
+ sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
409
+
367410 /* Disable cmd conflict check */
368411 extra = sdhci_readl(host, DWCMSHC_HOST_CTRL3);
369412 extra &= ~BIT(0);
370413 sdhci_writel(host, extra, DWCMSHC_HOST_CTRL3);
371414
372415 /* reset the clock phase when the frequency is lower than 100MHz */
373
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_CTRL);
374
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_RXCLK);
416
+ sdhci_writel(host, DWCMSHC_EMMC_DLL_BYPASS | DWCMSHC_EMMC_DLL_START, DWCMSHC_EMMC_DLL_CTRL);
417
+ sdhci_writel(host, DLL_RXCLK_ORI_GATE, DWCMSHC_EMMC_DLL_RXCLK);
375418 sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_TXCLK);
376
- sdhci_writel(host, 0, DWCMSHC_EMMC_DLL_STRBIN);
377419 sdhci_writel(host, 0, DECMSHC_EMMC_DLL_CMDOUT);
420
+ /*
421
+ * Before switching to hs400es mode, the driver will enable
422
+ * enhanced strobe first. PHY needs to configure the parameters
423
+ * of enhanced strobe first.
424
+ */
425
+ extra = DWCMSHC_EMMC_DLL_DLYENA |
426
+ DLL_STRBIN_DELAY_NUM_SEL |
427
+ data->ddr50_strbin_delay_num << DLL_STRBIN_DELAY_NUM_OFFSET;
428
+ sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_STRBIN);
378429 }
430
+
431
+exit:
432
+ /* enable output clock */
433
+ sdhci_enable_clk(host, 0);
434
+
379435 return ret;
436
+}
437
+
438
+static int dwcmshc_sdhci_set_enhanced_strobe(struct sdhci_host *host)
439
+{
440
+ struct mmc *mmc = host->mmc;
441
+ u32 vendor;
442
+
443
+ vendor = sdhci_readl(host, DWCMSHC_EMMC_CONTROL);
444
+ if (mmc->timing == MMC_TIMING_MMC_HS400ES)
445
+ vendor |= DWCMSHC_ENHANCED_STROBE;
446
+ else
447
+ vendor &= ~DWCMSHC_ENHANCED_STROBE;
448
+ sdhci_writel(host, vendor, DWCMSHC_EMMC_CONTROL);
449
+
450
+ /* some emmc device need a delay before send command */
451
+ udelay(100);
452
+
453
+ return 0;
380454 }
381455
382456 static void dwcmshc_sdhci_set_ios_post(struct sdhci_host *host)
383457 {
384458 u16 ctrl;
385
- u32 extra;
386459 u32 timing = host->mmc->timing;
387460
388461 if (timing == MMC_TIMING_MMC_HS400 || timing == MMC_TIMING_MMC_HS400ES) {
....@@ -395,16 +468,6 @@
395468 ctrl = sdhci_readw(host, DWCMSHC_EMMC_CONTROL);
396469 ctrl |= DWCMSHC_CARD_IS_EMMC;
397470 sdhci_writew(host, ctrl, DWCMSHC_EMMC_CONTROL);
398
-
399
- extra = DLL_CMDOUT_SRC_CLK_NEG |
400
- DLL_CMDOUT_EN_SRC_CLK_NEG;
401
- sdhci_writel(host, extra, DECMSHC_EMMC_DLL_CMDOUT);
402
-
403
- extra = DWCMSHC_EMMC_DLL_DLYENA |
404
- DLL_TXCLK_TAPNUM_FROM_SW |
405
- DLL_TXCLK_NO_INVERTER|
406
- DLL_TXCLK_TAPNUM_90_DEGREES;
407
- sdhci_writel(host, extra, DWCMSHC_EMMC_DLL_TXCLK);
408471 }
409472 }
410473
....@@ -434,9 +497,21 @@
434497 data->set_ios_post(host);
435498 }
436499
500
+static int rockchip_sdhci_set_enhanced_strobe(struct sdhci_host *host)
501
+{
502
+ struct rockchip_sdhc *priv = container_of(host, struct rockchip_sdhc, host);
503
+ struct sdhci_data *data = (struct sdhci_data *)dev_get_driver_data(priv->dev);
504
+
505
+ if (data->set_enhanced_strobe)
506
+ return data->set_enhanced_strobe(host);
507
+
508
+ return -ENOTSUPP;
509
+}
510
+
437511 static struct sdhci_ops rockchip_sdhci_ops = {
438512 .set_clock = rockchip_sdhci_set_clock,
439513 .set_ios_post = rockchip_sdhci_set_ios_post,
514
+ .set_enhanced_strobe = rockchip_sdhci_set_enhanced_strobe,
440515 };
441516
442517 static int rockchip_sdhci_probe(struct udevice *dev)
....@@ -496,7 +571,13 @@
496571 host->host_caps |= MMC_MODE_HS200;
497572 else if (dev_read_bool(dev, "mmc-hs400-1_8v"))
498573 host->host_caps |= MMC_MODE_HS400;
574
+
575
+ if (data->set_enhanced_strobe && dev_read_bool(dev, "mmc-hs400-enhanced-strobe"))
576
+ host->host_caps |= MMC_MODE_HS400ES;
577
+
499578 ret = sdhci_setup_cfg(&plat->cfg, host, 0, EMMC_MIN_FREQ);
579
+
580
+ plat->cfg.fixed_drv_type = dev_read_u32_default(dev, "fixed-emmc-driver-type", 0);
500581
501582 host->mmc = &plat->mmc;
502583 if (ret)
....@@ -536,13 +617,50 @@
536617 .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
537618 .get_phy = dwcmshc_emmc_get_phy,
538619 .flags = RK_RXCLK_NO_INVERTER,
620
+ .hs200_tx_tap = 16,
621
+ .hs400_tx_tap = 8,
622
+ .hs400_cmd_tap = 8,
623
+ .hs400_strbin_tap = 3,
624
+ .ddr50_strbin_delay_num = 16,
539625 };
540626
541627 static const struct sdhci_data rk3588_data = {
542628 .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
543629 .get_phy = dwcmshc_emmc_get_phy,
544630 .set_ios_post = dwcmshc_sdhci_set_ios_post,
545
- .flags = RK_DLL_CMD_OUT | RK_RXCLK_NO_INVERTER,
631
+ .set_enhanced_strobe = dwcmshc_sdhci_set_enhanced_strobe,
632
+ .flags = RK_DLL_CMD_OUT,
633
+ .hs200_tx_tap = 16,
634
+ .hs400_tx_tap = 9,
635
+ .hs400_cmd_tap = 8,
636
+ .hs400_strbin_tap = 3,
637
+ .ddr50_strbin_delay_num = 16,
638
+};
639
+
640
+static const struct sdhci_data rk3528_data = {
641
+ .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
642
+ .get_phy = dwcmshc_emmc_get_phy,
643
+ .set_ios_post = dwcmshc_sdhci_set_ios_post,
644
+ .set_enhanced_strobe = dwcmshc_sdhci_set_enhanced_strobe,
645
+ .flags = RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
646
+ .hs200_tx_tap = 12,
647
+ .hs400_tx_tap = 6,
648
+ .hs400_cmd_tap = 6,
649
+ .hs400_strbin_tap = 3,
650
+ .ddr50_strbin_delay_num = 10,
651
+};
652
+
653
+static const struct sdhci_data rk3562_data = {
654
+ .emmc_set_clock = dwcmshc_sdhci_emmc_set_clock,
655
+ .get_phy = dwcmshc_emmc_get_phy,
656
+ .set_ios_post = dwcmshc_sdhci_set_ios_post,
657
+ .set_enhanced_strobe = dwcmshc_sdhci_set_enhanced_strobe,
658
+ .flags = RK_DLL_CMD_OUT | RK_TAP_VALUE_SEL,
659
+ .hs200_tx_tap = 12,
660
+ .hs400_tx_tap = 6,
661
+ .hs400_cmd_tap = 6,
662
+ .hs400_strbin_tap = 3,
663
+ .ddr50_strbin_delay_num = 10,
546664 };
547665
548666 static const struct udevice_id sdhci_ids[] = {
....@@ -555,6 +673,14 @@
555673 .data = (ulong)&rk3568_data,
556674 },
557675 {
676
+ .compatible = "rockchip,rk3528-dwcmshc",
677
+ .data = (ulong)&rk3528_data,
678
+ },
679
+ {
680
+ .compatible = "rockchip,rk3562-dwcmshc",
681
+ .data = (ulong)&rk3562_data,
682
+ },
683
+ {
558684 .compatible = "rockchip,rk3588-dwcmshc",
559685 .data = (ulong)&rk3588_data,
560686 },