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