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