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