xref: /rk3399_rockchip-uboot/drivers/ram/rockchip/sdram_phy_px30.c (revision 8dd9db5d1cd5826638c3cdb5f681300ff2f29f3b)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * (C) Copyright 2018 Rockchip Electronics Co., Ltd.
4  */
5 
6 #include <common.h>
7 #include <ram.h>
8 #include <asm/io.h>
9 #include <asm/arch/sdram_common.h>
10 #include <asm/arch/sdram_share.h>
11 #include <asm/arch/sdram_phy_px30.h>
12 
13 static void sdram_phy_dll_bypass_set(void __iomem *phy_base, u32 freq)
14 {
15 	u32 tmp;
16 	u32 i, j;
17 
18 	setbits_le32(PHY_REG(phy_base, 0x13), 1 << 4);
19 	clrbits_le32(PHY_REG(phy_base, 0x14), 1 << 3);
20 	for (i = 0; i < 4; i++) {
21 		j = 0x26 + i * 0x10;
22 		setbits_le32(PHY_REG(phy_base, j), 1 << 4);
23 		clrbits_le32(PHY_REG(phy_base, j + 0x1), 1 << 3);
24 	}
25 
26 	if (freq <= (400 * MHZ))
27 		/* DLL bypass */
28 		setbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
29 	else
30 		clrbits_le32(PHY_REG(phy_base, 0xa4), 0x1f);
31 
32 	if (freq <= (801 * MHZ))
33 		tmp = 2;
34 	else
35 		tmp = 1;
36 
37 	for (i = 0; i < 4; i++) {
38 		j = 0x28 + i * 0x10;
39 		writel(tmp, PHY_REG(phy_base, j));
40 	}
41 }
42 
43 static void sdram_phy_set_ds_odt(void __iomem *phy_base,
44 				 u32 dram_type)
45 {
46 	u32 cmd_drv, clk_drv, dqs_drv, dqs_odt;
47 	u32 i, j;
48 
49 	if (dram_type == DDR3) {
50 		cmd_drv = PHY_DDR3_RON_RTT_34ohm;
51 		clk_drv = PHY_DDR3_RON_RTT_45ohm;
52 		dqs_drv = PHY_DDR3_RON_RTT_34ohm;
53 		dqs_odt = PHY_DDR3_RON_RTT_225ohm;
54 	} else {
55 		cmd_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
56 		clk_drv = PHY_DDR4_LPDDR3_RON_RTT_43ohm;
57 		dqs_drv = PHY_DDR4_LPDDR3_RON_RTT_34ohm;
58 		if (dram_type == LPDDR2)
59 			dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_DISABLE;
60 		else
61 			dqs_odt = PHY_DDR4_LPDDR3_RON_RTT_240ohm;
62 	}
63 	/* DS */
64 	writel(cmd_drv, PHY_REG(phy_base, 0x11));
65 	clrsetbits_le32(PHY_REG(phy_base, 0x12), 0x1f << 3, cmd_drv << 3);
66 	writel(clk_drv, PHY_REG(phy_base, 0x16));
67 	writel(clk_drv, PHY_REG(phy_base, 0x18));
68 
69 	for (i = 0; i < 4; i++) {
70 		j = 0x20 + i * 0x10;
71 		writel(dqs_drv, PHY_REG(phy_base, j));
72 		writel(dqs_drv, PHY_REG(phy_base, j + 0xf));
73 		/* ODT */
74 		writel(dqs_odt, PHY_REG(phy_base, j + 0x1));
75 		writel(dqs_odt, PHY_REG(phy_base, j + 0xe));
76 	}
77 }
78 
79 void phy_soft_reset(void __iomem *phy_base)
80 {
81 	clrbits_le32(PHY_REG(phy_base, 0), 0x3 << 2);
82 	udelay(1);
83 	setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET);
84 	udelay(5);
85 	setbits_le32(PHY_REG(phy_base, 0), DIGITAL_DERESET);
86 	udelay(1);
87 }
88 
89 void phy_dram_set_bw(void __iomem *phy_base, u32 bw)
90 {
91 	if (bw == 2) {
92 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
93 		setbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
94 		setbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
95 	} else if (bw == 1) {
96 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
97 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
98 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
99 	} else if (bw == 0) {
100 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
101 		clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
102 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
103 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
104 	}
105 
106 	phy_soft_reset(phy_base);
107 }
108 
109 int phy_data_training(void __iomem *phy_base, u32 cs, u32 dramtype)
110 {
111 	u32 ret;
112 	u32 odt_val;
113 	u32 i, j;
114 
115 	odt_val = readl(PHY_REG(phy_base, 0x2e));
116 
117 	for (i = 0; i < 4; i++) {
118 		j = 0x20 + i * 0x10;
119 		writel(PHY_DDR3_RON_RTT_225ohm, PHY_REG(phy_base, j + 0x1));
120 		writel(0, PHY_REG(phy_base, j + 0xe));
121 	}
122 
123 	if (dramtype == DDR4) {
124 		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0);
125 		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0);
126 		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0);
127 		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0);
128 	}
129 	/* choose training cs */
130 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
131 	/* enable gate training */
132 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
133 	udelay(50);
134 	ret = readl(PHY_REG(phy_base, 0xff));
135 	/* disable gate training */
136 	clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
137 	clrbits_le32(PHY_REG(phy_base, 2), 0x30);
138 
139 	if (dramtype == DDR4) {
140 		clrsetbits_le32(PHY_REG(phy_base, 0x29), 0x3, 0x2);
141 		clrsetbits_le32(PHY_REG(phy_base, 0x39), 0x3, 0x2);
142 		clrsetbits_le32(PHY_REG(phy_base, 0x49), 0x3, 0x2);
143 		clrsetbits_le32(PHY_REG(phy_base, 0x59), 0x3, 0x2);
144 	}
145 
146 	if (ret & 0x10) {
147 		ret = -1;
148 	} else {
149 		ret = (ret & 0xf) ^ (readl(PHY_REG(phy_base, 0)) >> 4);
150 		ret = (ret == 0) ? 0 : -1;
151 	}
152 
153 	for (i = 0; i < 4; i++) {
154 		j = 0x20 + i * 0x10;
155 		writel(odt_val, PHY_REG(phy_base, j + 0x1));
156 		writel(odt_val, PHY_REG(phy_base, j + 0xe));
157 	}
158 
159 	return ret;
160 }
161 
162 void phy_cfg(void __iomem *phy_base,
163 	     struct ddr_phy_regs *phy_regs, struct ddr_phy_skew *skew,
164 	     struct sdram_base_params *base, u32 bw)
165 {
166 	u32 i;
167 
168 	sdram_phy_dll_bypass_set(phy_base, base->ddr_freq);
169 	for (i = 0; phy_regs->phy[i][0] != 0xFFFFFFFF; i++) {
170 		writel(phy_regs->phy[i][1],
171 		       phy_base + phy_regs->phy[i][0]);
172 	}
173 	if (bw == 2) {
174 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 0xf << 4);
175 	} else if (bw == 1) {
176 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 3 << 4);
177 		/* disable DQS2,DQS3 tx dll  for saving power */
178 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
179 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
180 	} else {
181 		clrsetbits_le32(PHY_REG(phy_base, 0), 0xf << 4, 1 << 4);
182 		/* disable DQS2,DQS3 tx dll  for saving power */
183 		clrbits_le32(PHY_REG(phy_base, 0x36), 1 << 3);
184 		clrbits_le32(PHY_REG(phy_base, 0x46), 1 << 3);
185 		clrbits_le32(PHY_REG(phy_base, 0x56), 1 << 3);
186 	}
187 	sdram_phy_set_ds_odt(phy_base, base->dramtype);
188 
189 	/* deskew */
190 	setbits_le32(PHY_REG(phy_base, 2), 8);
191 	sdram_copy_to_reg(PHY_REG(phy_base, 0xb0),
192 			  &skew->a0_a1_skew[0], 15 * 4);
193 	sdram_copy_to_reg(PHY_REG(phy_base, 0x70),
194 			  &skew->cs0_dm0_skew[0], 44 * 4);
195 	sdram_copy_to_reg(PHY_REG(phy_base, 0xc0),
196 			  &skew->cs1_dm0_skew[0], 44 * 4);
197 }
198 
199