blob: f7f6de1ba98bb322a377e5db9008f5a74da83556 [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>
Simon Glassdbd79542020-05-10 11:40:11 -060012#include <linux/delay.h>
Kever Yang0446dd82019-11-15 11:04:41 +080013
14static 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
51static 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
87void 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
97void 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
117int 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
171void 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}