xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/sdram_phy_px30.c (revision b8dc613cbc483a8abfcf4203e4fa0e18f60b1d27)
174803decSYouMin Chen // SPDX-License-Identifier: GPL-2.0
274803decSYouMin Chen /*
374803decSYouMin Chen  * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
474803decSYouMin Chen  */
574803decSYouMin Chen 
674803decSYouMin Chen #include <common.h>
774803decSYouMin Chen #include <ram.h>
874803decSYouMin Chen #include <asm/io.h>
9e1f97ec3SYouMin Chen #include <asm/arch/sdram.h>
105685f66aSYouMin Chen #include <asm/arch/sdram_common.h>
1174803decSYouMin Chen #include <asm/arch/sdram_phy_px30.h>
1274803decSYouMin Chen 
sdram_phy_dll_bypass_set(void __iomem * phy_base,u32 freq)1374803decSYouMin Chen static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
1474803decSYouMin Chen {
1574803decSYouMin Chen 	u32 tmp;
1674803decSYouMin Chen 	u32 i, j;
17*bbf5a1e4SYouMin Chen 	u32 dqs_dll_freq;
1874803decSYouMin Chen 
1974803decSYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
2074803decSYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
2174803decSYouMin Chen 	for (i = 0; i < 4; i++) {
2274803decSYouMin Chen 		j = 0x26 + i * 0x10;
2374803decSYouMin Chen 		setbits_le32(PHY_REG(phy_base, j), 1 << 4);
2474803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
2574803decSYouMin Chen 	}
2674803decSYouMin Chen 
27*bbf5a1e4SYouMin Chen 	if (freq <= 400)
2874803decSYouMin Chen 		/* DLL bypass */
2974803decSYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
3074803decSYouMin Chen 	else
3174803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
3274803decSYouMin Chen 
33*bbf5a1e4SYouMin Chen 	#ifdef CONFIG_ROCKCHIP_RK3328
34*bbf5a1e4SYouMin Chen 	dqs_dll_freq = 680;
35*bbf5a1e4SYouMin Chen 	#else
36*bbf5a1e4SYouMin Chen 	dqs_dll_freq = 801;
37*bbf5a1e4SYouMin Chen 	#endif
38*bbf5a1e4SYouMin Chen 
39*bbf5a1e4SYouMin Chen 	if (freq <= dqs_dll_freq)
4074803decSYouMin Chen 		tmp = 2;
4174803decSYouMin Chen 	else
4274803decSYouMin Chen 		tmp = 1;
4374803decSYouMin Chen 
4474803decSYouMin Chen 	for (i = 0; i < 4; i++) {
4574803decSYouMin Chen 		j = 0x28 + i * 0x10;
4674803decSYouMin Chen 		writel(tmp, PHY_REG(phy_base, j));
4774803decSYouMin Chen 	}
4874803decSYouMin Chen }
4974803decSYouMin Chen 
sdram_phy_set_ds_odt(void __iomem * phy_base,u32 dram_type)5074803decSYouMin Chen static void sdram_phy_set_ds_odt(void __iomem *phy_base,
5174803decSYouMin Chen 				 u32 dram_type)
5274803decSYouMin Chen {
5374803decSYouMin Chen 	u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
5474803decSYouMin Chen 	u32 i, j;
5574803decSYouMin Chen 
5674803decSYouMin Chen 	if (dram_type == DDR3) {
5774803decSYouMin Chen 		cmd_drv = PHY_DDR3_RON_RTT_34ohm;
5874803decSYouMin Chen 		clk_drv = PHY_DDR3_RON_RTT_45ohm;
5974803decSYouMin Chen 		dqs_drv = PHY_DDR3_RON_RTT_34ohm;
6074803decSYouMin Chen 		dqs_odt = PHY_DDR3_RON_RTT_225ohm;
6174803decSYouMin Chen 	} else {
6274803decSYouMin Chen 		cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
6374803decSYouMin Chen 		clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
6474803decSYouMin Chen 		dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
6574803decSYouMin Chen 		if (dram_type == LPDDR2)
6674803decSYouMin Chen 			dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
6774803decSYouMin Chen 		else
6874803decSYouMin Chen 			dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
6974803decSYouMin Chen 	}
7074803decSYouMin Chen 	/* DS */
7174803decSYouMin Chen 	writel(cmd_drv, PHY_REG(phy_base, 0x11));
7274803decSYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
7374803decSYouMin Chen 	writel(clk_drv, PHY_REG(phy_base, 0x16));
7474803decSYouMin Chen 	writel(clk_drv, PHY_REG(phy_base, 0x18));
7574803decSYouMin Chen 
7674803decSYouMin Chen 	for (i = 0; i < 4; i++) {
7774803decSYouMin Chen 		j = 0x20 + i * 0x10;
7874803decSYouMin Chen 		writel(dqs_drv, PHY_REG(phy_base, j));
7974803decSYouMin Chen 		writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
8074803decSYouMin Chen 		/* ODT */
8174803decSYouMin Chen 		writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
8274803decSYouMin Chen 		writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
8374803decSYouMin Chen 	}
8474803decSYouMin Chen }
8574803decSYouMin Chen 
phy_soft_reset(void __iomem * phy_base)8674803decSYouMin Chen void phy_soft_reset(void __iomem *phy_base)
8774803decSYouMin Chen {
8874803decSYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
8974803decSYouMin Chen 	udelay(1);
9074803decSYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
9174803decSYouMin Chen 	udelay(5);
9274803decSYouMin Chen 	setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
9374803decSYouMin Chen 	udelay(1);
9474803decSYouMin Chen }
9574803decSYouMin Chen 
phy_dram_set_bw(void __iomem * phy_base,u32 bw)9674803decSYouMin Chen void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
9774803decSYouMin Chen {
9874803decSYouMin Chen 	if (bw == 2) {
9974803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
10074803decSYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
10174803decSYouMin Chen 		setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
10274803decSYouMin Chen 	} else if (bw == 1) {
10374803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
10474803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
10574803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
10674803decSYouMin Chen 	} else if (bw == 0) {
10774803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
10874803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
10974803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
11074803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
11174803decSYouMin Chen 	}
11274803decSYouMin Chen 
11374803decSYouMin Chen 	phy_soft_reset(phy_base);
11474803decSYouMin Chen }
11574803decSYouMin Chen 
phy_data_training(void __iomem * phy_base,u32 cs,u32 dramtype)11674803decSYouMin Chen int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
11774803decSYouMin Chen {
11874803decSYouMin Chen 	u32 ret;
11974803decSYouMin Chen 	u32 odt_val;
12074803decSYouMin Chen 	u32 i, j;
12174803decSYouMin Chen 
12274803decSYouMin Chen 	odt_val = readl(PHY_REG(phy_base, 0x2e));
12374803decSYouMin Chen 
12474803decSYouMin Chen 	for (i = 0; i < 4; i++) {
12574803decSYouMin Chen 		j = 0x20 + i * 0x10;
12674803decSYouMin Chen 		writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
12774803decSYouMin Chen 		writel(0, PHY_REG(phy_base, j + 0xe));
12874803decSYouMin Chen 	}
12974803decSYouMin Chen 
13074803decSYouMin Chen 	if (dramtype == DDR4) {
13174803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
13274803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
13374803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
13474803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
13574803decSYouMin Chen 	}
13674803decSYouMin Chen 	/* choose training cs */
13774803decSYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
13874803decSYouMin Chen 	/* enable gate training */
13974803decSYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
14074803decSYouMin Chen 	udelay(50);
14174803decSYouMin Chen 	ret = readl(PHY_REG(phy_base, 0xff));
14274803decSYouMin Chen 	/* disable gate training */
14374803decSYouMin Chen 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
144*bbf5a1e4SYouMin Chen 	#ifndef CONFIG_ROCKCHIP_RK3328
14574803decSYouMin Chen 	clrbits_le32(PHY_REG(phy_base, 2), 0x30);
146*bbf5a1e4SYouMin Chen 	#endif
14774803decSYouMin Chen 
14874803decSYouMin Chen 	if (dramtype == DDR4) {
14974803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
15074803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
15174803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
15274803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
15374803decSYouMin Chen 	}
15474803decSYouMin Chen 
15574803decSYouMin Chen 	if (ret & 0x10) {
15674803decSYouMin Chen 		ret = -1;
15774803decSYouMin Chen 	} else {
15874803decSYouMin Chen 		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
15974803decSYouMin Chen 		ret = (ret == 0) ? 0 : -1;
16074803decSYouMin Chen 	}
16174803decSYouMin Chen 
16274803decSYouMin Chen 	for (i = 0; i < 4; i++) {
16374803decSYouMin Chen 		j = 0x20 + i * 0x10;
16474803decSYouMin Chen 		writel(odt_val, PHY_REG(phy_base, j + 0x1));
16574803decSYouMin Chen 		writel(odt_val, PHY_REG(phy_base, j + 0xe));
16674803decSYouMin Chen 	}
16774803decSYouMin Chen 	return ret;
16874803decSYouMin Chen }
16974803decSYouMin Chen 
phy_cfg(void __iomem * phy_base,struct ddr_phy_regs * phy_regs,struct ddr_phy_skew * skew,struct sdram_base_params * base,u32 bw)17074803decSYouMin Chen void phy_cfg(void __iomem *phy_base,
17174803decSYouMin Chen 	     struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
17274803decSYouMin Chen 	     struct sdram_base_params *base, u32 bw)
17374803decSYouMin Chen {
17474803decSYouMin Chen 	u32 i;
17574803decSYouMin Chen 
17674803decSYouMin Chen 	sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
17774803decSYouMin Chen 	for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
17874803decSYouMin Chen 		writel(phy_regs->phy[i][1],
17974803decSYouMin Chen 		       phy_base + phy_regs->phy[i][0]);
18074803decSYouMin Chen 	}
18174803decSYouMin Chen 	if (bw == 2) {
18274803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
18374803decSYouMin Chen 	} else if (bw == 1) {
18474803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
18574803decSYouMin Chen 		/* disable DQS2,DQS3 tx dll  for saving power */
18674803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
18774803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
18874803decSYouMin Chen 	} else {
18974803decSYouMin Chen 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
19074803decSYouMin Chen 		/* disable DQS2,DQS3 tx dll  for saving power */
19174803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
19274803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
19374803decSYouMin Chen 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
19474803decSYouMin Chen 	}
19574803decSYouMin Chen 	sdram_phy_set_ds_odt(phy_base, base->dramtype);
19674803decSYouMin Chen 
19774803decSYouMin Chen 	/* deskew */
19874803decSYouMin Chen 	setbits_le32(PHY_REG(phy_base, 2), 8);
19974803decSYouMin Chen 	sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
20074803decSYouMin Chen 			  &skew->a0_a1_skew[0], 15 * 4);
20174803decSYouMin Chen 	sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
20274803decSYouMin Chen 			  &skew->cs0_dm0_skew[0], 44 * 4);
20374803decSYouMin Chen 	sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
20474803decSYouMin Chen 			  &skew->cs1_dm0_skew[0], 44 * 4);
20574803decSYouMin Chen }
20674803decSYouMin Chen 
207