1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * (C) Copyright 2020 Rockchip Electronics Co., Ltd.
4*4882a593Smuzhiyun */
5*4882a593Smuzhiyun
6*4882a593Smuzhiyun #include <common.h>
7*4882a593Smuzhiyun #include <debug_uart.h>
8*4882a593Smuzhiyun #include <dm.h>
9*4882a593Smuzhiyun #include <ram.h>
10*4882a593Smuzhiyun #include <syscon.h>
11*4882a593Smuzhiyun #include <asm/io.h>
12*4882a593Smuzhiyun #include <asm/arch/clock.h>
13*4882a593Smuzhiyun #include <asm/arch/hardware.h>
14*4882a593Smuzhiyun #include <asm/arch/rk_atags.h>
15*4882a593Smuzhiyun #include <asm/arch/cru_rv1126.h>
16*4882a593Smuzhiyun #include <asm/arch/grf_rv1126.h>
17*4882a593Smuzhiyun #include <asm/arch/sdram_common.h>
18*4882a593Smuzhiyun #include <asm/arch/sdram_rv1126.h>
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* define training flag */
21*4882a593Smuzhiyun #define CA_TRAINING (0x1 << 0)
22*4882a593Smuzhiyun #define READ_GATE_TRAINING (0x1 << 1)
23*4882a593Smuzhiyun #define WRITE_LEVELING (0x1 << 2)
24*4882a593Smuzhiyun #define WRITE_TRAINING (0x1 << 3)
25*4882a593Smuzhiyun #define READ_TRAINING (0x1 << 4)
26*4882a593Smuzhiyun #define FULL_TRAINING (0xff)
27*4882a593Smuzhiyun
28*4882a593Smuzhiyun #define SKEW_RX_SIGNAL (0)
29*4882a593Smuzhiyun #define SKEW_TX_SIGNAL (1)
30*4882a593Smuzhiyun #define SKEW_CA_SIGNAL (2)
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun #define DESKEW_MDF_ABS_VAL (0)
33*4882a593Smuzhiyun #define DESKEW_MDF_DIFF_VAL (1)
34*4882a593Smuzhiyun
35*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
36*4882a593Smuzhiyun #ifndef CONFIG_TPL_TINY_FRAMEWORK
37*4882a593Smuzhiyun #error please defined CONFIG_TPL_TINY_FRAMEWORK for RV1126 !!!
38*4882a593Smuzhiyun #endif
39*4882a593Smuzhiyun #endif
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun #ifdef CONFIG_TPL_BUILD
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun struct dram_info {
44*4882a593Smuzhiyun void __iomem *pctl;
45*4882a593Smuzhiyun void __iomem *phy;
46*4882a593Smuzhiyun struct rv1126_cru *cru;
47*4882a593Smuzhiyun struct msch_regs *msch;
48*4882a593Smuzhiyun struct rv1126_ddrgrf *ddrgrf;
49*4882a593Smuzhiyun struct rv1126_grf *grf;
50*4882a593Smuzhiyun struct ram_info info;
51*4882a593Smuzhiyun struct rv1126_pmugrf *pmugrf;
52*4882a593Smuzhiyun u32 sr_idle;
53*4882a593Smuzhiyun u32 pd_idle;
54*4882a593Smuzhiyun };
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun #define GRF_BASE_ADDR 0xfe000000
57*4882a593Smuzhiyun #define PMU_GRF_BASE_ADDR 0xfe020000
58*4882a593Smuzhiyun #define DDR_GRF_BASE_ADDR 0xfe030000
59*4882a593Smuzhiyun #define BUS_SGRF_BASE_ADDR 0xfe0a0000
60*4882a593Smuzhiyun #define SERVER_MSCH_BASE_ADDR 0xfe800000
61*4882a593Smuzhiyun #define CRU_BASE_ADDR 0xff490000
62*4882a593Smuzhiyun #define DDR_PHY_BASE_ADDR 0xff4a0000
63*4882a593Smuzhiyun #define UPCTL2_BASE_ADDR 0xffa50000
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun #define SGRF_SOC_CON2 0x8
66*4882a593Smuzhiyun #define SGRF_SOC_CON12 0x30
67*4882a593Smuzhiyun #define SGRF_SOC_CON13 0x34
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun struct dram_info dram_info;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun #if (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 3)
72*4882a593Smuzhiyun struct rv1126_sdram_params sdram_configs[] = {
73*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-328.inc"
74*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-396.inc"
75*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-528.inc"
76*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-664.inc"
77*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-784.inc"
78*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-924.inc"
79*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr3-detect-1056.inc"
80*4882a593Smuzhiyun };
81*4882a593Smuzhiyun #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 0)
82*4882a593Smuzhiyun struct rv1126_sdram_params sdram_configs[] = {
83*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-328.inc"
84*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-396.inc"
85*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-528.inc"
86*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-664.inc"
87*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-784.inc"
88*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-924.inc"
89*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-ddr4-detect-1056.inc"
90*4882a593Smuzhiyun };
91*4882a593Smuzhiyun #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 6)
92*4882a593Smuzhiyun struct rv1126_sdram_params sdram_configs[] = {
93*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-328.inc"
94*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-396.inc"
95*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-528.inc"
96*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-664.inc"
97*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-784.inc"
98*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-924.inc"
99*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr3-detect-1056.inc"
100*4882a593Smuzhiyun };
101*4882a593Smuzhiyun #elif (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 7) || (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 8)
102*4882a593Smuzhiyun struct rv1126_sdram_params sdram_configs[] = {
103*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-328.inc"
104*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-396.inc"
105*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-528.inc"
106*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-664.inc"
107*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-784.inc"
108*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-924.inc"
109*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-lpddr4-detect-1056.inc"
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun #endif
112*4882a593Smuzhiyun
113*4882a593Smuzhiyun u32 common_info[] = {
114*4882a593Smuzhiyun #include "sdram_inc/rv1126/sdram-rv1126-loader_params.inc"
115*4882a593Smuzhiyun };
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
118*4882a593Smuzhiyun static struct rw_trn_result rw_trn_result;
119*4882a593Smuzhiyun #endif
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun static struct rv1126_fsp_param fsp_param[MAX_IDX];
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static u8 lp3_odt_value;
124*4882a593Smuzhiyun
125*4882a593Smuzhiyun static s8 wrlvl_result[2][4];
126*4882a593Smuzhiyun
127*4882a593Smuzhiyun /* DDR configuration 0-9 */
128*4882a593Smuzhiyun u16 ddr_cfg_2_rbc[] = {
129*4882a593Smuzhiyun ((0 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 3), /* 0 */
130*4882a593Smuzhiyun ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 2), /* 1 */
131*4882a593Smuzhiyun ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 3), /* 2 */
132*4882a593Smuzhiyun ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 1), /* 3 */
133*4882a593Smuzhiyun ((0 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 4), /* 4 */
134*4882a593Smuzhiyun ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 1), /* 5 */
135*4882a593Smuzhiyun ((0 << 8) | (3 << 5) | (1 << 4) | (1 << 3) | 2), /* 6 */
136*4882a593Smuzhiyun ((0 << 8) | (2 << 5) | (1 << 4) | (1 << 3) | 3), /* 7 */
137*4882a593Smuzhiyun ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 2), /* 8 */
138*4882a593Smuzhiyun ((1 << 8) | (2 << 5) | (0 << 4) | (1 << 3) | 2) /* 9 */
139*4882a593Smuzhiyun };
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun /* DDR configuration 10-21 */
142*4882a593Smuzhiyun u8 ddr4_cfg_2_rbc[] = {
143*4882a593Smuzhiyun ((0 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 0), /* 10 */
144*4882a593Smuzhiyun ((1 << 7) | (2 << 4) | (0 << 3) | (2 << 1) | 0), /* 11 */
145*4882a593Smuzhiyun ((0 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 0), /* 12 */
146*4882a593Smuzhiyun ((1 << 7) | (3 << 4) | (0 << 3) | (1 << 1) | 0), /* 13 */
147*4882a593Smuzhiyun ((0 << 7) | (4 << 4) | (0 << 3) | (2 << 1) | 1), /* 14 */
148*4882a593Smuzhiyun ((1 << 7) | (3 << 4) | (0 << 3) | (2 << 1) | 1), /* 15 */
149*4882a593Smuzhiyun ((1 << 7) | (4 << 4) | (0 << 3) | (1 << 1) | 1), /* 16 */
150*4882a593Smuzhiyun ((0 << 7) | (2 << 4) | (1 << 3) | (2 << 1) | 0), /* 17 */
151*4882a593Smuzhiyun ((0 << 7) | (3 << 4) | (1 << 3) | (1 << 1) | 0), /* 18 */
152*4882a593Smuzhiyun ((0 << 7) | (3 << 4) | (1 << 3) | (2 << 1) | 1), /* 19 */
153*4882a593Smuzhiyun ((0 << 7) | (4 << 4) | (1 << 3) | (1 << 1) | 1), /* 20 */
154*4882a593Smuzhiyun ((1 << 7) | (4 << 4) | (0 << 3) | (0 << 1) | 0) /* 21 */
155*4882a593Smuzhiyun };
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun /* DDR configuration 22-28 */
158*4882a593Smuzhiyun u16 ddr_cfg_2_rbc_p2[] = {
159*4882a593Smuzhiyun ((1 << 8) | (3 << 5) | (0 << 4) | (1 << 3) | 0), /* 22 */
160*4882a593Smuzhiyun ((0 << 8) | (4 << 5) | (0 << 4) | (1 << 3) | 2), /* 23 */
161*4882a593Smuzhiyun ((1 << 8) | (3 << 5) | (0 << 4) | (0 << 3) | 3), /* 24 */
162*4882a593Smuzhiyun ((0 << 8) | (3 << 5) | (1 << 4) | (0 << 3) | 3), /* 25 */
163*4882a593Smuzhiyun ((0 << 8) | (4 << 5) | (1 << 4) | (0 << 3) | 2), /* 26 */
164*4882a593Smuzhiyun ((1 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 2), /* 27 */
165*4882a593Smuzhiyun ((0 << 8) | (4 << 5) | (0 << 4) | (0 << 3) | 3) /* 28 */
166*4882a593Smuzhiyun };
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun u8 d4_rbc_2_d3_rbc[][2] = {
169*4882a593Smuzhiyun {10, 0},
170*4882a593Smuzhiyun {11, 2},
171*4882a593Smuzhiyun {12, 23},
172*4882a593Smuzhiyun {13, 1},
173*4882a593Smuzhiyun {14, 28},
174*4882a593Smuzhiyun {15, 24},
175*4882a593Smuzhiyun {16, 27},
176*4882a593Smuzhiyun {17, 7},
177*4882a593Smuzhiyun {18, 6},
178*4882a593Smuzhiyun {19, 25},
179*4882a593Smuzhiyun {20, 26},
180*4882a593Smuzhiyun {21, 3}
181*4882a593Smuzhiyun };
182*4882a593Smuzhiyun
183*4882a593Smuzhiyun u32 addrmap[29][9] = {
184*4882a593Smuzhiyun {24, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
185*4882a593Smuzhiyun 0x08080808, 0x00000f0f, 0x3f3f}, /* 0 */
186*4882a593Smuzhiyun {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
187*4882a593Smuzhiyun 0x07070707, 0x00000f0f, 0x3f3f}, /* 1 */
188*4882a593Smuzhiyun {23, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
189*4882a593Smuzhiyun 0x0f080808, 0x00000f0f, 0x3f3f}, /* 2 */
190*4882a593Smuzhiyun {22, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x06060606,
191*4882a593Smuzhiyun 0x06060606, 0x00000f0f, 0x3f3f}, /* 3 */
192*4882a593Smuzhiyun {24, 0x000a0a0a, 0x00000000, 0x00000000, 0x00000000, 0x09090909,
193*4882a593Smuzhiyun 0x0f090909, 0x00000f0f, 0x3f3f}, /* 4 */
194*4882a593Smuzhiyun {6, 0x00070707, 0x00000000, 0x1f000000, 0x00001f1f, 0x07070707,
195*4882a593Smuzhiyun 0x07070707, 0x00000f0f, 0x3f3f}, /* 5 */
196*4882a593Smuzhiyun {7, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x08080808,
197*4882a593Smuzhiyun 0x08080808, 0x00000f0f, 0x3f3f}, /* 6 */
198*4882a593Smuzhiyun {8, 0x00090909, 0x00000000, 0x00000000, 0x00001f00, 0x09090909,
199*4882a593Smuzhiyun 0x0f090909, 0x00000f0f, 0x3f3f}, /* 7 */
200*4882a593Smuzhiyun {22, 0x001f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
201*4882a593Smuzhiyun 0x06060606, 0x00000f0f, 0x3f3f}, /* 8 */
202*4882a593Smuzhiyun {23, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
203*4882a593Smuzhiyun 0x0f070707, 0x00000f0f, 0x3f3f}, /* 9 */
204*4882a593Smuzhiyun
205*4882a593Smuzhiyun {24, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
206*4882a593Smuzhiyun 0x08080808, 0x00000f0f, 0x0801}, /* 10 */
207*4882a593Smuzhiyun {23, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
208*4882a593Smuzhiyun 0x0f080808, 0x00000f0f, 0x0801}, /* 11 */
209*4882a593Smuzhiyun {24, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
210*4882a593Smuzhiyun 0x07070707, 0x00000f07, 0x0700}, /* 12 */
211*4882a593Smuzhiyun {23, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
212*4882a593Smuzhiyun 0x07070707, 0x00000f0f, 0x0700}, /* 13 */
213*4882a593Smuzhiyun {24, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
214*4882a593Smuzhiyun 0x07070707, 0x00000f07, 0x3f01}, /* 14 */
215*4882a593Smuzhiyun {23, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x07070707,
216*4882a593Smuzhiyun 0x07070707, 0x00000f0f, 0x3f01}, /* 15 */
217*4882a593Smuzhiyun {23, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x06060606,
218*4882a593Smuzhiyun 0x06060606, 0x00000f06, 0x3f00}, /* 16 */
219*4882a593Smuzhiyun {8, 0x003f0a0a, 0x01010100, 0x01010101, 0x00001f1f, 0x09090909,
220*4882a593Smuzhiyun 0x0f090909, 0x00000f0f, 0x0801}, /* 17 */
221*4882a593Smuzhiyun {7, 0x003f0909, 0x00000007, 0x1f000000, 0x00001f1f, 0x08080808,
222*4882a593Smuzhiyun 0x08080808, 0x00000f0f, 0x0700}, /* 18 */
223*4882a593Smuzhiyun {7, 0x003f0909, 0x01010100, 0x01010101, 0x00001f1f, 0x08080808,
224*4882a593Smuzhiyun 0x08080808, 0x00000f0f, 0x3f01}, /* 19 */
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun {6, 0x003f0808, 0x00000007, 0x1f000000, 0x00001f1f, 0x07070707,
227*4882a593Smuzhiyun 0x07070707, 0x00000f07, 0x3f00}, /* 20 */
228*4882a593Smuzhiyun {23, 0x003f0909, 0x00000006, 0x1f1f0000, 0x00001f1f, 0x06060606,
229*4882a593Smuzhiyun 0x06060606, 0x00000f06, 0x0600}, /* 21 */
230*4882a593Smuzhiyun {21, 0x00060606, 0x00000000, 0x1f1f0000, 0x00001f1f, 0x05050505,
231*4882a593Smuzhiyun 0x05050505, 0x00000f0f, 0x3f3f}, /* 22 */
232*4882a593Smuzhiyun
233*4882a593Smuzhiyun {24, 0x00080808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
234*4882a593Smuzhiyun 0x07070707, 0x00000f07, 0x3f3f}, /* 23 */
235*4882a593Smuzhiyun {23, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
236*4882a593Smuzhiyun 0x07070707, 0x00000f0f, 0x3f3f}, /* 24 */
237*4882a593Smuzhiyun {7, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x08080808,
238*4882a593Smuzhiyun 0x08080808, 0x00000f0f, 0x3f3f}, /* 25 */
239*4882a593Smuzhiyun {6, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x07070707,
240*4882a593Smuzhiyun 0x07070707, 0x00000f07, 0x3f3f}, /* 26 */
241*4882a593Smuzhiyun {23, 0x003f0808, 0x00000000, 0x00000000, 0x00001f1f, 0x06060606,
242*4882a593Smuzhiyun 0x06060606, 0x00000f06, 0x3f3f}, /* 27 */
243*4882a593Smuzhiyun {24, 0x003f0909, 0x00000000, 0x00000000, 0x00001f00, 0x07070707,
244*4882a593Smuzhiyun 0x07070707, 0x00000f07, 0x3f3f} /* 28 */
245*4882a593Smuzhiyun };
246*4882a593Smuzhiyun
247*4882a593Smuzhiyun static u8 dq_sel[22][3] = {
248*4882a593Smuzhiyun {0x0, 0x17, 0x22},
249*4882a593Smuzhiyun {0x1, 0x18, 0x23},
250*4882a593Smuzhiyun {0x2, 0x19, 0x24},
251*4882a593Smuzhiyun {0x3, 0x1a, 0x25},
252*4882a593Smuzhiyun {0x4, 0x1b, 0x26},
253*4882a593Smuzhiyun {0x5, 0x1c, 0x27},
254*4882a593Smuzhiyun {0x6, 0x1d, 0x28},
255*4882a593Smuzhiyun {0x7, 0x1e, 0x29},
256*4882a593Smuzhiyun {0x8, 0x16, 0x21},
257*4882a593Smuzhiyun {0x9, 0x1f, 0x2a},
258*4882a593Smuzhiyun {0xa, 0x20, 0x2b},
259*4882a593Smuzhiyun {0x10, 0x1, 0xc},
260*4882a593Smuzhiyun {0x11, 0x2, 0xd},
261*4882a593Smuzhiyun {0x12, 0x3, 0xe},
262*4882a593Smuzhiyun {0x13, 0x4, 0xf},
263*4882a593Smuzhiyun {0x14, 0x5, 0x10},
264*4882a593Smuzhiyun {0x15, 0x6, 0x11},
265*4882a593Smuzhiyun {0x16, 0x7, 0x12},
266*4882a593Smuzhiyun {0x17, 0x8, 0x13},
267*4882a593Smuzhiyun {0x18, 0x0, 0xb},
268*4882a593Smuzhiyun {0x19, 0x9, 0x14},
269*4882a593Smuzhiyun {0x1a, 0xa, 0x15}
270*4882a593Smuzhiyun };
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun static u16 grp_addr[4] = {
273*4882a593Smuzhiyun ADD_GROUP_CS0_A,
274*4882a593Smuzhiyun ADD_GROUP_CS0_B,
275*4882a593Smuzhiyun ADD_GROUP_CS1_A,
276*4882a593Smuzhiyun ADD_GROUP_CS1_B
277*4882a593Smuzhiyun };
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun static u8 wrlvl_result_offset[2][4] = {
280*4882a593Smuzhiyun {0xa0 + 0x26, 0xa0 + 0x27, 0xd0 + 0x26, 0xd0 + 0x27},
281*4882a593Smuzhiyun {0xa0 + 0x28, 0xa0 + 0x29, 0xd0 + 0x28, 0xd0 + 0x29},
282*4882a593Smuzhiyun };
283*4882a593Smuzhiyun
284*4882a593Smuzhiyun static u16 dqs_dq_skew_adr[16] = {
285*4882a593Smuzhiyun 0x170 + 0, /* SKEW_UPDATE_RX_CS0_DQS0 */
286*4882a593Smuzhiyun 0x170 + 0xb, /* SKEW_UPDATE_RX_CS0_DQS1 */
287*4882a593Smuzhiyun 0x1d0 + 0, /* SKEW_UPDATE_RX_CS0_DQS2 */
288*4882a593Smuzhiyun 0x1d0 + 0xb, /* SKEW_UPDATE_RX_CS0_DQS3 */
289*4882a593Smuzhiyun 0x1a0 + 0, /* SKEW_UPDATE_RX_CS1_DQS0 */
290*4882a593Smuzhiyun 0x1a0 + 0xb, /* SKEW_UPDATE_RX_CS1_DQS1 */
291*4882a593Smuzhiyun 0x200 + 0, /* SKEW_UPDATE_RX_CS1_DQS2 */
292*4882a593Smuzhiyun 0x200 + 0xb, /* SKEW_UPDATE_RX_CS1_DQS3 */
293*4882a593Smuzhiyun 0x170 + 0x16, /* SKEW_UPDATE_TX_CS0_DQS0 */
294*4882a593Smuzhiyun 0x170 + 0x21, /* SKEW_UPDATE_TX_CS0_DQS1 */
295*4882a593Smuzhiyun 0x1d0 + 0x16, /* SKEW_UPDATE_TX_CS0_DQS2 */
296*4882a593Smuzhiyun 0x1d0 + 0x21, /* SKEW_UPDATE_TX_CS0_DQS3 */
297*4882a593Smuzhiyun 0x1a0 + 0x16, /* SKEW_UPDATE_TX_CS1_DQS0 */
298*4882a593Smuzhiyun 0x1a0 + 0x21, /* SKEW_UPDATE_TX_CS1_DQS1 */
299*4882a593Smuzhiyun 0x200 + 0x16, /* SKEW_UPDATE_TX_CS1_DQS2 */
300*4882a593Smuzhiyun 0x200 + 0x21, /* SKEW_UPDATE_TX_CS1_DQS3 */
301*4882a593Smuzhiyun };
302*4882a593Smuzhiyun
rkclk_ddr_reset(struct dram_info * dram,u32 ctl_srstn,u32 ctl_psrstn,u32 phy_srstn,u32 phy_psrstn)303*4882a593Smuzhiyun static void rkclk_ddr_reset(struct dram_info *dram,
304*4882a593Smuzhiyun u32 ctl_srstn, u32 ctl_psrstn,
305*4882a593Smuzhiyun u32 phy_srstn, u32 phy_psrstn)
306*4882a593Smuzhiyun {
307*4882a593Smuzhiyun writel(UPCTL2_SRSTN_REQ(ctl_srstn) | UPCTL2_PSRSTN_REQ(ctl_psrstn) |
308*4882a593Smuzhiyun UPCTL2_ASRSTN_REQ(ctl_srstn),
309*4882a593Smuzhiyun BUS_SGRF_BASE_ADDR + SGRF_SOC_CON13);
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun writel(DDRPHY_SRSTN_REQ(phy_srstn) | DDRPHY_PSRSTN_REQ(phy_psrstn),
312*4882a593Smuzhiyun &dram->cru->softrst_con[12]);
313*4882a593Smuzhiyun }
314*4882a593Smuzhiyun
rkclk_set_dpll(struct dram_info * dram,unsigned int hz)315*4882a593Smuzhiyun static void rkclk_set_dpll(struct dram_info *dram, unsigned int hz)
316*4882a593Smuzhiyun {
317*4882a593Smuzhiyun unsigned int refdiv, postdiv1, postdiv2, fbdiv;
318*4882a593Smuzhiyun int delay = 1000;
319*4882a593Smuzhiyun u32 mhz = hz / MHz;
320*4882a593Smuzhiyun struct global_info *gbl_info;
321*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
322*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
323*4882a593Smuzhiyun u32 ssmod_info;
324*4882a593Smuzhiyun u32 dsmpd = 1;
325*4882a593Smuzhiyun
326*4882a593Smuzhiyun gbl_info = (struct global_info *)((void *)common_info +
327*4882a593Smuzhiyun index->global_index.offset * 4);
328*4882a593Smuzhiyun ssmod_info = gbl_info->info_2t;
329*4882a593Smuzhiyun refdiv = 1;
330*4882a593Smuzhiyun if (mhz <= 100) {
331*4882a593Smuzhiyun postdiv1 = 6;
332*4882a593Smuzhiyun postdiv2 = 4;
333*4882a593Smuzhiyun } else if (mhz <= 150) {
334*4882a593Smuzhiyun postdiv1 = 4;
335*4882a593Smuzhiyun postdiv2 = 4;
336*4882a593Smuzhiyun } else if (mhz <= 200) {
337*4882a593Smuzhiyun postdiv1 = 6;
338*4882a593Smuzhiyun postdiv2 = 2;
339*4882a593Smuzhiyun } else if (mhz <= 300) {
340*4882a593Smuzhiyun postdiv1 = 4;
341*4882a593Smuzhiyun postdiv2 = 2;
342*4882a593Smuzhiyun } else if (mhz <= 400) {
343*4882a593Smuzhiyun postdiv1 = 6;
344*4882a593Smuzhiyun postdiv2 = 1;
345*4882a593Smuzhiyun } else {
346*4882a593Smuzhiyun postdiv1 = 4;
347*4882a593Smuzhiyun postdiv2 = 1;
348*4882a593Smuzhiyun }
349*4882a593Smuzhiyun fbdiv = (mhz * refdiv * postdiv1 * postdiv2) / 24;
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun writel(DPLL_MODE(CLOCK_FROM_XIN_OSC), &dram->cru->mode);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun writel(0x1f000000, &dram->cru->clksel_con[64]);
354*4882a593Smuzhiyun writel(POSTDIV1(postdiv1) | FBDIV(fbdiv), &dram->cru->pll[1].con0);
355*4882a593Smuzhiyun /* enable ssmod */
356*4882a593Smuzhiyun if (PLL_SSMOD_SPREAD(ssmod_info)) {
357*4882a593Smuzhiyun dsmpd = 0;
358*4882a593Smuzhiyun clrsetbits_le32(&dram->cru->pll[1].con2,
359*4882a593Smuzhiyun 0xffffff << 0, 0x0 << 0);
360*4882a593Smuzhiyun writel(SSMOD_SPREAD(PLL_SSMOD_SPREAD(ssmod_info)) |
361*4882a593Smuzhiyun SSMOD_DIVVAL(PLL_SSMOD_DIV(ssmod_info)) |
362*4882a593Smuzhiyun SSMOD_DOWNSPREAD(PLL_SSMOD_DOWNSPREAD(ssmod_info)) |
363*4882a593Smuzhiyun SSMOD_RESET(0) |
364*4882a593Smuzhiyun SSMOD_DIS_SSCG(0) |
365*4882a593Smuzhiyun SSMOD_BP(0),
366*4882a593Smuzhiyun &dram->cru->pll[1].con3);
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun writel(DSMPD(dsmpd) | POSTDIV2(postdiv2) | REFDIV(refdiv),
369*4882a593Smuzhiyun &dram->cru->pll[1].con1);
370*4882a593Smuzhiyun
371*4882a593Smuzhiyun while (delay > 0) {
372*4882a593Smuzhiyun udelay(1);
373*4882a593Smuzhiyun if (LOCK(readl(&dram->cru->pll[1].con1)))
374*4882a593Smuzhiyun break;
375*4882a593Smuzhiyun delay--;
376*4882a593Smuzhiyun }
377*4882a593Smuzhiyun if (delay <= 0)
378*4882a593Smuzhiyun printascii("ERROR: DPLL lock timeout!\n");
379*4882a593Smuzhiyun
380*4882a593Smuzhiyun writel(DPLL_MODE(CLOCK_FROM_PLL), &dram->cru->mode);
381*4882a593Smuzhiyun }
382*4882a593Smuzhiyun
rkclk_configure_ddr(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)383*4882a593Smuzhiyun static void rkclk_configure_ddr(struct dram_info *dram,
384*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
385*4882a593Smuzhiyun {
386*4882a593Smuzhiyun /* for inno ddr phy need freq / 2 */
387*4882a593Smuzhiyun rkclk_set_dpll(dram, sdram_params->base.ddr_freq * MHZ / 2);
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun
390*4882a593Smuzhiyun static unsigned int
calculate_ddrconfig(struct rv1126_sdram_params * sdram_params)391*4882a593Smuzhiyun calculate_ddrconfig(struct rv1126_sdram_params *sdram_params)
392*4882a593Smuzhiyun {
393*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
394*4882a593Smuzhiyun u32 cs, bw, die_bw, col, row, bank;
395*4882a593Smuzhiyun u32 cs1_row;
396*4882a593Smuzhiyun u32 i, tmp;
397*4882a593Smuzhiyun u32 ddrconf = -1;
398*4882a593Smuzhiyun u32 row_3_4;
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun cs = cap_info->rank;
401*4882a593Smuzhiyun bw = cap_info->bw;
402*4882a593Smuzhiyun die_bw = cap_info->dbw;
403*4882a593Smuzhiyun col = cap_info->col;
404*4882a593Smuzhiyun row = cap_info->cs0_row;
405*4882a593Smuzhiyun cs1_row = cap_info->cs1_row;
406*4882a593Smuzhiyun bank = cap_info->bk;
407*4882a593Smuzhiyun row_3_4 = cap_info->row_3_4;
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4) {
410*4882a593Smuzhiyun if (cs == 2 && row == cs1_row && !row_3_4) {
411*4882a593Smuzhiyun tmp = ((row - 13) << 4) | (1 << 3) | (bw << 1) |
412*4882a593Smuzhiyun die_bw;
413*4882a593Smuzhiyun for (i = 17; i < 21; i++) {
414*4882a593Smuzhiyun if (((tmp & 0xf) ==
415*4882a593Smuzhiyun (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
416*4882a593Smuzhiyun ((tmp & 0x70) <=
417*4882a593Smuzhiyun (ddr4_cfg_2_rbc[i - 10] & 0x70))) {
418*4882a593Smuzhiyun ddrconf = i;
419*4882a593Smuzhiyun goto out;
420*4882a593Smuzhiyun }
421*4882a593Smuzhiyun }
422*4882a593Smuzhiyun }
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun tmp = ((cs - 1) << 7) | ((row - 13) << 4) | (bw << 1) | die_bw;
425*4882a593Smuzhiyun for (i = 10; i < 21; i++) {
426*4882a593Smuzhiyun if (((tmp & 0xf) == (ddr4_cfg_2_rbc[i - 10] & 0xf)) &&
427*4882a593Smuzhiyun ((tmp & 0x70) <= (ddr4_cfg_2_rbc[i - 10] & 0x70)) &&
428*4882a593Smuzhiyun ((tmp & 0x80) <= (ddr4_cfg_2_rbc[i - 10] & 0x80))) {
429*4882a593Smuzhiyun ddrconf = i;
430*4882a593Smuzhiyun goto out;
431*4882a593Smuzhiyun }
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun } else {
434*4882a593Smuzhiyun if (cs == 2 && row == cs1_row && bank == 3) {
435*4882a593Smuzhiyun for (i = 5; i < 8; i++) {
436*4882a593Smuzhiyun if (((bw + col - 10) == (ddr_cfg_2_rbc[i] &
437*4882a593Smuzhiyun 0x7)) &&
438*4882a593Smuzhiyun ((row - 13) << 5) <= (ddr_cfg_2_rbc[i] &
439*4882a593Smuzhiyun (0x7 << 5))) {
440*4882a593Smuzhiyun ddrconf = i;
441*4882a593Smuzhiyun goto out;
442*4882a593Smuzhiyun }
443*4882a593Smuzhiyun }
444*4882a593Smuzhiyun }
445*4882a593Smuzhiyun
446*4882a593Smuzhiyun tmp = ((cs - 1) << 8) | ((row - 13) << 5) |
447*4882a593Smuzhiyun ((bw + col - 10) << 0);
448*4882a593Smuzhiyun if (bank == 3)
449*4882a593Smuzhiyun tmp |= (1 << 3);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun for (i = 0; i < 9; i++)
452*4882a593Smuzhiyun if (((tmp & 0x1f) == (ddr_cfg_2_rbc[i] & 0x1f)) &&
453*4882a593Smuzhiyun ((tmp & (7 << 5)) <=
454*4882a593Smuzhiyun (ddr_cfg_2_rbc[i] & (7 << 5))) &&
455*4882a593Smuzhiyun ((tmp & (1 << 8)) <=
456*4882a593Smuzhiyun (ddr_cfg_2_rbc[i] & (1 << 8)))) {
457*4882a593Smuzhiyun ddrconf = i;
458*4882a593Smuzhiyun goto out;
459*4882a593Smuzhiyun }
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun for (i = 0; i < 7; i++)
462*4882a593Smuzhiyun if (((tmp & 0x1f) == (ddr_cfg_2_rbc_p2[i] & 0x1f)) &&
463*4882a593Smuzhiyun ((tmp & (7 << 5)) <=
464*4882a593Smuzhiyun (ddr_cfg_2_rbc_p2[i] & (7 << 5))) &&
465*4882a593Smuzhiyun ((tmp & (1 << 8)) <=
466*4882a593Smuzhiyun (ddr_cfg_2_rbc_p2[i] & (1 << 8)))) {
467*4882a593Smuzhiyun ddrconf = i + 22;
468*4882a593Smuzhiyun goto out;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun if (cs == 1 && bank == 3 && row <= 17 &&
472*4882a593Smuzhiyun (col + bw) == 12)
473*4882a593Smuzhiyun ddrconf = 23;
474*4882a593Smuzhiyun }
475*4882a593Smuzhiyun
476*4882a593Smuzhiyun out:
477*4882a593Smuzhiyun if (ddrconf > 28)
478*4882a593Smuzhiyun printascii("calculate ddrconfig error\n");
479*4882a593Smuzhiyun
480*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4) {
481*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
482*4882a593Smuzhiyun if (ddrconf == d4_rbc_2_d3_rbc[i][0]) {
483*4882a593Smuzhiyun if (ddrconf == 21 && row > 16)
484*4882a593Smuzhiyun printascii("warn:ddrconf21 row > 16\n");
485*4882a593Smuzhiyun else
486*4882a593Smuzhiyun ddrconf = d4_rbc_2_d3_rbc[i][1];
487*4882a593Smuzhiyun break;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun }
490*4882a593Smuzhiyun }
491*4882a593Smuzhiyun
492*4882a593Smuzhiyun return ddrconf;
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun
sw_set_req(struct dram_info * dram)495*4882a593Smuzhiyun static void sw_set_req(struct dram_info *dram)
496*4882a593Smuzhiyun {
497*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun /* clear sw_done=0 */
500*4882a593Smuzhiyun writel(PCTL2_SW_DONE_CLEAR, pctl_base + DDR_PCTL2_SWCTL);
501*4882a593Smuzhiyun }
502*4882a593Smuzhiyun
sw_set_ack(struct dram_info * dram)503*4882a593Smuzhiyun static void sw_set_ack(struct dram_info *dram)
504*4882a593Smuzhiyun {
505*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
506*4882a593Smuzhiyun
507*4882a593Smuzhiyun /* set sw_done=1 */
508*4882a593Smuzhiyun writel(PCTL2_SW_DONE, pctl_base + DDR_PCTL2_SWCTL);
509*4882a593Smuzhiyun while (1) {
510*4882a593Smuzhiyun /* wait programming done */
511*4882a593Smuzhiyun if (readl(pctl_base + DDR_PCTL2_SWSTAT) &
512*4882a593Smuzhiyun PCTL2_SW_DONE_ACK)
513*4882a593Smuzhiyun break;
514*4882a593Smuzhiyun }
515*4882a593Smuzhiyun }
516*4882a593Smuzhiyun
set_ctl_address_map(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)517*4882a593Smuzhiyun static void set_ctl_address_map(struct dram_info *dram,
518*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
519*4882a593Smuzhiyun {
520*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
521*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
522*4882a593Smuzhiyun u32 ddrconf = cap_info->ddrconfig;
523*4882a593Smuzhiyun u32 i, row;
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun row = cap_info->cs0_row;
526*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4) {
527*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(d4_rbc_2_d3_rbc) ; i++) {
528*4882a593Smuzhiyun if (ddrconf == d4_rbc_2_d3_rbc[i][1]) {
529*4882a593Smuzhiyun ddrconf = d4_rbc_2_d3_rbc[i][0];
530*4882a593Smuzhiyun break;
531*4882a593Smuzhiyun }
532*4882a593Smuzhiyun }
533*4882a593Smuzhiyun }
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun if (ddrconf >= ARRAY_SIZE(addrmap)) {
536*4882a593Smuzhiyun printascii("set ctl address map fail\n");
537*4882a593Smuzhiyun return;
538*4882a593Smuzhiyun }
539*4882a593Smuzhiyun
540*4882a593Smuzhiyun sdram_copy_to_reg((u32 *)(pctl_base + DDR_PCTL2_ADDRMAP0),
541*4882a593Smuzhiyun &addrmap[ddrconf][0], ARRAY_SIZE(addrmap[ddrconf]) * 4);
542*4882a593Smuzhiyun
543*4882a593Smuzhiyun /* unused row set to 0xf */
544*4882a593Smuzhiyun for (i = 17; i >= row; i--)
545*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6 +
546*4882a593Smuzhiyun ((i - 12) * 8 / 32) * 4,
547*4882a593Smuzhiyun 0xf << ((i - 12) * 8 % 32));
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR3 && cap_info->row_3_4)
550*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_ADDRMAP6, 1 << 31);
551*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4 && cap_info->bw == 0x1)
552*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_PCCFG, 1 << 8);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun if (cap_info->rank == 1)
555*4882a593Smuzhiyun clrsetbits_le32(pctl_base + DDR_PCTL2_ADDRMAP0, 0x1f, 0x1f);
556*4882a593Smuzhiyun }
557*4882a593Smuzhiyun
phy_pll_set(struct dram_info * dram,u32 freq,u32 wait)558*4882a593Smuzhiyun static void phy_pll_set(struct dram_info *dram, u32 freq, u32 wait)
559*4882a593Smuzhiyun {
560*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
561*4882a593Smuzhiyun u32 fbdiv, prediv, postdiv, postdiv_en;
562*4882a593Smuzhiyun int delay = 1000;
563*4882a593Smuzhiyun
564*4882a593Smuzhiyun if (wait) {
565*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x53), PHY_PD_DISB);
566*4882a593Smuzhiyun while (!(readl(PHY_REG(phy_base, 0x90)) & PHY_PLL_LOCK)) {
567*4882a593Smuzhiyun udelay(1);
568*4882a593Smuzhiyun if (delay-- <= 0) {
569*4882a593Smuzhiyun printascii("ERROR: phy pll lock timeout!\n");
570*4882a593Smuzhiyun while (1)
571*4882a593Smuzhiyun ;
572*4882a593Smuzhiyun }
573*4882a593Smuzhiyun }
574*4882a593Smuzhiyun } else {
575*4882a593Smuzhiyun freq /= MHz;
576*4882a593Smuzhiyun prediv = 1;
577*4882a593Smuzhiyun if (freq <= 200) {
578*4882a593Smuzhiyun fbdiv = 16;
579*4882a593Smuzhiyun postdiv = 2;
580*4882a593Smuzhiyun postdiv_en = 1;
581*4882a593Smuzhiyun } else if (freq <= 456) {
582*4882a593Smuzhiyun fbdiv = 8;
583*4882a593Smuzhiyun postdiv = 1;
584*4882a593Smuzhiyun postdiv_en = 1;
585*4882a593Smuzhiyun } else {
586*4882a593Smuzhiyun fbdiv = 4;
587*4882a593Smuzhiyun postdiv = 0;
588*4882a593Smuzhiyun postdiv_en = 0;
589*4882a593Smuzhiyun }
590*4882a593Smuzhiyun writel(fbdiv & 0xff, PHY_REG(phy_base, 0x50));
591*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_PBDIV_BIT9_MASK,
592*4882a593Smuzhiyun (fbdiv >> 8) & 1);
593*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x51), PHY_POSTDIV_EN_MASK,
594*4882a593Smuzhiyun postdiv_en << PHY_POSTDIV_EN_SHIFT);
595*4882a593Smuzhiyun
596*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x52),
597*4882a593Smuzhiyun PHY_PREDIV_MASK << PHY_PREDIV_SHIFT, prediv);
598*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x53),
599*4882a593Smuzhiyun PHY_POSTDIV_MASK << PHY_POSTDIV_SHIFT,
600*4882a593Smuzhiyun postdiv << PHY_POSTDIV_SHIFT);
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun }
603*4882a593Smuzhiyun
604*4882a593Smuzhiyun static const u16 d3_phy_drv_2_ohm[][2] = {
605*4882a593Smuzhiyun {PHY_DDR3_RON_455ohm, 455},
606*4882a593Smuzhiyun {PHY_DDR3_RON_230ohm, 230},
607*4882a593Smuzhiyun {PHY_DDR3_RON_153ohm, 153},
608*4882a593Smuzhiyun {PHY_DDR3_RON_115ohm, 115},
609*4882a593Smuzhiyun {PHY_DDR3_RON_91ohm, 91},
610*4882a593Smuzhiyun {PHY_DDR3_RON_76ohm, 76},
611*4882a593Smuzhiyun {PHY_DDR3_RON_65ohm, 65},
612*4882a593Smuzhiyun {PHY_DDR3_RON_57ohm, 57},
613*4882a593Smuzhiyun {PHY_DDR3_RON_51ohm, 51},
614*4882a593Smuzhiyun {PHY_DDR3_RON_46ohm, 46},
615*4882a593Smuzhiyun {PHY_DDR3_RON_41ohm, 41},
616*4882a593Smuzhiyun {PHY_DDR3_RON_38ohm, 38},
617*4882a593Smuzhiyun {PHY_DDR3_RON_35ohm, 35},
618*4882a593Smuzhiyun {PHY_DDR3_RON_32ohm, 32},
619*4882a593Smuzhiyun {PHY_DDR3_RON_30ohm, 30},
620*4882a593Smuzhiyun {PHY_DDR3_RON_28ohm, 28},
621*4882a593Smuzhiyun {PHY_DDR3_RON_27ohm, 27},
622*4882a593Smuzhiyun {PHY_DDR3_RON_25ohm, 25},
623*4882a593Smuzhiyun {PHY_DDR3_RON_24ohm, 24},
624*4882a593Smuzhiyun {PHY_DDR3_RON_23ohm, 23},
625*4882a593Smuzhiyun {PHY_DDR3_RON_22ohm, 22},
626*4882a593Smuzhiyun {PHY_DDR3_RON_21ohm, 21},
627*4882a593Smuzhiyun {PHY_DDR3_RON_20ohm, 20}
628*4882a593Smuzhiyun };
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun static u16 d3_phy_odt_2_ohm[][2] = {
631*4882a593Smuzhiyun {PHY_DDR3_RTT_DISABLE, 0},
632*4882a593Smuzhiyun {PHY_DDR3_RTT_561ohm, 561},
633*4882a593Smuzhiyun {PHY_DDR3_RTT_282ohm, 282},
634*4882a593Smuzhiyun {PHY_DDR3_RTT_188ohm, 188},
635*4882a593Smuzhiyun {PHY_DDR3_RTT_141ohm, 141},
636*4882a593Smuzhiyun {PHY_DDR3_RTT_113ohm, 113},
637*4882a593Smuzhiyun {PHY_DDR3_RTT_94ohm, 94},
638*4882a593Smuzhiyun {PHY_DDR3_RTT_81ohm, 81},
639*4882a593Smuzhiyun {PHY_DDR3_RTT_72ohm, 72},
640*4882a593Smuzhiyun {PHY_DDR3_RTT_64ohm, 64},
641*4882a593Smuzhiyun {PHY_DDR3_RTT_58ohm, 58},
642*4882a593Smuzhiyun {PHY_DDR3_RTT_52ohm, 52},
643*4882a593Smuzhiyun {PHY_DDR3_RTT_48ohm, 48},
644*4882a593Smuzhiyun {PHY_DDR3_RTT_44ohm, 44},
645*4882a593Smuzhiyun {PHY_DDR3_RTT_41ohm, 41},
646*4882a593Smuzhiyun {PHY_DDR3_RTT_38ohm, 38},
647*4882a593Smuzhiyun {PHY_DDR3_RTT_37ohm, 37},
648*4882a593Smuzhiyun {PHY_DDR3_RTT_34ohm, 34},
649*4882a593Smuzhiyun {PHY_DDR3_RTT_32ohm, 32},
650*4882a593Smuzhiyun {PHY_DDR3_RTT_31ohm, 31},
651*4882a593Smuzhiyun {PHY_DDR3_RTT_29ohm, 29},
652*4882a593Smuzhiyun {PHY_DDR3_RTT_28ohm, 28},
653*4882a593Smuzhiyun {PHY_DDR3_RTT_27ohm, 27},
654*4882a593Smuzhiyun {PHY_DDR3_RTT_25ohm, 25}
655*4882a593Smuzhiyun };
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun static u16 d4lp3_phy_drv_2_ohm[][2] = {
658*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_482ohm, 482},
659*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_244ohm, 244},
660*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_162ohm, 162},
661*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_122ohm, 122},
662*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_97ohm, 97},
663*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_81ohm, 81},
664*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_69ohm, 69},
665*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_61ohm, 61},
666*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_54ohm, 54},
667*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_48ohm, 48},
668*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_44ohm, 44},
669*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_40ohm, 40},
670*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_37ohm, 37},
671*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_34ohm, 34},
672*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_32ohm, 32},
673*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_30ohm, 30},
674*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_28ohm, 28},
675*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_27ohm, 27},
676*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_25ohm, 25},
677*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_24ohm, 24},
678*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_23ohm, 23},
679*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_22ohm, 22},
680*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RON_21ohm, 21}
681*4882a593Smuzhiyun };
682*4882a593Smuzhiyun
683*4882a593Smuzhiyun static u16 d4lp3_phy_odt_2_ohm[][2] = {
684*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_DISABLE, 0},
685*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_586ohm, 586},
686*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_294ohm, 294},
687*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_196ohm, 196},
688*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_148ohm, 148},
689*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_118ohm, 118},
690*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_99ohm, 99},
691*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_85ohm, 58},
692*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_76ohm, 76},
693*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_67ohm, 67},
694*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_60ohm, 60},
695*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_55ohm, 55},
696*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_50ohm, 50},
697*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_46ohm, 46},
698*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_43ohm, 43},
699*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_40ohm, 40},
700*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_38ohm, 38},
701*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_36ohm, 36},
702*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_34ohm, 34},
703*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_32ohm, 32},
704*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_31ohm, 31},
705*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_29ohm, 29},
706*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_28ohm, 28},
707*4882a593Smuzhiyun {PHY_DDR4_LPDDR3_RTT_27ohm, 27}
708*4882a593Smuzhiyun };
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun static u16 lp4_phy_drv_2_ohm[][2] = {
711*4882a593Smuzhiyun {PHY_LPDDR4_RON_501ohm, 501},
712*4882a593Smuzhiyun {PHY_LPDDR4_RON_253ohm, 253},
713*4882a593Smuzhiyun {PHY_LPDDR4_RON_168ohm, 168},
714*4882a593Smuzhiyun {PHY_LPDDR4_RON_126ohm, 126},
715*4882a593Smuzhiyun {PHY_LPDDR4_RON_101ohm, 101},
716*4882a593Smuzhiyun {PHY_LPDDR4_RON_84ohm, 84},
717*4882a593Smuzhiyun {PHY_LPDDR4_RON_72ohm, 72},
718*4882a593Smuzhiyun {PHY_LPDDR4_RON_63ohm, 63},
719*4882a593Smuzhiyun {PHY_LPDDR4_RON_56ohm, 56},
720*4882a593Smuzhiyun {PHY_LPDDR4_RON_50ohm, 50},
721*4882a593Smuzhiyun {PHY_LPDDR4_RON_46ohm, 46},
722*4882a593Smuzhiyun {PHY_LPDDR4_RON_42ohm, 42},
723*4882a593Smuzhiyun {PHY_LPDDR4_RON_38ohm, 38},
724*4882a593Smuzhiyun {PHY_LPDDR4_RON_36ohm, 36},
725*4882a593Smuzhiyun {PHY_LPDDR4_RON_33ohm, 33},
726*4882a593Smuzhiyun {PHY_LPDDR4_RON_31ohm, 31},
727*4882a593Smuzhiyun {PHY_LPDDR4_RON_29ohm, 29},
728*4882a593Smuzhiyun {PHY_LPDDR4_RON_28ohm, 28},
729*4882a593Smuzhiyun {PHY_LPDDR4_RON_26ohm, 26},
730*4882a593Smuzhiyun {PHY_LPDDR4_RON_25ohm, 25},
731*4882a593Smuzhiyun {PHY_LPDDR4_RON_24ohm, 24},
732*4882a593Smuzhiyun {PHY_LPDDR4_RON_23ohm, 23},
733*4882a593Smuzhiyun {PHY_LPDDR4_RON_22ohm, 22}
734*4882a593Smuzhiyun };
735*4882a593Smuzhiyun
736*4882a593Smuzhiyun static u16 lp4_phy_odt_2_ohm[][2] = {
737*4882a593Smuzhiyun {PHY_LPDDR4_RTT_DISABLE, 0},
738*4882a593Smuzhiyun {PHY_LPDDR4_RTT_604ohm, 604},
739*4882a593Smuzhiyun {PHY_LPDDR4_RTT_303ohm, 303},
740*4882a593Smuzhiyun {PHY_LPDDR4_RTT_202ohm, 202},
741*4882a593Smuzhiyun {PHY_LPDDR4_RTT_152ohm, 152},
742*4882a593Smuzhiyun {PHY_LPDDR4_RTT_122ohm, 122},
743*4882a593Smuzhiyun {PHY_LPDDR4_RTT_101ohm, 101},
744*4882a593Smuzhiyun {PHY_LPDDR4_RTT_87ohm, 87},
745*4882a593Smuzhiyun {PHY_LPDDR4_RTT_78ohm, 78},
746*4882a593Smuzhiyun {PHY_LPDDR4_RTT_69ohm, 69},
747*4882a593Smuzhiyun {PHY_LPDDR4_RTT_62ohm, 62},
748*4882a593Smuzhiyun {PHY_LPDDR4_RTT_56ohm, 56},
749*4882a593Smuzhiyun {PHY_LPDDR4_RTT_52ohm, 52},
750*4882a593Smuzhiyun {PHY_LPDDR4_RTT_48ohm, 48},
751*4882a593Smuzhiyun {PHY_LPDDR4_RTT_44ohm, 44},
752*4882a593Smuzhiyun {PHY_LPDDR4_RTT_41ohm, 41},
753*4882a593Smuzhiyun {PHY_LPDDR4_RTT_39ohm, 39},
754*4882a593Smuzhiyun {PHY_LPDDR4_RTT_37ohm, 37},
755*4882a593Smuzhiyun {PHY_LPDDR4_RTT_35ohm, 35},
756*4882a593Smuzhiyun {PHY_LPDDR4_RTT_33ohm, 33},
757*4882a593Smuzhiyun {PHY_LPDDR4_RTT_32ohm, 32},
758*4882a593Smuzhiyun {PHY_LPDDR4_RTT_30ohm, 30},
759*4882a593Smuzhiyun {PHY_LPDDR4_RTT_29ohm, 29},
760*4882a593Smuzhiyun {PHY_LPDDR4_RTT_27ohm, 27}
761*4882a593Smuzhiyun };
762*4882a593Smuzhiyun
lp4_odt_calc(u32 odt_ohm)763*4882a593Smuzhiyun static u32 lp4_odt_calc(u32 odt_ohm)
764*4882a593Smuzhiyun {
765*4882a593Smuzhiyun u32 odt;
766*4882a593Smuzhiyun
767*4882a593Smuzhiyun if (odt_ohm == 0)
768*4882a593Smuzhiyun odt = LPDDR4_DQODT_DIS;
769*4882a593Smuzhiyun else if (odt_ohm <= 40)
770*4882a593Smuzhiyun odt = LPDDR4_DQODT_40;
771*4882a593Smuzhiyun else if (odt_ohm <= 48)
772*4882a593Smuzhiyun odt = LPDDR4_DQODT_48;
773*4882a593Smuzhiyun else if (odt_ohm <= 60)
774*4882a593Smuzhiyun odt = LPDDR4_DQODT_60;
775*4882a593Smuzhiyun else if (odt_ohm <= 80)
776*4882a593Smuzhiyun odt = LPDDR4_DQODT_80;
777*4882a593Smuzhiyun else if (odt_ohm <= 120)
778*4882a593Smuzhiyun odt = LPDDR4_DQODT_120;
779*4882a593Smuzhiyun else
780*4882a593Smuzhiyun odt = LPDDR4_DQODT_240;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun return odt;
783*4882a593Smuzhiyun }
784*4882a593Smuzhiyun
get_ddr_drv_odt_info(u32 dramtype)785*4882a593Smuzhiyun static void *get_ddr_drv_odt_info(u32 dramtype)
786*4882a593Smuzhiyun {
787*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
788*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
789*4882a593Smuzhiyun void *ddr_info = 0;
790*4882a593Smuzhiyun
791*4882a593Smuzhiyun if (dramtype == DDR4)
792*4882a593Smuzhiyun ddr_info = (void *)common_info + index->ddr4_index.offset * 4;
793*4882a593Smuzhiyun else if (dramtype == DDR3)
794*4882a593Smuzhiyun ddr_info = (void *)common_info + index->ddr3_index.offset * 4;
795*4882a593Smuzhiyun else if (dramtype == LPDDR3)
796*4882a593Smuzhiyun ddr_info = (void *)common_info + index->lp3_index.offset * 4;
797*4882a593Smuzhiyun else if (dramtype == LPDDR4)
798*4882a593Smuzhiyun ddr_info = (void *)common_info + index->lp4_index.offset * 4;
799*4882a593Smuzhiyun else if (dramtype == LPDDR4X)
800*4882a593Smuzhiyun ddr_info = (void *)common_info + index->lp4x_index.offset * 4;
801*4882a593Smuzhiyun else
802*4882a593Smuzhiyun printascii("unsupported dram type\n");
803*4882a593Smuzhiyun return ddr_info;
804*4882a593Smuzhiyun }
805*4882a593Smuzhiyun
set_lp4_vref(struct dram_info * dram,struct lp4_info * lp4_info,u32 freq_mhz,u32 dst_fsp,u32 dramtype)806*4882a593Smuzhiyun static void set_lp4_vref(struct dram_info *dram, struct lp4_info *lp4_info,
807*4882a593Smuzhiyun u32 freq_mhz, u32 dst_fsp, u32 dramtype)
808*4882a593Smuzhiyun {
809*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
810*4882a593Smuzhiyun u32 ca_vref, dq_vref;
811*4882a593Smuzhiyun
812*4882a593Smuzhiyun if (freq_mhz <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
813*4882a593Smuzhiyun ca_vref = LP4_CA_VREF(lp4_info->vref_when_odtoff);
814*4882a593Smuzhiyun else
815*4882a593Smuzhiyun ca_vref = LP4_CA_VREF(lp4_info->vref_when_odten);
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun if (freq_mhz <= LP4_DQ_ODT_EN_FREQ(lp4_info->dq_odten_freq))
818*4882a593Smuzhiyun dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odtoff);
819*4882a593Smuzhiyun else
820*4882a593Smuzhiyun dq_vref = LP4_DQ_VREF(lp4_info->vref_when_odten);
821*4882a593Smuzhiyun
822*4882a593Smuzhiyun if (dramtype == LPDDR4) {
823*4882a593Smuzhiyun if (ca_vref < 100)
824*4882a593Smuzhiyun ca_vref = 100;
825*4882a593Smuzhiyun if (ca_vref > 420)
826*4882a593Smuzhiyun ca_vref = 420;
827*4882a593Smuzhiyun
828*4882a593Smuzhiyun if (ca_vref <= 300)
829*4882a593Smuzhiyun ca_vref = (0 << 6) | (ca_vref - 100) / 4;
830*4882a593Smuzhiyun else
831*4882a593Smuzhiyun ca_vref = (1 << 6) | (ca_vref - 220) / 4;
832*4882a593Smuzhiyun
833*4882a593Smuzhiyun if (dq_vref < 100)
834*4882a593Smuzhiyun dq_vref = 100;
835*4882a593Smuzhiyun if (dq_vref > 420)
836*4882a593Smuzhiyun dq_vref = 420;
837*4882a593Smuzhiyun
838*4882a593Smuzhiyun if (dq_vref <= 300)
839*4882a593Smuzhiyun dq_vref = (0 << 6) | (dq_vref - 100) / 4;
840*4882a593Smuzhiyun else
841*4882a593Smuzhiyun dq_vref = (1 << 6) | (dq_vref - 220) / 4;
842*4882a593Smuzhiyun } else {
843*4882a593Smuzhiyun ca_vref = ca_vref * 11 / 6;
844*4882a593Smuzhiyun if (ca_vref < 150)
845*4882a593Smuzhiyun ca_vref = 150;
846*4882a593Smuzhiyun if (ca_vref > 629)
847*4882a593Smuzhiyun ca_vref = 629;
848*4882a593Smuzhiyun
849*4882a593Smuzhiyun if (ca_vref <= 449)
850*4882a593Smuzhiyun ca_vref = (0 << 6) | (ca_vref - 150) / 4;
851*4882a593Smuzhiyun else
852*4882a593Smuzhiyun ca_vref = (1 << 6) | (ca_vref - 329) / 4;
853*4882a593Smuzhiyun
854*4882a593Smuzhiyun if (dq_vref < 150)
855*4882a593Smuzhiyun dq_vref = 150;
856*4882a593Smuzhiyun if (dq_vref > 629)
857*4882a593Smuzhiyun dq_vref = 629;
858*4882a593Smuzhiyun
859*4882a593Smuzhiyun if (dq_vref <= 449)
860*4882a593Smuzhiyun dq_vref = (0 << 6) | (dq_vref - 150) / 6;
861*4882a593Smuzhiyun else
862*4882a593Smuzhiyun dq_vref = (1 << 6) | (dq_vref - 329) / 6;
863*4882a593Smuzhiyun }
864*4882a593Smuzhiyun sw_set_req(dram);
865*4882a593Smuzhiyun clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
866*4882a593Smuzhiyun DDR_PCTL2_INIT6,
867*4882a593Smuzhiyun PCTL2_MR_MASK << PCTL2_LPDDR4_MR12_SHIFT,
868*4882a593Smuzhiyun ca_vref << PCTL2_LPDDR4_MR12_SHIFT);
869*4882a593Smuzhiyun
870*4882a593Smuzhiyun clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
871*4882a593Smuzhiyun DDR_PCTL2_INIT7,
872*4882a593Smuzhiyun PCTL2_MR_MASK << PCTL2_LPDDR4_MR14_SHIFT,
873*4882a593Smuzhiyun dq_vref << PCTL2_LPDDR4_MR14_SHIFT);
874*4882a593Smuzhiyun sw_set_ack(dram);
875*4882a593Smuzhiyun }
876*4882a593Smuzhiyun
set_ds_odt(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 dst_fsp)877*4882a593Smuzhiyun static void set_ds_odt(struct dram_info *dram,
878*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params, u32 dst_fsp)
879*4882a593Smuzhiyun {
880*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
881*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
882*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
883*4882a593Smuzhiyun struct ddr2_3_4_lp2_3_info *ddr_info;
884*4882a593Smuzhiyun struct lp4_info *lp4_info;
885*4882a593Smuzhiyun u32 i, j, tmp;
886*4882a593Smuzhiyun const u16 (*p_drv)[2];
887*4882a593Smuzhiyun const u16 (*p_odt)[2];
888*4882a593Smuzhiyun u32 drv_info, sr_info;
889*4882a593Smuzhiyun u32 phy_dq_drv_ohm, phy_clk_drv_ohm, phy_ca_drv_ohm, dram_drv_ohm;
890*4882a593Smuzhiyun u32 phy_odt_ohm, dram_odt_ohm;
891*4882a593Smuzhiyun u32 lp4_pu_cal, phy_lp4_drv_pd_en;
892*4882a593Smuzhiyun u32 phy_odt_up_en, phy_odt_dn_en;
893*4882a593Smuzhiyun u32 sr_dq, sr_clk;
894*4882a593Smuzhiyun u32 freq = sdram_params->base.ddr_freq;
895*4882a593Smuzhiyun u32 mr1_mr3, mr11, mr22, vref_out, vref_inner;
896*4882a593Smuzhiyun u32 phy_clk_drv = 0, phy_odt = 0, phy_ca_drv = 0, dram_caodt_ohm = 0;
897*4882a593Smuzhiyun u32 phy_dq_drv = 0;
898*4882a593Smuzhiyun u32 phy_odt_up = 0, phy_odt_dn = 0;
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun ddr_info = get_ddr_drv_odt_info(dramtype);
901*4882a593Smuzhiyun lp4_info = (void *)ddr_info;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun if (!ddr_info)
904*4882a593Smuzhiyun return;
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun /* dram odt en freq control phy drv, dram odt and phy sr */
907*4882a593Smuzhiyun if (freq <= DRAMODT_EN_FREQ(ddr_info->odten_freq)) {
908*4882a593Smuzhiyun drv_info = ddr_info->drv_when_odtoff;
909*4882a593Smuzhiyun dram_odt_ohm = 0;
910*4882a593Smuzhiyun sr_info = ddr_info->sr_when_odtoff;
911*4882a593Smuzhiyun phy_lp4_drv_pd_en =
912*4882a593Smuzhiyun PHY_LP4_DRV_PULLDOWN_EN_ODTOFF(lp4_info->odt_info);
913*4882a593Smuzhiyun } else {
914*4882a593Smuzhiyun drv_info = ddr_info->drv_when_odten;
915*4882a593Smuzhiyun dram_odt_ohm = ODT_INFO_DRAM_ODT(ddr_info->odt_info);
916*4882a593Smuzhiyun sr_info = ddr_info->sr_when_odten;
917*4882a593Smuzhiyun phy_lp4_drv_pd_en =
918*4882a593Smuzhiyun PHY_LP4_DRV_PULLDOWN_EN_ODTEN(lp4_info->odt_info);
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun phy_dq_drv_ohm =
921*4882a593Smuzhiyun DRV_INFO_PHY_DQ_DRV(drv_info);
922*4882a593Smuzhiyun phy_clk_drv_ohm =
923*4882a593Smuzhiyun DRV_INFO_PHY_CLK_DRV(drv_info);
924*4882a593Smuzhiyun phy_ca_drv_ohm =
925*4882a593Smuzhiyun DRV_INFO_PHY_CA_DRV(drv_info);
926*4882a593Smuzhiyun
927*4882a593Smuzhiyun sr_dq = DQ_SR_INFO(sr_info);
928*4882a593Smuzhiyun sr_clk = CLK_SR_INFO(sr_info);
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun /* phy odt en freq control dram drv and phy odt */
931*4882a593Smuzhiyun if (freq <= PHYODT_EN_FREQ(ddr_info->odten_freq)) {
932*4882a593Smuzhiyun dram_drv_ohm = DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odtoff);
933*4882a593Smuzhiyun lp4_pu_cal = LP4_DRV_PU_CAL_ODTOFF(lp4_info->odt_info);
934*4882a593Smuzhiyun phy_odt_ohm = 0;
935*4882a593Smuzhiyun phy_odt_up_en = 0;
936*4882a593Smuzhiyun phy_odt_dn_en = 0;
937*4882a593Smuzhiyun } else {
938*4882a593Smuzhiyun dram_drv_ohm =
939*4882a593Smuzhiyun DRV_INFO_DRAM_DQ_DRV(ddr_info->drv_when_odten);
940*4882a593Smuzhiyun phy_odt_ohm = ODT_INFO_PHY_ODT(ddr_info->odt_info);
941*4882a593Smuzhiyun phy_odt_up_en =
942*4882a593Smuzhiyun ODT_INFO_PULLUP_EN(ddr_info->odt_info);
943*4882a593Smuzhiyun phy_odt_dn_en =
944*4882a593Smuzhiyun ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
945*4882a593Smuzhiyun lp4_pu_cal = LP4_DRV_PU_CAL_ODTEN(lp4_info->odt_info);
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
949*4882a593Smuzhiyun if (phy_odt_ohm) {
950*4882a593Smuzhiyun phy_odt_up_en = 0;
951*4882a593Smuzhiyun phy_odt_dn_en = 1;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun if (freq <= LP4_CA_ODT_EN_FREQ(lp4_info->ca_odten_freq))
954*4882a593Smuzhiyun dram_caodt_ohm = 0;
955*4882a593Smuzhiyun else
956*4882a593Smuzhiyun dram_caodt_ohm =
957*4882a593Smuzhiyun ODT_INFO_LP4_CA_ODT(lp4_info->odt_info);
958*4882a593Smuzhiyun }
959*4882a593Smuzhiyun
960*4882a593Smuzhiyun if (dramtype == DDR3) {
961*4882a593Smuzhiyun p_drv = d3_phy_drv_2_ohm;
962*4882a593Smuzhiyun p_odt = d3_phy_odt_2_ohm;
963*4882a593Smuzhiyun } else if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
964*4882a593Smuzhiyun p_drv = lp4_phy_drv_2_ohm;
965*4882a593Smuzhiyun p_odt = lp4_phy_odt_2_ohm;
966*4882a593Smuzhiyun } else {
967*4882a593Smuzhiyun p_drv = d4lp3_phy_drv_2_ohm;
968*4882a593Smuzhiyun p_odt = d4lp3_phy_odt_2_ohm;
969*4882a593Smuzhiyun }
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
972*4882a593Smuzhiyun if (phy_dq_drv_ohm <= *(*(p_drv + i) + 1)) {
973*4882a593Smuzhiyun phy_dq_drv = **(p_drv + i);
974*4882a593Smuzhiyun break;
975*4882a593Smuzhiyun }
976*4882a593Smuzhiyun if (i == 0)
977*4882a593Smuzhiyun break;
978*4882a593Smuzhiyun }
979*4882a593Smuzhiyun for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
980*4882a593Smuzhiyun if (phy_clk_drv_ohm <= *(*(p_drv + i) + 1)) {
981*4882a593Smuzhiyun phy_clk_drv = **(p_drv + i);
982*4882a593Smuzhiyun break;
983*4882a593Smuzhiyun }
984*4882a593Smuzhiyun if (i == 0)
985*4882a593Smuzhiyun break;
986*4882a593Smuzhiyun }
987*4882a593Smuzhiyun for (i = ARRAY_SIZE(d3_phy_drv_2_ohm) - 1; ; i--) {
988*4882a593Smuzhiyun if (phy_ca_drv_ohm <= *(*(p_drv + i) + 1)) {
989*4882a593Smuzhiyun phy_ca_drv = **(p_drv + i);
990*4882a593Smuzhiyun break;
991*4882a593Smuzhiyun }
992*4882a593Smuzhiyun if (i == 0)
993*4882a593Smuzhiyun break;
994*4882a593Smuzhiyun }
995*4882a593Smuzhiyun if (!phy_odt_ohm)
996*4882a593Smuzhiyun phy_odt = 0;
997*4882a593Smuzhiyun else
998*4882a593Smuzhiyun for (i = ARRAY_SIZE(d4lp3_phy_odt_2_ohm) - 1; ; i--) {
999*4882a593Smuzhiyun if (phy_odt_ohm <= *(*(p_odt + i) + 1)) {
1000*4882a593Smuzhiyun phy_odt = **(p_odt + i);
1001*4882a593Smuzhiyun break;
1002*4882a593Smuzhiyun }
1003*4882a593Smuzhiyun if (i == 0)
1004*4882a593Smuzhiyun break;
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun if (dramtype != LPDDR4 && dramtype != LPDDR4X) {
1008*4882a593Smuzhiyun if (!phy_odt_ohm || (phy_odt_up_en && phy_odt_dn_en))
1009*4882a593Smuzhiyun vref_inner = 0x80;
1010*4882a593Smuzhiyun else if (phy_odt_up_en)
1011*4882a593Smuzhiyun vref_inner = (2 * dram_drv_ohm + phy_odt_ohm) * 128 /
1012*4882a593Smuzhiyun (dram_drv_ohm + phy_odt_ohm);
1013*4882a593Smuzhiyun else
1014*4882a593Smuzhiyun vref_inner = phy_odt_ohm * 128 /
1015*4882a593Smuzhiyun (phy_odt_ohm + dram_drv_ohm);
1016*4882a593Smuzhiyun
1017*4882a593Smuzhiyun if (dramtype != DDR3 && dram_odt_ohm)
1018*4882a593Smuzhiyun vref_out = (2 * phy_dq_drv_ohm + dram_odt_ohm) * 128 /
1019*4882a593Smuzhiyun (phy_dq_drv_ohm + dram_odt_ohm);
1020*4882a593Smuzhiyun else
1021*4882a593Smuzhiyun vref_out = 0x80;
1022*4882a593Smuzhiyun } else {
1023*4882a593Smuzhiyun /* for lp4 and lp4x*/
1024*4882a593Smuzhiyun if (phy_odt_ohm)
1025*4882a593Smuzhiyun vref_inner =
1026*4882a593Smuzhiyun (PHY_LP4_DQ_VREF(lp4_info->vref_when_odten) *
1027*4882a593Smuzhiyun 256) / 1000;
1028*4882a593Smuzhiyun else
1029*4882a593Smuzhiyun vref_inner =
1030*4882a593Smuzhiyun (PHY_LP4_DQ_VREF(lp4_info->vref_when_odtoff) *
1031*4882a593Smuzhiyun 256) / 1000;
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun vref_out = 0x80;
1034*4882a593Smuzhiyun }
1035*4882a593Smuzhiyun
1036*4882a593Smuzhiyun /* default ZQCALIB bypass mode */
1037*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x100), 0x1f, phy_ca_drv);
1038*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x101), 0x1f, phy_ca_drv);
1039*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x102), 0x1f, phy_clk_drv);
1040*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x103), 0x1f, phy_clk_drv);
1041*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
1042*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_clk_drv);
1043*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_clk_drv);
1044*4882a593Smuzhiyun } else {
1045*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x107), 0x1f, phy_ca_drv);
1046*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x108), 0x1f, phy_ca_drv);
1047*4882a593Smuzhiyun }
1048*4882a593Smuzhiyun /* clk / cmd slew rate */
1049*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x106), 0x1f, sr_clk);
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun phy_lp4_drv_pd_en = (~phy_lp4_drv_pd_en) & 1;
1052*4882a593Smuzhiyun if (phy_odt_up_en)
1053*4882a593Smuzhiyun phy_odt_up = phy_odt;
1054*4882a593Smuzhiyun if (phy_odt_dn_en)
1055*4882a593Smuzhiyun phy_odt_dn = phy_odt;
1056*4882a593Smuzhiyun
1057*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1058*4882a593Smuzhiyun j = 0x110 + i * 0x10;
1059*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, j + 1), 0x1f, phy_odt_up);
1060*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, j), 0x1f, phy_odt_dn);
1061*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, j + 2), 0x1f, phy_dq_drv);
1062*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, j + 3), 0x1f, phy_dq_drv);
1063*4882a593Smuzhiyun writel(vref_inner, PHY_REG(phy_base, 0x118 + i * 0x10));
1064*4882a593Smuzhiyun
1065*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10),
1066*4882a593Smuzhiyun 1 << 3, phy_lp4_drv_pd_en << 3);
1067*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X)
1068*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x114 + i * 0x10), BIT(5));
1069*4882a593Smuzhiyun /* dq slew rate */
1070*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x117 + i * 0x10),
1071*4882a593Smuzhiyun 0x1f, sr_dq);
1072*4882a593Smuzhiyun }
1073*4882a593Smuzhiyun
1074*4882a593Smuzhiyun /* reg_rx_vref_value_update */
1075*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1076*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1077*4882a593Smuzhiyun
1078*4882a593Smuzhiyun /* RAM VREF */
1079*4882a593Smuzhiyun writel(vref_out, PHY_REG(phy_base, 0x105));
1080*4882a593Smuzhiyun if (dramtype == LPDDR3)
1081*4882a593Smuzhiyun udelay(100);
1082*4882a593Smuzhiyun
1083*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X)
1084*4882a593Smuzhiyun set_lp4_vref(dram, lp4_info, freq, dst_fsp, dramtype);
1085*4882a593Smuzhiyun
1086*4882a593Smuzhiyun if (dramtype == DDR3 || dramtype == DDR4) {
1087*4882a593Smuzhiyun mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1088*4882a593Smuzhiyun DDR_PCTL2_INIT3);
1089*4882a593Smuzhiyun mr1_mr3 = mr1_mr3 >> PCTL2_DDR34_MR1_SHIFT & PCTL2_MR_MASK;
1090*4882a593Smuzhiyun } else {
1091*4882a593Smuzhiyun mr1_mr3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1092*4882a593Smuzhiyun DDR_PCTL2_INIT4);
1093*4882a593Smuzhiyun mr1_mr3 = mr1_mr3 >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK;
1094*4882a593Smuzhiyun }
1095*4882a593Smuzhiyun
1096*4882a593Smuzhiyun if (dramtype == DDR3) {
1097*4882a593Smuzhiyun mr1_mr3 &= ~(DDR3_DS_MASK | DDR3_RTT_NOM_MASK);
1098*4882a593Smuzhiyun if (dram_drv_ohm == 34)
1099*4882a593Smuzhiyun mr1_mr3 |= DDR3_DS_34;
1100*4882a593Smuzhiyun
1101*4882a593Smuzhiyun if (dram_odt_ohm == 0)
1102*4882a593Smuzhiyun mr1_mr3 |= DDR3_RTT_NOM_DIS;
1103*4882a593Smuzhiyun else if (dram_odt_ohm <= 40)
1104*4882a593Smuzhiyun mr1_mr3 |= DDR3_RTT_NOM_40;
1105*4882a593Smuzhiyun else if (dram_odt_ohm <= 60)
1106*4882a593Smuzhiyun mr1_mr3 |= DDR3_RTT_NOM_60;
1107*4882a593Smuzhiyun else
1108*4882a593Smuzhiyun mr1_mr3 |= DDR3_RTT_NOM_120;
1109*4882a593Smuzhiyun
1110*4882a593Smuzhiyun } else if (dramtype == DDR4) {
1111*4882a593Smuzhiyun mr1_mr3 &= ~(DDR4_DS_MASK | DDR4_RTT_NOM_MASK);
1112*4882a593Smuzhiyun if (dram_drv_ohm == 48)
1113*4882a593Smuzhiyun mr1_mr3 |= DDR4_DS_48;
1114*4882a593Smuzhiyun
1115*4882a593Smuzhiyun if (dram_odt_ohm == 0)
1116*4882a593Smuzhiyun mr1_mr3 |= DDR4_RTT_NOM_DIS;
1117*4882a593Smuzhiyun else if (dram_odt_ohm <= 34)
1118*4882a593Smuzhiyun mr1_mr3 |= DDR4_RTT_NOM_34;
1119*4882a593Smuzhiyun else if (dram_odt_ohm <= 40)
1120*4882a593Smuzhiyun mr1_mr3 |= DDR4_RTT_NOM_40;
1121*4882a593Smuzhiyun else if (dram_odt_ohm <= 48)
1122*4882a593Smuzhiyun mr1_mr3 |= DDR4_RTT_NOM_48;
1123*4882a593Smuzhiyun else if (dram_odt_ohm <= 60)
1124*4882a593Smuzhiyun mr1_mr3 |= DDR4_RTT_NOM_60;
1125*4882a593Smuzhiyun else
1126*4882a593Smuzhiyun mr1_mr3 |= DDR4_RTT_NOM_120;
1127*4882a593Smuzhiyun
1128*4882a593Smuzhiyun } else if (dramtype == LPDDR3) {
1129*4882a593Smuzhiyun if (dram_drv_ohm <= 34)
1130*4882a593Smuzhiyun mr1_mr3 |= LPDDR3_DS_34;
1131*4882a593Smuzhiyun else if (dram_drv_ohm <= 40)
1132*4882a593Smuzhiyun mr1_mr3 |= LPDDR3_DS_40;
1133*4882a593Smuzhiyun else if (dram_drv_ohm <= 48)
1134*4882a593Smuzhiyun mr1_mr3 |= LPDDR3_DS_48;
1135*4882a593Smuzhiyun else if (dram_drv_ohm <= 60)
1136*4882a593Smuzhiyun mr1_mr3 |= LPDDR3_DS_60;
1137*4882a593Smuzhiyun else if (dram_drv_ohm <= 80)
1138*4882a593Smuzhiyun mr1_mr3 |= LPDDR3_DS_80;
1139*4882a593Smuzhiyun
1140*4882a593Smuzhiyun if (dram_odt_ohm == 0)
1141*4882a593Smuzhiyun lp3_odt_value = LPDDR3_ODT_DIS;
1142*4882a593Smuzhiyun else if (dram_odt_ohm <= 60)
1143*4882a593Smuzhiyun lp3_odt_value = LPDDR3_ODT_60;
1144*4882a593Smuzhiyun else if (dram_odt_ohm <= 120)
1145*4882a593Smuzhiyun lp3_odt_value = LPDDR3_ODT_120;
1146*4882a593Smuzhiyun else
1147*4882a593Smuzhiyun lp3_odt_value = LPDDR3_ODT_240;
1148*4882a593Smuzhiyun } else {/* for lpddr4 and lpddr4x */
1149*4882a593Smuzhiyun /* MR3 for lp4 PU-CAL and PDDS */
1150*4882a593Smuzhiyun mr1_mr3 &= ~(LPDDR4_PDDS_MASK | LPDDR4_PU_CAL_MASK);
1151*4882a593Smuzhiyun mr1_mr3 |= lp4_pu_cal;
1152*4882a593Smuzhiyun
1153*4882a593Smuzhiyun tmp = lp4_odt_calc(dram_drv_ohm);
1154*4882a593Smuzhiyun if (!tmp)
1155*4882a593Smuzhiyun tmp = LPDDR4_PDDS_240;
1156*4882a593Smuzhiyun mr1_mr3 |= (tmp << LPDDR4_PDDS_SHIFT);
1157*4882a593Smuzhiyun
1158*4882a593Smuzhiyun /* MR11 for lp4 ca odt, dq odt set */
1159*4882a593Smuzhiyun mr11 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1160*4882a593Smuzhiyun DDR_PCTL2_INIT6);
1161*4882a593Smuzhiyun mr11 = mr11 >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK;
1162*4882a593Smuzhiyun
1163*4882a593Smuzhiyun mr11 &= ~(LPDDR4_DQODT_MASK | LPDDR4_CAODT_MASK);
1164*4882a593Smuzhiyun
1165*4882a593Smuzhiyun tmp = lp4_odt_calc(dram_odt_ohm);
1166*4882a593Smuzhiyun mr11 |= (tmp << LPDDR4_DQODT_SHIFT);
1167*4882a593Smuzhiyun
1168*4882a593Smuzhiyun tmp = lp4_odt_calc(dram_caodt_ohm);
1169*4882a593Smuzhiyun mr11 |= (tmp << LPDDR4_CAODT_SHIFT);
1170*4882a593Smuzhiyun sw_set_req(dram);
1171*4882a593Smuzhiyun clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1172*4882a593Smuzhiyun DDR_PCTL2_INIT6,
1173*4882a593Smuzhiyun PCTL2_MR_MASK << PCTL2_LPDDR4_MR11_SHIFT,
1174*4882a593Smuzhiyun mr11 << PCTL2_LPDDR4_MR11_SHIFT);
1175*4882a593Smuzhiyun sw_set_ack(dram);
1176*4882a593Smuzhiyun
1177*4882a593Smuzhiyun /* MR22 for soc odt/odt-ck/odt-cs/odt-ca */
1178*4882a593Smuzhiyun mr22 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1179*4882a593Smuzhiyun DDR_PCTL2_INIT7);
1180*4882a593Smuzhiyun mr22 = mr22 >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK;
1181*4882a593Smuzhiyun mr22 &= ~LPDDR4_SOC_ODT_MASK;
1182*4882a593Smuzhiyun
1183*4882a593Smuzhiyun tmp = lp4_odt_calc(phy_odt_ohm);
1184*4882a593Smuzhiyun mr22 |= tmp;
1185*4882a593Smuzhiyun mr22 = mr22 |
1186*4882a593Smuzhiyun (LP4_ODTE_CK_EN(lp4_info->cs_drv_ca_odt_info) <<
1187*4882a593Smuzhiyun LPDDR4_ODTE_CK_SHIFT) |
1188*4882a593Smuzhiyun (LP4_ODTE_CS_EN(lp4_info->cs_drv_ca_odt_info) <<
1189*4882a593Smuzhiyun LPDDR4_ODTE_CS_SHIFT) |
1190*4882a593Smuzhiyun (LP4_ODTD_CA_EN(lp4_info->cs_drv_ca_odt_info) <<
1191*4882a593Smuzhiyun LPDDR4_ODTD_CA_SHIFT);
1192*4882a593Smuzhiyun
1193*4882a593Smuzhiyun sw_set_req(dram);
1194*4882a593Smuzhiyun clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1195*4882a593Smuzhiyun DDR_PCTL2_INIT7,
1196*4882a593Smuzhiyun PCTL2_MR_MASK << PCTL2_LPDDR4_MR22_SHIFT,
1197*4882a593Smuzhiyun mr22 << PCTL2_LPDDR4_MR22_SHIFT);
1198*4882a593Smuzhiyun sw_set_ack(dram);
1199*4882a593Smuzhiyun }
1200*4882a593Smuzhiyun
1201*4882a593Smuzhiyun if (dramtype == DDR4 || dramtype == DDR3) {
1202*4882a593Smuzhiyun sw_set_req(dram);
1203*4882a593Smuzhiyun clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1204*4882a593Smuzhiyun DDR_PCTL2_INIT3,
1205*4882a593Smuzhiyun PCTL2_MR_MASK << PCTL2_DDR34_MR1_SHIFT,
1206*4882a593Smuzhiyun mr1_mr3 << PCTL2_DDR34_MR1_SHIFT);
1207*4882a593Smuzhiyun sw_set_ack(dram);
1208*4882a593Smuzhiyun } else {
1209*4882a593Smuzhiyun sw_set_req(dram);
1210*4882a593Smuzhiyun clrsetbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
1211*4882a593Smuzhiyun DDR_PCTL2_INIT4,
1212*4882a593Smuzhiyun PCTL2_MR_MASK << PCTL2_LPDDR234_MR3_SHIFT,
1213*4882a593Smuzhiyun mr1_mr3 << PCTL2_LPDDR234_MR3_SHIFT);
1214*4882a593Smuzhiyun sw_set_ack(dram);
1215*4882a593Smuzhiyun }
1216*4882a593Smuzhiyun }
1217*4882a593Smuzhiyun
sdram_cmd_dq_path_remap(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)1218*4882a593Smuzhiyun static int sdram_cmd_dq_path_remap(struct dram_info *dram,
1219*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
1220*4882a593Smuzhiyun {
1221*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1222*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
1223*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
1224*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
1225*4882a593Smuzhiyun struct dq_map_info *map_info;
1226*4882a593Smuzhiyun
1227*4882a593Smuzhiyun map_info = (struct dq_map_info *)((void *)common_info +
1228*4882a593Smuzhiyun index->dq_map_index.offset * 4);
1229*4882a593Smuzhiyun
1230*4882a593Smuzhiyun if (dramtype == LPDDR4X)
1231*4882a593Smuzhiyun dramtype = LPDDR4;
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun if (dramtype <= LPDDR4)
1234*4882a593Smuzhiyun writel((map_info->byte_map[dramtype / 4] >>
1235*4882a593Smuzhiyun ((dramtype % 4) * 8)) & 0xff,
1236*4882a593Smuzhiyun PHY_REG(phy_base, 0x4f));
1237*4882a593Smuzhiyun
1238*4882a593Smuzhiyun return 0;
1239*4882a593Smuzhiyun }
1240*4882a593Smuzhiyun
phy_cfg(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)1241*4882a593Smuzhiyun static void phy_cfg(struct dram_info *dram,
1242*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
1243*4882a593Smuzhiyun {
1244*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
1245*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1246*4882a593Smuzhiyun u32 i, dq_map, tmp;
1247*4882a593Smuzhiyun u32 byte1 = 0, byte0 = 0;
1248*4882a593Smuzhiyun
1249*4882a593Smuzhiyun sdram_cmd_dq_path_remap(dram, sdram_params);
1250*4882a593Smuzhiyun
1251*4882a593Smuzhiyun phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 0);
1252*4882a593Smuzhiyun for (i = 0; sdram_params->phy_regs.phy[i][0] != 0xFFFFFFFF; i++) {
1253*4882a593Smuzhiyun writel(sdram_params->phy_regs.phy[i][1],
1254*4882a593Smuzhiyun phy_base + sdram_params->phy_regs.phy[i][0]);
1255*4882a593Smuzhiyun }
1256*4882a593Smuzhiyun
1257*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x62), BIT(5));
1258*4882a593Smuzhiyun dq_map = readl(PHY_REG(phy_base, 0x4f));
1259*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1260*4882a593Smuzhiyun if (((dq_map >> (i * 2)) & 0x3) == 0) {
1261*4882a593Smuzhiyun byte0 = i;
1262*4882a593Smuzhiyun break;
1263*4882a593Smuzhiyun }
1264*4882a593Smuzhiyun }
1265*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1266*4882a593Smuzhiyun if (((dq_map >> (i * 2)) & 0x3) == 1) {
1267*4882a593Smuzhiyun byte1 = i;
1268*4882a593Smuzhiyun break;
1269*4882a593Smuzhiyun }
1270*4882a593Smuzhiyun }
1271*4882a593Smuzhiyun
1272*4882a593Smuzhiyun tmp = readl(PHY_REG(phy_base, 0xf)) & (~PHY_DQ_WIDTH_MASK);
1273*4882a593Smuzhiyun if (cap_info->bw == 2)
1274*4882a593Smuzhiyun tmp |= 0xf;
1275*4882a593Smuzhiyun else if (cap_info->bw == 1)
1276*4882a593Smuzhiyun tmp |= ((1 << byte0) | (1 << byte1));
1277*4882a593Smuzhiyun else
1278*4882a593Smuzhiyun tmp |= (1 << byte0);
1279*4882a593Smuzhiyun
1280*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, 0xf));
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun /* lpddr4 odt control by phy, enable cs0 odt */
1283*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR4 ||
1284*4882a593Smuzhiyun sdram_params->base.dramtype == LPDDR4X)
1285*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x20), 0x7 << 4,
1286*4882a593Smuzhiyun (1 << 6) | (1 << 4));
1287*4882a593Smuzhiyun /* for ca training ca vref choose range1 */
1288*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x1e), BIT(6));
1289*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x1f), BIT(6));
1290*4882a593Smuzhiyun /* for wr training PHY_0x7c[5], choose range0 */
1291*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x7c), BIT(5));
1292*4882a593Smuzhiyun }
1293*4882a593Smuzhiyun
update_refresh_reg(struct dram_info * dram)1294*4882a593Smuzhiyun static int update_refresh_reg(struct dram_info *dram)
1295*4882a593Smuzhiyun {
1296*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1297*4882a593Smuzhiyun u32 ret;
1298*4882a593Smuzhiyun
1299*4882a593Smuzhiyun ret = readl(pctl_base + DDR_PCTL2_RFSHCTL3) ^ (1 << 1);
1300*4882a593Smuzhiyun writel(ret, pctl_base + DDR_PCTL2_RFSHCTL3);
1301*4882a593Smuzhiyun
1302*4882a593Smuzhiyun return 0;
1303*4882a593Smuzhiyun }
1304*4882a593Smuzhiyun
1305*4882a593Smuzhiyun /*
1306*4882a593Smuzhiyun * rank = 1: cs0
1307*4882a593Smuzhiyun * rank = 2: cs1
1308*4882a593Smuzhiyun */
read_mr(struct dram_info * dram,u32 rank,u32 mr_num,u32 dramtype)1309*4882a593Smuzhiyun u32 read_mr(struct dram_info *dram, u32 rank, u32 mr_num, u32 dramtype)
1310*4882a593Smuzhiyun {
1311*4882a593Smuzhiyun u32 ret;
1312*4882a593Smuzhiyun u32 i, temp;
1313*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1314*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
1315*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
1316*4882a593Smuzhiyun struct dq_map_info *map_info;
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun map_info = (struct dq_map_info *)((void *)common_info +
1319*4882a593Smuzhiyun index->dq_map_index.offset * 4);
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun pctl_read_mr(pctl_base, rank, mr_num);
1322*4882a593Smuzhiyun
1323*4882a593Smuzhiyun if (dramtype == LPDDR3) {
1324*4882a593Smuzhiyun temp = (readl(&dram->ddrgrf->ddr_grf_status[0]) & 0xff);
1325*4882a593Smuzhiyun ret = 0;
1326*4882a593Smuzhiyun for (i = 0; i < 8; i++)
1327*4882a593Smuzhiyun ret |= ((temp >> i) & 0x1) << ((map_info->lp3_dq0_7_map >> (i * 4)) & 0xf);
1328*4882a593Smuzhiyun } else {
1329*4882a593Smuzhiyun ret = readl(&dram->ddrgrf->ddr_grf_status[1]) & 0xff;
1330*4882a593Smuzhiyun }
1331*4882a593Smuzhiyun
1332*4882a593Smuzhiyun return ret;
1333*4882a593Smuzhiyun }
1334*4882a593Smuzhiyun
1335*4882a593Smuzhiyun /* before call this function autorefresh should be disabled */
send_a_refresh(struct dram_info * dram)1336*4882a593Smuzhiyun void send_a_refresh(struct dram_info *dram)
1337*4882a593Smuzhiyun {
1338*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1339*4882a593Smuzhiyun
1340*4882a593Smuzhiyun while (readl(pctl_base + DDR_PCTL2_DBGSTAT) & 0x3)
1341*4882a593Smuzhiyun continue;
1342*4882a593Smuzhiyun writel(0x3, pctl_base + DDR_PCTL2_DBGCMD);
1343*4882a593Smuzhiyun }
1344*4882a593Smuzhiyun
enter_sr(struct dram_info * dram,u32 en)1345*4882a593Smuzhiyun static void enter_sr(struct dram_info *dram, u32 en)
1346*4882a593Smuzhiyun {
1347*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1348*4882a593Smuzhiyun
1349*4882a593Smuzhiyun if (en) {
1350*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
1351*4882a593Smuzhiyun while (1) {
1352*4882a593Smuzhiyun if (((readl(pctl_base + DDR_PCTL2_STAT) &
1353*4882a593Smuzhiyun PCTL2_SELFREF_TYPE_MASK) ==
1354*4882a593Smuzhiyun PCTL2_SELFREF_TYPE_SR_NOT_AUTO) &&
1355*4882a593Smuzhiyun ((readl(pctl_base + DDR_PCTL2_STAT) &
1356*4882a593Smuzhiyun PCTL2_OPERATING_MODE_MASK) ==
1357*4882a593Smuzhiyun PCTL2_OPERATING_MODE_SR))
1358*4882a593Smuzhiyun break;
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun } else {
1361*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, PCTL2_SELFREF_SW);
1362*4882a593Smuzhiyun while ((readl(pctl_base + DDR_PCTL2_STAT) &
1363*4882a593Smuzhiyun PCTL2_OPERATING_MODE_MASK) == PCTL2_OPERATING_MODE_SR)
1364*4882a593Smuzhiyun continue;
1365*4882a593Smuzhiyun }
1366*4882a593Smuzhiyun }
1367*4882a593Smuzhiyun
record_dq_prebit(struct dram_info * dram)1368*4882a593Smuzhiyun void record_dq_prebit(struct dram_info *dram)
1369*4882a593Smuzhiyun {
1370*4882a593Smuzhiyun u32 group, i, tmp;
1371*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1372*4882a593Smuzhiyun
1373*4882a593Smuzhiyun for (group = 0; group < 4; group++) {
1374*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(dq_sel); i++) {
1375*4882a593Smuzhiyun /* l_loop_invdelaysel */
1376*4882a593Smuzhiyun writel(dq_sel[i][0], PHY_REG(phy_base,
1377*4882a593Smuzhiyun grp_addr[group] + 0x2c));
1378*4882a593Smuzhiyun tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2e));
1379*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base,
1380*4882a593Smuzhiyun grp_addr[group] + dq_sel[i][1]));
1381*4882a593Smuzhiyun
1382*4882a593Smuzhiyun /* r_loop_invdelaysel */
1383*4882a593Smuzhiyun writel(dq_sel[i][0], PHY_REG(phy_base,
1384*4882a593Smuzhiyun grp_addr[group] + 0x2d));
1385*4882a593Smuzhiyun tmp = readl(PHY_REG(phy_base, grp_addr[group] + 0x2f));
1386*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base,
1387*4882a593Smuzhiyun grp_addr[group] + dq_sel[i][2]));
1388*4882a593Smuzhiyun }
1389*4882a593Smuzhiyun }
1390*4882a593Smuzhiyun }
1391*4882a593Smuzhiyun
update_dq_rx_prebit(struct dram_info * dram)1392*4882a593Smuzhiyun static void update_dq_rx_prebit(struct dram_info *dram)
1393*4882a593Smuzhiyun {
1394*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1395*4882a593Smuzhiyun
1396*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x70), BIT(1) | BIT(6) | BIT(4),
1397*4882a593Smuzhiyun BIT(4));
1398*4882a593Smuzhiyun udelay(1);
1399*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x70), BIT(4));
1400*4882a593Smuzhiyun }
1401*4882a593Smuzhiyun
update_dq_tx_prebit(struct dram_info * dram)1402*4882a593Smuzhiyun static void update_dq_tx_prebit(struct dram_info *dram)
1403*4882a593Smuzhiyun {
1404*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1405*4882a593Smuzhiyun
1406*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1407*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x2), BIT(3));
1408*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1409*4882a593Smuzhiyun udelay(1);
1410*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0xc), BIT(6));
1411*4882a593Smuzhiyun }
1412*4882a593Smuzhiyun
update_ca_prebit(struct dram_info * dram)1413*4882a593Smuzhiyun static void update_ca_prebit(struct dram_info *dram)
1414*4882a593Smuzhiyun {
1415*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1416*4882a593Smuzhiyun
1417*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x25), BIT(2));
1418*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1419*4882a593Smuzhiyun udelay(1);
1420*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x22), BIT(6));
1421*4882a593Smuzhiyun }
1422*4882a593Smuzhiyun
1423*4882a593Smuzhiyun /*
1424*4882a593Smuzhiyun * dir: 0: de-skew = delta_*
1425*4882a593Smuzhiyun * 1: de-skew = reg val - delta_*
1426*4882a593Smuzhiyun * delta_dir: value for differential signal: clk/
1427*4882a593Smuzhiyun * delta_sig: value for single signal: ca/cmd
1428*4882a593Smuzhiyun */
modify_ca_deskew(struct dram_info * dram,u32 dir,int delta_dif,int delta_sig,u32 cs,u32 dramtype)1429*4882a593Smuzhiyun static void modify_ca_deskew(struct dram_info *dram, u32 dir, int delta_dif,
1430*4882a593Smuzhiyun int delta_sig, u32 cs, u32 dramtype)
1431*4882a593Smuzhiyun {
1432*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1433*4882a593Smuzhiyun u32 i, cs_en, tmp;
1434*4882a593Smuzhiyun u32 dfi_lp_stat = 0;
1435*4882a593Smuzhiyun
1436*4882a593Smuzhiyun if (cs == 0)
1437*4882a593Smuzhiyun cs_en = 1;
1438*4882a593Smuzhiyun else if (cs == 2)
1439*4882a593Smuzhiyun cs_en = 2;
1440*4882a593Smuzhiyun else
1441*4882a593Smuzhiyun cs_en = 3;
1442*4882a593Smuzhiyun
1443*4882a593Smuzhiyun if ((dramtype == LPDDR4 || dramtype == LPDDR4X) &&
1444*4882a593Smuzhiyun ((readl(PHY_REG(phy_base, 0x60)) & BIT(5)) == 0)) {
1445*4882a593Smuzhiyun dfi_lp_stat = 1;
1446*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
1447*4882a593Smuzhiyun }
1448*4882a593Smuzhiyun enter_sr(dram, 1);
1449*4882a593Smuzhiyun
1450*4882a593Smuzhiyun for (i = 0; i < 0x20; i++) {
1451*4882a593Smuzhiyun if (dir == DESKEW_MDF_ABS_VAL)
1452*4882a593Smuzhiyun tmp = delta_sig;
1453*4882a593Smuzhiyun else
1454*4882a593Smuzhiyun tmp = readl(PHY_REG(phy_base, 0x150 + i)) +
1455*4882a593Smuzhiyun delta_sig;
1456*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, 0x150 + i));
1457*4882a593Smuzhiyun }
1458*4882a593Smuzhiyun
1459*4882a593Smuzhiyun if (dir == DESKEW_MDF_ABS_VAL)
1460*4882a593Smuzhiyun tmp = delta_dif;
1461*4882a593Smuzhiyun else
1462*4882a593Smuzhiyun tmp = readl(PHY_REG(phy_base, 0x150 + 0x17)) -
1463*4882a593Smuzhiyun delta_sig + delta_dif;
1464*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, 0x150 + 0x17));
1465*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, 0x150 + 0x18));
1466*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
1467*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, 0x150 + 0x4));
1468*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, 0x150 + 0xa));
1469*4882a593Smuzhiyun
1470*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x10), cs_en << 6);
1471*4882a593Smuzhiyun update_ca_prebit(dram);
1472*4882a593Smuzhiyun }
1473*4882a593Smuzhiyun enter_sr(dram, 0);
1474*4882a593Smuzhiyun
1475*4882a593Smuzhiyun if (dfi_lp_stat)
1476*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x60), BIT(5));
1477*4882a593Smuzhiyun
1478*4882a593Smuzhiyun }
1479*4882a593Smuzhiyun
get_min_value(struct dram_info * dram,u32 signal,u32 rank)1480*4882a593Smuzhiyun static u32 get_min_value(struct dram_info *dram, u32 signal, u32 rank)
1481*4882a593Smuzhiyun {
1482*4882a593Smuzhiyun u32 i, j, offset = 0;
1483*4882a593Smuzhiyun u32 min = 0x3f;
1484*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1485*4882a593Smuzhiyun u32 byte_en;
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun if (signal == SKEW_TX_SIGNAL)
1488*4882a593Smuzhiyun offset = 8;
1489*4882a593Smuzhiyun
1490*4882a593Smuzhiyun if (signal == SKEW_CA_SIGNAL) {
1491*4882a593Smuzhiyun for (i = 0; i < 0x20; i++)
1492*4882a593Smuzhiyun min = MIN(min, readl(PHY_REG(phy_base, 0x150 + i)));
1493*4882a593Smuzhiyun } else {
1494*4882a593Smuzhiyun byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1495*4882a593Smuzhiyun for (j = offset; j < offset + rank * 4; j++) {
1496*4882a593Smuzhiyun if (!((byte_en >> (j % 4)) & 1))
1497*4882a593Smuzhiyun continue;
1498*4882a593Smuzhiyun for (i = 0; i < 11; i++)
1499*4882a593Smuzhiyun min = MIN(min,
1500*4882a593Smuzhiyun readl(PHY_REG(phy_base,
1501*4882a593Smuzhiyun dqs_dq_skew_adr[j] +
1502*4882a593Smuzhiyun i)));
1503*4882a593Smuzhiyun }
1504*4882a593Smuzhiyun }
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun return min;
1507*4882a593Smuzhiyun }
1508*4882a593Smuzhiyun
low_power_update(struct dram_info * dram,u32 en)1509*4882a593Smuzhiyun static u32 low_power_update(struct dram_info *dram, u32 en)
1510*4882a593Smuzhiyun {
1511*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1512*4882a593Smuzhiyun u32 lp_stat = 0;
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun if (en) {
1515*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, en & 0xf);
1516*4882a593Smuzhiyun } else {
1517*4882a593Smuzhiyun lp_stat = readl(pctl_base + DDR_PCTL2_PWRCTL) & 0xf;
1518*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 0xf);
1519*4882a593Smuzhiyun }
1520*4882a593Smuzhiyun
1521*4882a593Smuzhiyun return lp_stat;
1522*4882a593Smuzhiyun }
1523*4882a593Smuzhiyun
1524*4882a593Smuzhiyun /*
1525*4882a593Smuzhiyun * signal:
1526*4882a593Smuzhiyun * dir: 0: de-skew = delta_*
1527*4882a593Smuzhiyun * 1: de-skew = reg val - delta_*
1528*4882a593Smuzhiyun * delta_dir: value for differential signal: dqs
1529*4882a593Smuzhiyun * delta_sig: value for single signal: dq/dm
1530*4882a593Smuzhiyun */
modify_dq_deskew(struct dram_info * dram,u32 signal,u32 dir,int delta_dif,int delta_sig,u32 rank)1531*4882a593Smuzhiyun static void modify_dq_deskew(struct dram_info *dram, u32 signal, u32 dir,
1532*4882a593Smuzhiyun int delta_dif, int delta_sig, u32 rank)
1533*4882a593Smuzhiyun {
1534*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1535*4882a593Smuzhiyun u32 i, j, tmp, offset;
1536*4882a593Smuzhiyun u32 byte_en;
1537*4882a593Smuzhiyun
1538*4882a593Smuzhiyun byte_en = readl(PHY_REG(phy_base, 0xf)) & 0xf;
1539*4882a593Smuzhiyun
1540*4882a593Smuzhiyun if (signal == SKEW_RX_SIGNAL)
1541*4882a593Smuzhiyun offset = 0;
1542*4882a593Smuzhiyun else
1543*4882a593Smuzhiyun offset = 8;
1544*4882a593Smuzhiyun
1545*4882a593Smuzhiyun for (j = offset; j < (offset + rank * 4); j++) {
1546*4882a593Smuzhiyun if (!((byte_en >> (j % 4)) & 1))
1547*4882a593Smuzhiyun continue;
1548*4882a593Smuzhiyun for (i = 0; i < 0x9; i++) {
1549*4882a593Smuzhiyun if (dir == DESKEW_MDF_ABS_VAL)
1550*4882a593Smuzhiyun tmp = delta_sig;
1551*4882a593Smuzhiyun else
1552*4882a593Smuzhiyun tmp = delta_sig + readl(PHY_REG(phy_base,
1553*4882a593Smuzhiyun dqs_dq_skew_adr[j] +
1554*4882a593Smuzhiyun i));
1555*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + i));
1556*4882a593Smuzhiyun }
1557*4882a593Smuzhiyun if (dir == DESKEW_MDF_ABS_VAL)
1558*4882a593Smuzhiyun tmp = delta_dif;
1559*4882a593Smuzhiyun else
1560*4882a593Smuzhiyun tmp = delta_dif + readl(PHY_REG(phy_base,
1561*4882a593Smuzhiyun dqs_dq_skew_adr[j] + 9));
1562*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 9));
1563*4882a593Smuzhiyun writel(tmp, PHY_REG(phy_base, dqs_dq_skew_adr[j] + 0xa));
1564*4882a593Smuzhiyun }
1565*4882a593Smuzhiyun if (signal == SKEW_RX_SIGNAL)
1566*4882a593Smuzhiyun update_dq_rx_prebit(dram);
1567*4882a593Smuzhiyun else
1568*4882a593Smuzhiyun update_dq_tx_prebit(dram);
1569*4882a593Smuzhiyun }
1570*4882a593Smuzhiyun
data_training_rg(struct dram_info * dram,u32 cs,u32 dramtype)1571*4882a593Smuzhiyun static int data_training_rg(struct dram_info *dram, u32 cs, u32 dramtype)
1572*4882a593Smuzhiyun {
1573*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1574*4882a593Smuzhiyun u32 ret;
1575*4882a593Smuzhiyun u32 dis_auto_zq = 0;
1576*4882a593Smuzhiyun u32 odt_val_up, odt_val_dn;
1577*4882a593Smuzhiyun u32 i, j;
1578*4882a593Smuzhiyun
1579*4882a593Smuzhiyun odt_val_dn = readl(PHY_REG(phy_base, 0x110));
1580*4882a593Smuzhiyun odt_val_up = readl(PHY_REG(phy_base, 0x111));
1581*4882a593Smuzhiyun
1582*4882a593Smuzhiyun if (dramtype != LPDDR4 || dramtype != LPDDR4X) {
1583*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1584*4882a593Smuzhiyun j = 0x110 + i * 0x10;
1585*4882a593Smuzhiyun writel(PHY_DDR4_LPDDR3_RTT_294ohm,
1586*4882a593Smuzhiyun PHY_REG(phy_base, j));
1587*4882a593Smuzhiyun writel(PHY_DDR4_LPDDR3_RTT_DISABLE,
1588*4882a593Smuzhiyun PHY_REG(phy_base, j + 0x1));
1589*4882a593Smuzhiyun }
1590*4882a593Smuzhiyun }
1591*4882a593Smuzhiyun dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1592*4882a593Smuzhiyun /* use normal read mode for data training */
1593*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1594*4882a593Smuzhiyun
1595*4882a593Smuzhiyun if (dramtype == DDR4)
1596*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0xc), BIT(1));
1597*4882a593Smuzhiyun
1598*4882a593Smuzhiyun /* choose training cs */
1599*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs));
1600*4882a593Smuzhiyun /* enable gate training */
1601*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 1);
1602*4882a593Smuzhiyun udelay(50);
1603*4882a593Smuzhiyun ret = readl(PHY_REG(phy_base, 0x91));
1604*4882a593Smuzhiyun /* disable gate training */
1605*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), 0x33, (0x20 >> cs) | 0);
1606*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 2), 0x30);
1607*4882a593Smuzhiyun pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1608*4882a593Smuzhiyun
1609*4882a593Smuzhiyun ret = (ret & 0x2f) ^ (readl(PHY_REG(phy_base, 0xf)) & 0xf);
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun if (dramtype != LPDDR4 || dramtype != LPDDR4X) {
1612*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1613*4882a593Smuzhiyun j = 0x110 + i * 0x10;
1614*4882a593Smuzhiyun writel(odt_val_dn, PHY_REG(phy_base, j));
1615*4882a593Smuzhiyun writel(odt_val_up, PHY_REG(phy_base, j + 0x1));
1616*4882a593Smuzhiyun }
1617*4882a593Smuzhiyun }
1618*4882a593Smuzhiyun return ret;
1619*4882a593Smuzhiyun }
1620*4882a593Smuzhiyun
data_training_wl(struct dram_info * dram,u32 cs,u32 dramtype,u32 rank)1621*4882a593Smuzhiyun static int data_training_wl(struct dram_info *dram, u32 cs, u32 dramtype,
1622*4882a593Smuzhiyun u32 rank)
1623*4882a593Smuzhiyun {
1624*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1625*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1626*4882a593Smuzhiyun u32 dis_auto_zq = 0;
1627*4882a593Smuzhiyun u32 tmp;
1628*4882a593Smuzhiyun u32 cur_fsp;
1629*4882a593Smuzhiyun u32 timeout_us = 1000;
1630*4882a593Smuzhiyun
1631*4882a593Smuzhiyun dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1632*4882a593Smuzhiyun
1633*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1634*4882a593Smuzhiyun
1635*4882a593Smuzhiyun cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1636*4882a593Smuzhiyun tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_INIT3) &
1637*4882a593Smuzhiyun 0xffff;
1638*4882a593Smuzhiyun writel(tmp & 0xff, PHY_REG(phy_base, 0x3));
1639*4882a593Smuzhiyun
1640*4882a593Smuzhiyun /* disable another cs's output */
1641*4882a593Smuzhiyun if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1642*4882a593Smuzhiyun pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp | (1 << 12),
1643*4882a593Smuzhiyun dramtype);
1644*4882a593Smuzhiyun if (dramtype == DDR3 || dramtype == DDR4)
1645*4882a593Smuzhiyun writel(0x40 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1646*4882a593Smuzhiyun else
1647*4882a593Smuzhiyun writel(0x80 | ((tmp >> 8) & 0x3f), PHY_REG(phy_base, 0x4));
1648*4882a593Smuzhiyun
1649*4882a593Smuzhiyun /* choose cs */
1650*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1651*4882a593Smuzhiyun ((0x2 >> cs) << 6) | (0 << 2));
1652*4882a593Smuzhiyun /* enable write leveling */
1653*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1654*4882a593Smuzhiyun ((0x2 >> cs) << 6) | (1 << 2));
1655*4882a593Smuzhiyun
1656*4882a593Smuzhiyun while (1) {
1657*4882a593Smuzhiyun if ((readl(PHY_REG(phy_base, 0x92)) & 0xf) ==
1658*4882a593Smuzhiyun (readl(PHY_REG(phy_base, 0xf)) & 0xf))
1659*4882a593Smuzhiyun break;
1660*4882a593Smuzhiyun
1661*4882a593Smuzhiyun udelay(1);
1662*4882a593Smuzhiyun if (timeout_us-- == 0) {
1663*4882a593Smuzhiyun printascii("error: write leveling timeout\n");
1664*4882a593Smuzhiyun while (1)
1665*4882a593Smuzhiyun ;
1666*4882a593Smuzhiyun }
1667*4882a593Smuzhiyun }
1668*4882a593Smuzhiyun
1669*4882a593Smuzhiyun /* disable write leveling */
1670*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), (0x3 << 6) | (0x3 << 2),
1671*4882a593Smuzhiyun ((0x2 >> cs) << 6) | (0 << 2));
1672*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 2), 0x3 << 6, 0 << 6);
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun /* enable another cs's output */
1675*4882a593Smuzhiyun if ((dramtype == DDR3 || dramtype == DDR4) && rank == 2)
1676*4882a593Smuzhiyun pctl_write_mr(dram->pctl, (cs + 1) & 1, 1, tmp & ~(1 << 12),
1677*4882a593Smuzhiyun dramtype);
1678*4882a593Smuzhiyun
1679*4882a593Smuzhiyun pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1680*4882a593Smuzhiyun
1681*4882a593Smuzhiyun return 0;
1682*4882a593Smuzhiyun }
1683*4882a593Smuzhiyun
1684*4882a593Smuzhiyun char pattern[32] = {
1685*4882a593Smuzhiyun 0xaa, 0x55, 0xaa, 0x55, 0x55, 0xaa, 0x55, 0xaa,
1686*4882a593Smuzhiyun 0x55, 0xaa, 0x55, 0xaa, 0xaa, 0x55, 0xaa, 0x55,
1687*4882a593Smuzhiyun 0x55, 0x55, 0xaa, 0xaa, 0xaa, 0xaa, 0x55, 0x55,
1688*4882a593Smuzhiyun 0xaa, 0xaa, 0x55, 0x55, 0x55, 0x55, 0xaa, 0xaa
1689*4882a593Smuzhiyun };
1690*4882a593Smuzhiyun
data_training_rd(struct dram_info * dram,u32 cs,u32 dramtype,u32 mhz)1691*4882a593Smuzhiyun static int data_training_rd(struct dram_info *dram, u32 cs, u32 dramtype,
1692*4882a593Smuzhiyun u32 mhz)
1693*4882a593Smuzhiyun {
1694*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1695*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1696*4882a593Smuzhiyun u32 trefi_1x, trfc_1x;
1697*4882a593Smuzhiyun u32 dis_auto_zq = 0;
1698*4882a593Smuzhiyun u32 timeout_us = 1000;
1699*4882a593Smuzhiyun u32 dqs_default;
1700*4882a593Smuzhiyun u32 cur_fsp;
1701*4882a593Smuzhiyun u32 vref_inner;
1702*4882a593Smuzhiyun u32 i;
1703*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
1704*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
1705*4882a593Smuzhiyun struct dq_map_info *map_info;
1706*4882a593Smuzhiyun
1707*4882a593Smuzhiyun vref_inner = readl(PHY_REG(phy_base, 0x128)) & 0xff;
1708*4882a593Smuzhiyun if (dramtype == DDR3 && vref_inner == 0x80) {
1709*4882a593Smuzhiyun for (i = 0; i < 4; i++)
1710*4882a593Smuzhiyun writel(vref_inner - 0xa,
1711*4882a593Smuzhiyun PHY_REG(phy_base, 0x118 + i * 0x10));
1712*4882a593Smuzhiyun
1713*4882a593Smuzhiyun /* reg_rx_vref_value_update */
1714*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1715*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1716*4882a593Smuzhiyun }
1717*4882a593Smuzhiyun
1718*4882a593Smuzhiyun map_info = (struct dq_map_info *)((void *)common_info +
1719*4882a593Smuzhiyun index->dq_map_index.offset * 4);
1720*4882a593Smuzhiyun /* only 1cs a time, 0:cs0 1 cs1 */
1721*4882a593Smuzhiyun if (cs > 1)
1722*4882a593Smuzhiyun return -1;
1723*4882a593Smuzhiyun
1724*4882a593Smuzhiyun dqs_default = 0xf;
1725*4882a593Smuzhiyun dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1726*4882a593Smuzhiyun
1727*4882a593Smuzhiyun cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1728*4882a593Smuzhiyun /* config refresh timing */
1729*4882a593Smuzhiyun trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1730*4882a593Smuzhiyun DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1731*4882a593Smuzhiyun trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1732*4882a593Smuzhiyun DDR_PCTL2_RFSHTMG) & 0x3ff;
1733*4882a593Smuzhiyun /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1734*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1735*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1736*4882a593Smuzhiyun /* reg_phy_trfc */
1737*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1738*4882a593Smuzhiyun /* reg_max_refi_cnt */
1739*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1740*4882a593Smuzhiyun
1741*4882a593Smuzhiyun /* choose training cs */
1742*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x71), 0x3 << 6, (0x2 >> cs) << 6);
1743*4882a593Smuzhiyun
1744*4882a593Smuzhiyun /* set dq map for ddr4 */
1745*4882a593Smuzhiyun if (dramtype == DDR4) {
1746*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x70), BIT(7));
1747*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
1748*4882a593Smuzhiyun writel((map_info->ddr4_dq_map[cs * 2] >>
1749*4882a593Smuzhiyun ((i % 4) * 8)) & 0xff,
1750*4882a593Smuzhiyun PHY_REG(phy_base, 0x238 + i));
1751*4882a593Smuzhiyun writel((map_info->ddr4_dq_map[cs * 2 + 1] >>
1752*4882a593Smuzhiyun ((i % 4) * 8)) & 0xff,
1753*4882a593Smuzhiyun PHY_REG(phy_base, 0x2b8 + i));
1754*4882a593Smuzhiyun }
1755*4882a593Smuzhiyun }
1756*4882a593Smuzhiyun
1757*4882a593Smuzhiyun /* cha_l reg_l_rd_train_dqs_default[5:0] */
1758*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x230), 0x3f, dqs_default);
1759*4882a593Smuzhiyun /* cha_h reg_h_rd_train_dqs_default[5:0] */
1760*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x234), 0x3f, dqs_default);
1761*4882a593Smuzhiyun /* chb_l reg_l_rd_train_dqs_default[5:0] */
1762*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x2b0), 0x3f, dqs_default);
1763*4882a593Smuzhiyun /* chb_h reg_h_rd_train_dqs_default[5:0] */
1764*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x2b4), 0x3f, dqs_default);
1765*4882a593Smuzhiyun
1766*4882a593Smuzhiyun /* Choose the read train auto mode */
1767*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x1);
1768*4882a593Smuzhiyun /* Enable the auto train of the read train */
1769*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x70), 0x3, 0x3);
1770*4882a593Smuzhiyun
1771*4882a593Smuzhiyun /* Wait the train done. */
1772*4882a593Smuzhiyun while (1) {
1773*4882a593Smuzhiyun if ((readl(PHY_REG(phy_base, 0x93)) >> 7) & 0x1)
1774*4882a593Smuzhiyun break;
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun udelay(1);
1777*4882a593Smuzhiyun if (timeout_us-- == 0) {
1778*4882a593Smuzhiyun printascii("error: read training timeout\n");
1779*4882a593Smuzhiyun return -1;
1780*4882a593Smuzhiyun }
1781*4882a593Smuzhiyun }
1782*4882a593Smuzhiyun
1783*4882a593Smuzhiyun /* Check the read train state */
1784*4882a593Smuzhiyun if ((readl(PHY_REG(phy_base, 0x240)) & 0x3) ||
1785*4882a593Smuzhiyun (readl(PHY_REG(phy_base, 0x2c0)) & 0x3)) {
1786*4882a593Smuzhiyun printascii("error: read training error\n");
1787*4882a593Smuzhiyun return -1;
1788*4882a593Smuzhiyun }
1789*4882a593Smuzhiyun
1790*4882a593Smuzhiyun /* Exit the Read Training by setting */
1791*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x70), BIT(1));
1792*4882a593Smuzhiyun
1793*4882a593Smuzhiyun pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1794*4882a593Smuzhiyun
1795*4882a593Smuzhiyun if (dramtype == DDR3 && vref_inner == 0x80) {
1796*4882a593Smuzhiyun for (i = 0; i < 4; i++)
1797*4882a593Smuzhiyun writel(vref_inner,
1798*4882a593Smuzhiyun PHY_REG(phy_base, 0x118 + i * 0x10));
1799*4882a593Smuzhiyun
1800*4882a593Smuzhiyun /* reg_rx_vref_value_update */
1801*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1802*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
1803*4882a593Smuzhiyun }
1804*4882a593Smuzhiyun
1805*4882a593Smuzhiyun return 0;
1806*4882a593Smuzhiyun }
1807*4882a593Smuzhiyun
data_training_wr(struct dram_info * dram,u32 cs,u32 dramtype,u32 mhz,u32 dst_fsp)1808*4882a593Smuzhiyun static int data_training_wr(struct dram_info *dram, u32 cs, u32 dramtype,
1809*4882a593Smuzhiyun u32 mhz, u32 dst_fsp)
1810*4882a593Smuzhiyun {
1811*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
1812*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1813*4882a593Smuzhiyun u32 trefi_1x, trfc_1x;
1814*4882a593Smuzhiyun u32 dis_auto_zq = 0;
1815*4882a593Smuzhiyun u32 timeout_us = 1000;
1816*4882a593Smuzhiyun u32 cur_fsp;
1817*4882a593Smuzhiyun u32 mr_tmp, cl, cwl, phy_fsp, offset = 0;
1818*4882a593Smuzhiyun
1819*4882a593Smuzhiyun if (dramtype == LPDDR3 && mhz <= 400) {
1820*4882a593Smuzhiyun phy_fsp = (readl(PHY_REG(phy_base, 0xc)) >> 0x2) & 0x3;
1821*4882a593Smuzhiyun offset = (phy_fsp == 0) ? 0x5 : 0x387 + (phy_fsp - 1) * 3;
1822*4882a593Smuzhiyun cl = readl(PHY_REG(phy_base, offset));
1823*4882a593Smuzhiyun cwl = readl(PHY_REG(phy_base, offset + 2));
1824*4882a593Smuzhiyun
1825*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, 0x8);
1826*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, 0x4);
1827*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 2, 0x6, dramtype);
1828*4882a593Smuzhiyun }
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun dis_auto_zq = pctl_dis_zqcs_aref(dram->pctl);
1831*4882a593Smuzhiyun
1832*4882a593Smuzhiyun /* PHY_0x7b[7:0] reg_train_col_addr[7:0] */
1833*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x7b), 0xff, 0x0);
1834*4882a593Smuzhiyun /* PHY_0x7c[4:2] reg_train_ba_addr[2:0] */
1835*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x7 << 2, 0x0 << 2);
1836*4882a593Smuzhiyun /* PHY_0x7c[1:0] reg_train_col_addr[9:8] */
1837*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3, 0x0);
1838*4882a593Smuzhiyun /* PHY_0x7d[7:0] reg_train_row_addr[7:0] */
1839*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x7d), 0xff, 0x0);
1840*4882a593Smuzhiyun /* PHY_0x7e[7:0] reg_train_row_addr[15:8] */
1841*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x7e), 0xff, 0x0);
1842*4882a593Smuzhiyun
1843*4882a593Smuzhiyun /* PHY_0x71[3] wrtrain_check_data_value_random_gen */
1844*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x71), BIT(3));
1845*4882a593Smuzhiyun
1846*4882a593Smuzhiyun /* config refresh timing */
1847*4882a593Smuzhiyun cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
1848*4882a593Smuzhiyun trefi_1x = ((readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1849*4882a593Smuzhiyun DDR_PCTL2_RFSHTMG) >> 16) & 0xfff) * 32;
1850*4882a593Smuzhiyun trfc_1x = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1851*4882a593Smuzhiyun DDR_PCTL2_RFSHTMG) & 0x3ff;
1852*4882a593Smuzhiyun /* reg_phy_trefi[7:0] and reg_phy_trefi[13:8] */
1853*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x6e), 0xff, trefi_1x & 0xff);
1854*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x6f), 0x3f, (trefi_1x >> 8) & 0x3f);
1855*4882a593Smuzhiyun /* reg_phy_trfc */
1856*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x57), 0xff, trfc_1x);
1857*4882a593Smuzhiyun /* reg_max_refi_cnt */
1858*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x61), 0xf << 4, 0x8 << 4);
1859*4882a593Smuzhiyun
1860*4882a593Smuzhiyun /* choose training cs */
1861*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0x7c), 0x3 << 6, (0x2 >> cs) << 6);
1862*4882a593Smuzhiyun
1863*4882a593Smuzhiyun /* PHY_0x7a [4] reg_wr_train_dqs_default_bypass */
1864*4882a593Smuzhiyun /* 0: Use the write-leveling value. */
1865*4882a593Smuzhiyun /* 1: use reg0x233 0x237 0x2b3 0x2b7 */
1866*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x7a), BIT(4));
1867*4882a593Smuzhiyun
1868*4882a593Smuzhiyun /* PHY_0x7a [0] reg_dq_wr_train_auto */
1869*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x7a), 0x1);
1870*4882a593Smuzhiyun
1871*4882a593Smuzhiyun /* PHY_0x7a [1] reg_dq_wr_train_en */
1872*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1873*4882a593Smuzhiyun
1874*4882a593Smuzhiyun send_a_refresh(dram);
1875*4882a593Smuzhiyun
1876*4882a593Smuzhiyun while (1) {
1877*4882a593Smuzhiyun if ((readl(PHY_REG(phy_base, 0x92)) >> 7) & 0x1)
1878*4882a593Smuzhiyun break;
1879*4882a593Smuzhiyun
1880*4882a593Smuzhiyun udelay(1);
1881*4882a593Smuzhiyun if (timeout_us-- == 0) {
1882*4882a593Smuzhiyun printascii("error: write training timeout\n");
1883*4882a593Smuzhiyun while (1)
1884*4882a593Smuzhiyun ;
1885*4882a593Smuzhiyun }
1886*4882a593Smuzhiyun }
1887*4882a593Smuzhiyun
1888*4882a593Smuzhiyun /* Check the write train state */
1889*4882a593Smuzhiyun if ((readl(PHY_REG(phy_base, 0x90)) >> 5) & 0x7) {
1890*4882a593Smuzhiyun printascii("error: write training error\n");
1891*4882a593Smuzhiyun return -1;
1892*4882a593Smuzhiyun }
1893*4882a593Smuzhiyun
1894*4882a593Smuzhiyun /* PHY_0x7a [1] reg_dq_wr_train_en */
1895*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x7a), BIT(1));
1896*4882a593Smuzhiyun
1897*4882a593Smuzhiyun pctl_rest_zqcs_aref(dram->pctl, dis_auto_zq);
1898*4882a593Smuzhiyun
1899*4882a593Smuzhiyun /* save LPDDR4/LPDDR4X write vref to fsp_param for dfs */
1900*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
1901*4882a593Smuzhiyun fsp_param[dst_fsp].vref_dq[cs] =
1902*4882a593Smuzhiyun ((readl(PHY_REG(phy_base, 0x384)) & 0x3f) +
1903*4882a593Smuzhiyun (readl(PHY_REG(phy_base, 0x385)) & 0x3f)) / 2;
1904*4882a593Smuzhiyun /* add range info */
1905*4882a593Smuzhiyun fsp_param[dst_fsp].vref_dq[cs] |=
1906*4882a593Smuzhiyun ((readl(PHY_REG(phy_base, 0x7c)) & BIT(5)) << 1);
1907*4882a593Smuzhiyun }
1908*4882a593Smuzhiyun
1909*4882a593Smuzhiyun if (dramtype == LPDDR3 && mhz <= 400) {
1910*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, offset), 0x1f, cl);
1911*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, offset + 2), 0x1f, cwl);
1912*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
1913*4882a593Smuzhiyun DDR_PCTL2_INIT3);
1914*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
1915*4882a593Smuzhiyun dramtype);
1916*4882a593Smuzhiyun }
1917*4882a593Smuzhiyun
1918*4882a593Smuzhiyun return 0;
1919*4882a593Smuzhiyun }
1920*4882a593Smuzhiyun
data_training(struct dram_info * dram,u32 cs,struct rv1126_sdram_params * sdram_params,u32 dst_fsp,u32 training_flag)1921*4882a593Smuzhiyun static int data_training(struct dram_info *dram, u32 cs,
1922*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params, u32 dst_fsp,
1923*4882a593Smuzhiyun u32 training_flag)
1924*4882a593Smuzhiyun {
1925*4882a593Smuzhiyun u32 ret = 0;
1926*4882a593Smuzhiyun
1927*4882a593Smuzhiyun if (training_flag == FULL_TRAINING)
1928*4882a593Smuzhiyun training_flag = READ_GATE_TRAINING | WRITE_LEVELING |
1929*4882a593Smuzhiyun WRITE_TRAINING | READ_TRAINING;
1930*4882a593Smuzhiyun
1931*4882a593Smuzhiyun if ((training_flag & WRITE_LEVELING) == WRITE_LEVELING) {
1932*4882a593Smuzhiyun ret = data_training_wl(dram, cs,
1933*4882a593Smuzhiyun sdram_params->base.dramtype,
1934*4882a593Smuzhiyun sdram_params->ch.cap_info.rank);
1935*4882a593Smuzhiyun if (ret != 0)
1936*4882a593Smuzhiyun goto out;
1937*4882a593Smuzhiyun }
1938*4882a593Smuzhiyun
1939*4882a593Smuzhiyun if ((training_flag & READ_GATE_TRAINING) == READ_GATE_TRAINING) {
1940*4882a593Smuzhiyun ret = data_training_rg(dram, cs,
1941*4882a593Smuzhiyun sdram_params->base.dramtype);
1942*4882a593Smuzhiyun if (ret != 0)
1943*4882a593Smuzhiyun goto out;
1944*4882a593Smuzhiyun }
1945*4882a593Smuzhiyun
1946*4882a593Smuzhiyun if ((training_flag & READ_TRAINING) == READ_TRAINING) {
1947*4882a593Smuzhiyun ret = data_training_rd(dram, cs,
1948*4882a593Smuzhiyun sdram_params->base.dramtype,
1949*4882a593Smuzhiyun sdram_params->base.ddr_freq);
1950*4882a593Smuzhiyun if (ret != 0)
1951*4882a593Smuzhiyun goto out;
1952*4882a593Smuzhiyun }
1953*4882a593Smuzhiyun
1954*4882a593Smuzhiyun if ((training_flag & WRITE_TRAINING) == WRITE_TRAINING) {
1955*4882a593Smuzhiyun ret = data_training_wr(dram, cs,
1956*4882a593Smuzhiyun sdram_params->base.dramtype,
1957*4882a593Smuzhiyun sdram_params->base.ddr_freq, dst_fsp);
1958*4882a593Smuzhiyun if (ret != 0)
1959*4882a593Smuzhiyun goto out;
1960*4882a593Smuzhiyun }
1961*4882a593Smuzhiyun
1962*4882a593Smuzhiyun out:
1963*4882a593Smuzhiyun return ret;
1964*4882a593Smuzhiyun }
1965*4882a593Smuzhiyun
get_wrlvl_val(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)1966*4882a593Smuzhiyun static int get_wrlvl_val(struct dram_info *dram,
1967*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
1968*4882a593Smuzhiyun {
1969*4882a593Smuzhiyun int i, j, clk_skew;
1970*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
1971*4882a593Smuzhiyun u32 lp_stat;
1972*4882a593Smuzhiyun int ret;
1973*4882a593Smuzhiyun
1974*4882a593Smuzhiyun lp_stat = low_power_update(dram, 0);
1975*4882a593Smuzhiyun
1976*4882a593Smuzhiyun clk_skew = 0x1f;
1977*4882a593Smuzhiyun modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, clk_skew, 3,
1978*4882a593Smuzhiyun sdram_params->base.dramtype);
1979*4882a593Smuzhiyun
1980*4882a593Smuzhiyun ret = data_training(dram, 0, sdram_params, 0, WRITE_LEVELING);
1981*4882a593Smuzhiyun if (sdram_params->ch.cap_info.rank == 2)
1982*4882a593Smuzhiyun ret |= data_training(dram, 1, sdram_params, 0, WRITE_LEVELING);
1983*4882a593Smuzhiyun
1984*4882a593Smuzhiyun for (j = 0; j < 2; j++)
1985*4882a593Smuzhiyun for (i = 0; i < 4; i++)
1986*4882a593Smuzhiyun wrlvl_result[j][i] =
1987*4882a593Smuzhiyun (readl(PHY_REG(phy_base, wrlvl_result_offset[j][i])) & 0x3f) -
1988*4882a593Smuzhiyun clk_skew;
1989*4882a593Smuzhiyun
1990*4882a593Smuzhiyun low_power_update(dram, lp_stat);
1991*4882a593Smuzhiyun
1992*4882a593Smuzhiyun return ret;
1993*4882a593Smuzhiyun }
1994*4882a593Smuzhiyun
1995*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
init_rw_trn_result_struct(struct rw_trn_result * result,void __iomem * phy_base,u8 cs_num)1996*4882a593Smuzhiyun static void init_rw_trn_result_struct(struct rw_trn_result *result,
1997*4882a593Smuzhiyun void __iomem *phy_base, u8 cs_num)
1998*4882a593Smuzhiyun {
1999*4882a593Smuzhiyun int i;
2000*4882a593Smuzhiyun
2001*4882a593Smuzhiyun result->cs_num = cs_num;
2002*4882a593Smuzhiyun result->byte_en = readb(PHY_REG(dram_info.phy, 0xf)) &
2003*4882a593Smuzhiyun PHY_DQ_WIDTH_MASK;
2004*4882a593Smuzhiyun for (i = 0; i < FSP_NUM; i++)
2005*4882a593Smuzhiyun result->fsp_mhz[i] = 0;
2006*4882a593Smuzhiyun }
2007*4882a593Smuzhiyun
save_rw_trn_min_max(void __iomem * phy_base,struct cs_rw_trn_result * rd_result,struct cs_rw_trn_result * wr_result,u8 byte_en)2008*4882a593Smuzhiyun static void save_rw_trn_min_max(void __iomem *phy_base,
2009*4882a593Smuzhiyun struct cs_rw_trn_result *rd_result,
2010*4882a593Smuzhiyun struct cs_rw_trn_result *wr_result,
2011*4882a593Smuzhiyun u8 byte_en)
2012*4882a593Smuzhiyun {
2013*4882a593Smuzhiyun u16 phy_ofs;
2014*4882a593Smuzhiyun u8 dqs;
2015*4882a593Smuzhiyun u8 dq;
2016*4882a593Smuzhiyun
2017*4882a593Smuzhiyun for (dqs = 0; dqs < BYTE_NUM; dqs++) {
2018*4882a593Smuzhiyun if ((byte_en & BIT(dqs)) == 0)
2019*4882a593Smuzhiyun continue;
2020*4882a593Smuzhiyun
2021*4882a593Smuzhiyun /* Channel A or B (low or high 16 bit) */
2022*4882a593Smuzhiyun phy_ofs = dqs < 2 ? 0x230 : 0x2b0;
2023*4882a593Smuzhiyun /* low or high 8 bit */
2024*4882a593Smuzhiyun phy_ofs += (dqs & 0x1) == 0 ? 0 : 0x9;
2025*4882a593Smuzhiyun for (dq = 0; dq < 8; dq++) {
2026*4882a593Smuzhiyun rd_result->dqs[dqs].dq_min[dq] =
2027*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x15 + dq));
2028*4882a593Smuzhiyun rd_result->dqs[dqs].dq_max[dq] =
2029*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x27 + dq));
2030*4882a593Smuzhiyun wr_result->dqs[dqs].dq_min[dq] =
2031*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x3d + dq));
2032*4882a593Smuzhiyun wr_result->dqs[dqs].dq_max[dq] =
2033*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x4f + dq));
2034*4882a593Smuzhiyun }
2035*4882a593Smuzhiyun }
2036*4882a593Smuzhiyun }
2037*4882a593Smuzhiyun
save_rw_trn_deskew(void __iomem * phy_base,struct fsp_rw_trn_result * result,u8 cs_num,int min_val,bool rw)2038*4882a593Smuzhiyun static void save_rw_trn_deskew(void __iomem *phy_base,
2039*4882a593Smuzhiyun struct fsp_rw_trn_result *result, u8 cs_num,
2040*4882a593Smuzhiyun int min_val, bool rw)
2041*4882a593Smuzhiyun {
2042*4882a593Smuzhiyun u16 phy_ofs;
2043*4882a593Smuzhiyun u8 cs;
2044*4882a593Smuzhiyun u8 dq;
2045*4882a593Smuzhiyun
2046*4882a593Smuzhiyun result->min_val = min_val;
2047*4882a593Smuzhiyun
2048*4882a593Smuzhiyun for (cs = 0; cs < cs_num; cs++) {
2049*4882a593Smuzhiyun phy_ofs = cs == 0 ? 0x170 : 0x1a0;
2050*4882a593Smuzhiyun phy_ofs += rw == SKEW_RX_SIGNAL ? 0x1 : 0x17;
2051*4882a593Smuzhiyun for (dq = 0; dq < 8; dq++) {
2052*4882a593Smuzhiyun result->cs[cs].dqs[0].dq_deskew[dq] =
2053*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + dq));
2054*4882a593Smuzhiyun result->cs[cs].dqs[1].dq_deskew[dq] =
2055*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0xb + dq));
2056*4882a593Smuzhiyun result->cs[cs].dqs[2].dq_deskew[dq] =
2057*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x60 + dq));
2058*4882a593Smuzhiyun result->cs[cs].dqs[3].dq_deskew[dq] =
2059*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + dq));
2060*4882a593Smuzhiyun }
2061*4882a593Smuzhiyun
2062*4882a593Smuzhiyun result->cs[cs].dqs[0].dqs_deskew =
2063*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x8));
2064*4882a593Smuzhiyun result->cs[cs].dqs[1].dqs_deskew =
2065*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0xb + 0x8));
2066*4882a593Smuzhiyun result->cs[cs].dqs[2].dqs_deskew =
2067*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0x8));
2068*4882a593Smuzhiyun result->cs[cs].dqs[3].dqs_deskew =
2069*4882a593Smuzhiyun readb(PHY_REG(phy_base, phy_ofs + 0x60 + 0xb + 0x8));
2070*4882a593Smuzhiyun }
2071*4882a593Smuzhiyun }
2072*4882a593Smuzhiyun
save_rw_trn_result_to_ddr(struct rw_trn_result * result)2073*4882a593Smuzhiyun static void save_rw_trn_result_to_ddr(struct rw_trn_result *result)
2074*4882a593Smuzhiyun {
2075*4882a593Smuzhiyun result->flag = DDR_DQ_EYE_FLAG;
2076*4882a593Smuzhiyun memcpy((void *)(RW_TRN_RESULT_ADDR), result, sizeof(*result));
2077*4882a593Smuzhiyun }
2078*4882a593Smuzhiyun #endif
2079*4882a593Smuzhiyun
high_freq_training(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 fsp)2080*4882a593Smuzhiyun static int high_freq_training(struct dram_info *dram,
2081*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params,
2082*4882a593Smuzhiyun u32 fsp)
2083*4882a593Smuzhiyun {
2084*4882a593Smuzhiyun u32 i, j;
2085*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
2086*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
2087*4882a593Smuzhiyun int min_val;
2088*4882a593Smuzhiyun int dqs_skew, clk_skew, ca_skew;
2089*4882a593Smuzhiyun u8 byte_en;
2090*4882a593Smuzhiyun int ret;
2091*4882a593Smuzhiyun
2092*4882a593Smuzhiyun byte_en = readl(PHY_REG(phy_base, 0xf)) & PHY_DQ_WIDTH_MASK;
2093*4882a593Smuzhiyun dqs_skew = 0;
2094*4882a593Smuzhiyun for (j = 0; j < sdram_params->ch.cap_info.rank; j++) {
2095*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
2096*4882a593Smuzhiyun if ((byte_en & BIT(i)) != 0)
2097*4882a593Smuzhiyun dqs_skew += wrlvl_result[j][i];
2098*4882a593Smuzhiyun }
2099*4882a593Smuzhiyun }
2100*4882a593Smuzhiyun dqs_skew = dqs_skew /
2101*4882a593Smuzhiyun (int)(sdram_params->ch.cap_info.rank * (1 << sdram_params->ch.cap_info.bw));
2102*4882a593Smuzhiyun
2103*4882a593Smuzhiyun clk_skew = 0x20 - dqs_skew;
2104*4882a593Smuzhiyun dqs_skew = 0x20;
2105*4882a593Smuzhiyun
2106*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
2107*4882a593Smuzhiyun min_val = 0xff;
2108*4882a593Smuzhiyun for (j = 0; j < sdram_params->ch.cap_info.rank; j++)
2109*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(wrlvl_result[0]); i++) {
2110*4882a593Smuzhiyun if ((byte_en & BIT(i)) != 0)
2111*4882a593Smuzhiyun min_val = MIN(wrlvl_result[j][i], min_val);
2112*4882a593Smuzhiyun }
2113*4882a593Smuzhiyun
2114*4882a593Smuzhiyun if (min_val < 0) {
2115*4882a593Smuzhiyun clk_skew = -min_val;
2116*4882a593Smuzhiyun ca_skew = -min_val;
2117*4882a593Smuzhiyun } else {
2118*4882a593Smuzhiyun clk_skew = 0;
2119*4882a593Smuzhiyun ca_skew = 0;
2120*4882a593Smuzhiyun }
2121*4882a593Smuzhiyun } else if (dramtype == LPDDR3) {
2122*4882a593Smuzhiyun ca_skew = clk_skew - 4;
2123*4882a593Smuzhiyun } else {
2124*4882a593Smuzhiyun ca_skew = clk_skew;
2125*4882a593Smuzhiyun }
2126*4882a593Smuzhiyun modify_ca_deskew(dram, DESKEW_MDF_ABS_VAL, clk_skew, ca_skew, 3,
2127*4882a593Smuzhiyun dramtype);
2128*4882a593Smuzhiyun
2129*4882a593Smuzhiyun writel(wrlvl_result[0][0] + clk_skew, PHY_REG(phy_base, 0x233));
2130*4882a593Smuzhiyun writel(wrlvl_result[0][1] + clk_skew, PHY_REG(phy_base, 0x237));
2131*4882a593Smuzhiyun writel(wrlvl_result[0][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
2132*4882a593Smuzhiyun writel(wrlvl_result[0][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
2133*4882a593Smuzhiyun ret = data_training(dram, 0, sdram_params, fsp, READ_GATE_TRAINING |
2134*4882a593Smuzhiyun READ_TRAINING | WRITE_TRAINING);
2135*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2136*4882a593Smuzhiyun rw_trn_result.fsp_mhz[fsp] = (u16)sdram_params->base.ddr_freq;
2137*4882a593Smuzhiyun save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[0],
2138*4882a593Smuzhiyun &rw_trn_result.wr_fsp[fsp].cs[0],
2139*4882a593Smuzhiyun rw_trn_result.byte_en);
2140*4882a593Smuzhiyun #endif
2141*4882a593Smuzhiyun if (sdram_params->ch.cap_info.rank == 2) {
2142*4882a593Smuzhiyun writel(wrlvl_result[1][0] + clk_skew, PHY_REG(phy_base, 0x233));
2143*4882a593Smuzhiyun writel(wrlvl_result[1][1] + clk_skew, PHY_REG(phy_base, 0x237));
2144*4882a593Smuzhiyun writel(wrlvl_result[1][2] + clk_skew, PHY_REG(phy_base, 0x2b3));
2145*4882a593Smuzhiyun writel(wrlvl_result[1][3] + clk_skew, PHY_REG(phy_base, 0x2b7));
2146*4882a593Smuzhiyun ret |= data_training(dram, 1, sdram_params, fsp,
2147*4882a593Smuzhiyun READ_GATE_TRAINING | READ_TRAINING |
2148*4882a593Smuzhiyun WRITE_TRAINING);
2149*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2150*4882a593Smuzhiyun save_rw_trn_min_max(phy_base, &rw_trn_result.rd_fsp[fsp].cs[1],
2151*4882a593Smuzhiyun &rw_trn_result.wr_fsp[fsp].cs[1],
2152*4882a593Smuzhiyun rw_trn_result.byte_en);
2153*4882a593Smuzhiyun #endif
2154*4882a593Smuzhiyun }
2155*4882a593Smuzhiyun if (ret)
2156*4882a593Smuzhiyun goto out;
2157*4882a593Smuzhiyun
2158*4882a593Smuzhiyun record_dq_prebit(dram);
2159*4882a593Smuzhiyun
2160*4882a593Smuzhiyun min_val = get_min_value(dram, SKEW_RX_SIGNAL,
2161*4882a593Smuzhiyun sdram_params->ch.cap_info.rank) * -1;
2162*4882a593Smuzhiyun modify_dq_deskew(dram, SKEW_RX_SIGNAL, DESKEW_MDF_DIFF_VAL,
2163*4882a593Smuzhiyun min_val, min_val, sdram_params->ch.cap_info.rank);
2164*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2165*4882a593Smuzhiyun save_rw_trn_deskew(phy_base, &rw_trn_result.rd_fsp[fsp],
2166*4882a593Smuzhiyun rw_trn_result.cs_num, (u8)(min_val * (-1)),
2167*4882a593Smuzhiyun SKEW_RX_SIGNAL);
2168*4882a593Smuzhiyun #endif
2169*4882a593Smuzhiyun
2170*4882a593Smuzhiyun min_val = MIN(get_min_value(dram, SKEW_TX_SIGNAL,
2171*4882a593Smuzhiyun sdram_params->ch.cap_info.rank),
2172*4882a593Smuzhiyun get_min_value(dram, SKEW_CA_SIGNAL,
2173*4882a593Smuzhiyun sdram_params->ch.cap_info.rank)) * -1;
2174*4882a593Smuzhiyun
2175*4882a593Smuzhiyun /* clk = 0, rx all skew -7, tx - min_value */
2176*4882a593Smuzhiyun modify_ca_deskew(dram, DESKEW_MDF_DIFF_VAL, min_val, min_val, 3,
2177*4882a593Smuzhiyun dramtype);
2178*4882a593Smuzhiyun
2179*4882a593Smuzhiyun modify_dq_deskew(dram, SKEW_TX_SIGNAL, DESKEW_MDF_DIFF_VAL,
2180*4882a593Smuzhiyun min_val, min_val, sdram_params->ch.cap_info.rank);
2181*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
2182*4882a593Smuzhiyun save_rw_trn_deskew(phy_base, &rw_trn_result.wr_fsp[fsp],
2183*4882a593Smuzhiyun rw_trn_result.cs_num, (u8)(min_val * (-1)),
2184*4882a593Smuzhiyun SKEW_TX_SIGNAL);
2185*4882a593Smuzhiyun #endif
2186*4882a593Smuzhiyun
2187*4882a593Smuzhiyun ret = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING);
2188*4882a593Smuzhiyun if (sdram_params->ch.cap_info.rank == 2)
2189*4882a593Smuzhiyun ret |= data_training(dram, 1, sdram_params, 0,
2190*4882a593Smuzhiyun READ_GATE_TRAINING);
2191*4882a593Smuzhiyun out:
2192*4882a593Smuzhiyun return ret;
2193*4882a593Smuzhiyun }
2194*4882a593Smuzhiyun
set_ddrconfig(struct dram_info * dram,u32 ddrconfig)2195*4882a593Smuzhiyun static void set_ddrconfig(struct dram_info *dram, u32 ddrconfig)
2196*4882a593Smuzhiyun {
2197*4882a593Smuzhiyun writel(ddrconfig, &dram->msch->deviceconf);
2198*4882a593Smuzhiyun clrsetbits_le32(&dram->grf->noc_con0, 0x3 << 0, 0 << 0);
2199*4882a593Smuzhiyun }
2200*4882a593Smuzhiyun
update_noc_timing(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2201*4882a593Smuzhiyun static void update_noc_timing(struct dram_info *dram,
2202*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
2203*4882a593Smuzhiyun {
2204*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2205*4882a593Smuzhiyun u32 bw, bl;
2206*4882a593Smuzhiyun
2207*4882a593Smuzhiyun bw = 8 << sdram_params->ch.cap_info.bw;
2208*4882a593Smuzhiyun bl = ((readl(pctl_base + DDR_PCTL2_MSTR) >> 16) & 0xf) * 2;
2209*4882a593Smuzhiyun
2210*4882a593Smuzhiyun /* update the noc timing related to data bus width */
2211*4882a593Smuzhiyun if ((bw / 8 * bl) <= 16)
2212*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrmode.b.burstsize = 0;
2213*4882a593Smuzhiyun else if ((bw / 8 * bl) == 32)
2214*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrmode.b.burstsize = 1;
2215*4882a593Smuzhiyun else if ((bw / 8 * bl) == 64)
2216*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrmode.b.burstsize = 2;
2217*4882a593Smuzhiyun else
2218*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrmode.b.burstsize = 3;
2219*4882a593Smuzhiyun
2220*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty =
2221*4882a593Smuzhiyun (bl * bw / 8) > 16 ? (bl / 4) : (16 / (bl * bw / 8)) * bl / 4;
2222*4882a593Smuzhiyun
2223*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR4 ||
2224*4882a593Smuzhiyun sdram_params->base.dramtype == LPDDR4X) {
2225*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrmode.b.mwrsize =
2226*4882a593Smuzhiyun (bw == 16) ? 0x1 : 0x2;
2227*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrtimingc0.b.wrtomwr =
2228*4882a593Smuzhiyun 3 * sdram_params->ch.noc_timings.ddrtimingc0.b.burstpenalty;
2229*4882a593Smuzhiyun }
2230*4882a593Smuzhiyun
2231*4882a593Smuzhiyun writel(sdram_params->ch.noc_timings.ddrtiminga0.d32,
2232*4882a593Smuzhiyun &dram->msch->ddrtiminga0);
2233*4882a593Smuzhiyun writel(sdram_params->ch.noc_timings.ddrtimingb0.d32,
2234*4882a593Smuzhiyun &dram->msch->ddrtimingb0);
2235*4882a593Smuzhiyun writel(sdram_params->ch.noc_timings.ddrtimingc0.d32,
2236*4882a593Smuzhiyun &dram->msch->ddrtimingc0);
2237*4882a593Smuzhiyun writel(sdram_params->ch.noc_timings.devtodev0.d32,
2238*4882a593Smuzhiyun &dram->msch->devtodev0);
2239*4882a593Smuzhiyun writel(sdram_params->ch.noc_timings.ddrmode.d32, &dram->msch->ddrmode);
2240*4882a593Smuzhiyun writel(sdram_params->ch.noc_timings.ddr4timing.d32,
2241*4882a593Smuzhiyun &dram->msch->ddr4timing);
2242*4882a593Smuzhiyun }
2243*4882a593Smuzhiyun
split_setup(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2244*4882a593Smuzhiyun static int split_setup(struct dram_info *dram,
2245*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
2246*4882a593Smuzhiyun {
2247*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2248*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
2249*4882a593Smuzhiyun u32 split_size, split_mode;
2250*4882a593Smuzhiyun u64 cs_cap[2], cap;
2251*4882a593Smuzhiyun
2252*4882a593Smuzhiyun cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dramtype);
2253*4882a593Smuzhiyun cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dramtype);
2254*4882a593Smuzhiyun /* only support the larger cap is in low 16bit */
2255*4882a593Smuzhiyun if (cap_info->cs0_high16bit_row < cap_info->cs0_row) {
2256*4882a593Smuzhiyun cap = cs_cap[0] / (1 << (cap_info->cs0_row -
2257*4882a593Smuzhiyun cap_info->cs0_high16bit_row));
2258*4882a593Smuzhiyun } else if ((cap_info->cs1_high16bit_row < cap_info->cs1_row) &&
2259*4882a593Smuzhiyun (cap_info->rank == 2)) {
2260*4882a593Smuzhiyun if (!cap_info->cs1_high16bit_row)
2261*4882a593Smuzhiyun cap = cs_cap[0];
2262*4882a593Smuzhiyun else
2263*4882a593Smuzhiyun cap = cs_cap[0] + cs_cap[1] / (1 << (cap_info->cs1_row -
2264*4882a593Smuzhiyun cap_info->cs1_high16bit_row));
2265*4882a593Smuzhiyun } else {
2266*4882a593Smuzhiyun goto out;
2267*4882a593Smuzhiyun }
2268*4882a593Smuzhiyun split_size = (u32)(cap >> 24) & SPLIT_SIZE_MASK;
2269*4882a593Smuzhiyun if (cap_info->bw == 2)
2270*4882a593Smuzhiyun split_mode = SPLIT_MODE_32_L16_VALID;
2271*4882a593Smuzhiyun else
2272*4882a593Smuzhiyun split_mode = SPLIT_MODE_16_L8_VALID;
2273*4882a593Smuzhiyun
2274*4882a593Smuzhiyun rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
2275*4882a593Smuzhiyun (SPLIT_MODE_MASK << SPLIT_MODE_OFFSET) |
2276*4882a593Smuzhiyun (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
2277*4882a593Smuzhiyun (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
2278*4882a593Smuzhiyun (split_mode << SPLIT_MODE_OFFSET) |
2279*4882a593Smuzhiyun (0x0 << SPLIT_BYPASS_OFFSET) |
2280*4882a593Smuzhiyun (split_size << SPLIT_SIZE_OFFSET));
2281*4882a593Smuzhiyun
2282*4882a593Smuzhiyun rk_clrsetreg(BUS_SGRF_BASE_ADDR + SGRF_SOC_CON2,
2283*4882a593Smuzhiyun MSCH_AXI_BYPASS_ALL_MASK << MSCH_AXI_BYPASS_ALL_SHIFT,
2284*4882a593Smuzhiyun 0x0 << MSCH_AXI_BYPASS_ALL_SHIFT);
2285*4882a593Smuzhiyun
2286*4882a593Smuzhiyun out:
2287*4882a593Smuzhiyun return 0;
2288*4882a593Smuzhiyun }
2289*4882a593Smuzhiyun
split_bypass(struct dram_info * dram)2290*4882a593Smuzhiyun static void split_bypass(struct dram_info *dram)
2291*4882a593Smuzhiyun {
2292*4882a593Smuzhiyun if ((readl(&dram->ddrgrf->grf_ddrsplit_con) &
2293*4882a593Smuzhiyun (1 << SPLIT_BYPASS_OFFSET)) != 0)
2294*4882a593Smuzhiyun return;
2295*4882a593Smuzhiyun
2296*4882a593Smuzhiyun /* bypass split */
2297*4882a593Smuzhiyun rk_clrsetreg(&dram->ddrgrf->grf_ddrsplit_con,
2298*4882a593Smuzhiyun (SPLIT_BYPASS_MASK << SPLIT_BYPASS_OFFSET) |
2299*4882a593Smuzhiyun (SPLIT_SIZE_MASK << SPLIT_SIZE_OFFSET),
2300*4882a593Smuzhiyun (0x1 << SPLIT_BYPASS_OFFSET) |
2301*4882a593Smuzhiyun (0x0 << SPLIT_SIZE_OFFSET));
2302*4882a593Smuzhiyun }
2303*4882a593Smuzhiyun
dram_all_config(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2304*4882a593Smuzhiyun static void dram_all_config(struct dram_info *dram,
2305*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
2306*4882a593Smuzhiyun {
2307*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2308*4882a593Smuzhiyun u32 dram_type = sdram_params->base.dramtype;
2309*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2310*4882a593Smuzhiyun u32 sys_reg2 = 0;
2311*4882a593Smuzhiyun u32 sys_reg3 = 0;
2312*4882a593Smuzhiyun u64 cs_cap[2];
2313*4882a593Smuzhiyun u32 cs_pst;
2314*4882a593Smuzhiyun
2315*4882a593Smuzhiyun set_ddrconfig(dram, cap_info->ddrconfig);
2316*4882a593Smuzhiyun sdram_org_config(cap_info, &sdram_params->base, &sys_reg2,
2317*4882a593Smuzhiyun &sys_reg3, 0);
2318*4882a593Smuzhiyun writel(sys_reg2, &dram->pmugrf->os_reg[2]);
2319*4882a593Smuzhiyun writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2320*4882a593Smuzhiyun
2321*4882a593Smuzhiyun cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2322*4882a593Smuzhiyun cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2323*4882a593Smuzhiyun
2324*4882a593Smuzhiyun if (cap_info->rank == 2) {
2325*4882a593Smuzhiyun cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2326*4882a593Smuzhiyun 6 + 2;
2327*4882a593Smuzhiyun if (cs_pst > 28)
2328*4882a593Smuzhiyun cs_cap[0] = 1llu << cs_pst;
2329*4882a593Smuzhiyun }
2330*4882a593Smuzhiyun
2331*4882a593Smuzhiyun writel(((((cs_cap[1] >> 20) / 64) & 0xff) << 8) |
2332*4882a593Smuzhiyun (((cs_cap[0] >> 20) / 64) & 0xff),
2333*4882a593Smuzhiyun &dram->msch->devicesize);
2334*4882a593Smuzhiyun update_noc_timing(dram, sdram_params);
2335*4882a593Smuzhiyun }
2336*4882a593Smuzhiyun
enable_low_power(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2337*4882a593Smuzhiyun static void enable_low_power(struct dram_info *dram,
2338*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
2339*4882a593Smuzhiyun {
2340*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2341*4882a593Smuzhiyun u32 grf_lp_con;
2342*4882a593Smuzhiyun
2343*4882a593Smuzhiyun writel(0x1f1f0617, &dram->ddrgrf->ddr_grf_con[1]);
2344*4882a593Smuzhiyun
2345*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4)
2346*4882a593Smuzhiyun grf_lp_con = (0x7 << 16) | (1 << 1);
2347*4882a593Smuzhiyun else if (sdram_params->base.dramtype == DDR3)
2348*4882a593Smuzhiyun grf_lp_con = (0x7 << 16) | (1 << 0);
2349*4882a593Smuzhiyun else
2350*4882a593Smuzhiyun grf_lp_con = (0x7 << 16) | (1 << 2);
2351*4882a593Smuzhiyun
2352*4882a593Smuzhiyun /* en lpckdis_en */
2353*4882a593Smuzhiyun grf_lp_con = grf_lp_con | (0x1 << (9 + 16)) | (0x1 << 9);
2354*4882a593Smuzhiyun writel(grf_lp_con, &dram->ddrgrf->ddr_grf_lp_con);
2355*4882a593Smuzhiyun
2356*4882a593Smuzhiyun /* enable sr, pd */
2357*4882a593Smuzhiyun if (dram->pd_idle == 0)
2358*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2359*4882a593Smuzhiyun else
2360*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 1));
2361*4882a593Smuzhiyun if (dram->sr_idle == 0)
2362*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2363*4882a593Smuzhiyun else
2364*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, 1);
2365*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_PWRCTL, (1 << 3));
2366*4882a593Smuzhiyun }
2367*4882a593Smuzhiyun
ddr_set_atags(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2368*4882a593Smuzhiyun static void ddr_set_atags(struct dram_info *dram,
2369*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
2370*4882a593Smuzhiyun {
2371*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2372*4882a593Smuzhiyun u32 dram_type = sdram_params->base.dramtype;
2373*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2374*4882a593Smuzhiyun struct tag_serial t_serial;
2375*4882a593Smuzhiyun struct tag_ddr_mem t_ddrmem;
2376*4882a593Smuzhiyun struct tag_soc_info t_socinfo;
2377*4882a593Smuzhiyun u64 cs_cap[2];
2378*4882a593Smuzhiyun u32 cs_pst = 0;
2379*4882a593Smuzhiyun u32 split, split_size;
2380*4882a593Smuzhiyun u64 reduce_cap = 0;
2381*4882a593Smuzhiyun
2382*4882a593Smuzhiyun cs_cap[0] = sdram_get_cs_cap(cap_info, 0, dram_type);
2383*4882a593Smuzhiyun cs_cap[1] = sdram_get_cs_cap(cap_info, 1, dram_type);
2384*4882a593Smuzhiyun
2385*4882a593Smuzhiyun memset(&t_serial, 0, sizeof(struct tag_serial));
2386*4882a593Smuzhiyun
2387*4882a593Smuzhiyun t_serial.version = 0;
2388*4882a593Smuzhiyun t_serial.enable = 1;
2389*4882a593Smuzhiyun t_serial.addr = CONFIG_DEBUG_UART_BASE;
2390*4882a593Smuzhiyun t_serial.baudrate = CONFIG_BAUDRATE;
2391*4882a593Smuzhiyun t_serial.m_mode = SERIAL_M_MODE_M0;
2392*4882a593Smuzhiyun t_serial.id = 2;
2393*4882a593Smuzhiyun
2394*4882a593Smuzhiyun atags_destroy();
2395*4882a593Smuzhiyun atags_set_tag(ATAG_SERIAL, &t_serial);
2396*4882a593Smuzhiyun
2397*4882a593Smuzhiyun split = readl(&dram->ddrgrf->grf_ddrsplit_con);
2398*4882a593Smuzhiyun memset(&t_ddrmem, 0, sizeof(struct tag_ddr_mem));
2399*4882a593Smuzhiyun if (cap_info->row_3_4) {
2400*4882a593Smuzhiyun cs_cap[0] = cs_cap[0] * 3 / 4;
2401*4882a593Smuzhiyun cs_cap[1] = cs_cap[1] * 3 / 4;
2402*4882a593Smuzhiyun } else if (!(split & (1 << SPLIT_BYPASS_OFFSET))) {
2403*4882a593Smuzhiyun split_size = (split >> SPLIT_SIZE_OFFSET) & SPLIT_SIZE_MASK;
2404*4882a593Smuzhiyun reduce_cap = (cs_cap[0] + cs_cap[1] - (split_size << 24)) / 2;
2405*4882a593Smuzhiyun }
2406*4882a593Smuzhiyun t_ddrmem.version = 0;
2407*4882a593Smuzhiyun t_ddrmem.bank[0] = CONFIG_SYS_SDRAM_BASE;
2408*4882a593Smuzhiyun if (cs_cap[1]) {
2409*4882a593Smuzhiyun cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2410*4882a593Smuzhiyun 6 + 2;
2411*4882a593Smuzhiyun }
2412*4882a593Smuzhiyun
2413*4882a593Smuzhiyun if (cs_cap[1] && cs_pst > 27) {
2414*4882a593Smuzhiyun t_ddrmem.count = 2;
2415*4882a593Smuzhiyun t_ddrmem.bank[1] = 1 << cs_pst;
2416*4882a593Smuzhiyun t_ddrmem.bank[2] = cs_cap[0];
2417*4882a593Smuzhiyun t_ddrmem.bank[3] = cs_cap[1] - reduce_cap;
2418*4882a593Smuzhiyun } else {
2419*4882a593Smuzhiyun t_ddrmem.count = 1;
2420*4882a593Smuzhiyun t_ddrmem.bank[1] = (u64)cs_cap[0] + (u64)cs_cap[1] - reduce_cap;
2421*4882a593Smuzhiyun }
2422*4882a593Smuzhiyun
2423*4882a593Smuzhiyun atags_set_tag(ATAG_DDR_MEM, &t_ddrmem);
2424*4882a593Smuzhiyun
2425*4882a593Smuzhiyun memset(&t_socinfo, 0, sizeof(struct tag_soc_info));
2426*4882a593Smuzhiyun t_socinfo.version = 0x1;
2427*4882a593Smuzhiyun t_socinfo.name = 0x1126;
2428*4882a593Smuzhiyun t_socinfo.flags = SOC_FLAGS_TDBT;
2429*4882a593Smuzhiyun atags_set_tag(ATAG_SOC_INFO, &t_socinfo);
2430*4882a593Smuzhiyun }
2431*4882a593Smuzhiyun
print_ddr_info(struct rv1126_sdram_params * sdram_params)2432*4882a593Smuzhiyun static void print_ddr_info(struct rv1126_sdram_params *sdram_params)
2433*4882a593Smuzhiyun {
2434*4882a593Smuzhiyun u32 split;
2435*4882a593Smuzhiyun
2436*4882a593Smuzhiyun if ((readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2437*4882a593Smuzhiyun (1 << SPLIT_BYPASS_OFFSET)) != 0)
2438*4882a593Smuzhiyun split = 0;
2439*4882a593Smuzhiyun else
2440*4882a593Smuzhiyun split = readl(DDR_GRF_BASE_ADDR + DDR_GRF_SPLIT_CON) &
2441*4882a593Smuzhiyun SPLIT_SIZE_MASK;
2442*4882a593Smuzhiyun
2443*4882a593Smuzhiyun sdram_print_ddr_info(&sdram_params->ch.cap_info,
2444*4882a593Smuzhiyun &sdram_params->base, split);
2445*4882a593Smuzhiyun }
2446*4882a593Smuzhiyun
modify_ddr34_bw_byte_map(u8 rg_result,struct rv1126_sdram_params * sdram_params)2447*4882a593Smuzhiyun static int modify_ddr34_bw_byte_map(u8 rg_result, struct rv1126_sdram_params *sdram_params)
2448*4882a593Smuzhiyun {
2449*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index = (struct sdram_head_info_index_v2 *)common_info;
2450*4882a593Smuzhiyun struct dq_map_info *map_info = (struct dq_map_info *)
2451*4882a593Smuzhiyun ((void *)common_info + index->dq_map_index.offset * 4);
2452*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2453*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
2454*4882a593Smuzhiyun u32 byte_map = 0;
2455*4882a593Smuzhiyun u32 byte = 0;
2456*4882a593Smuzhiyun u32 byte_map_shift;
2457*4882a593Smuzhiyun int i;
2458*4882a593Smuzhiyun
2459*4882a593Smuzhiyun if (dramtype == DDR3)
2460*4882a593Smuzhiyun byte_map_shift = 24;
2461*4882a593Smuzhiyun else if (dramtype == DDR4)
2462*4882a593Smuzhiyun byte_map_shift = 0;
2463*4882a593Smuzhiyun else
2464*4882a593Smuzhiyun return -1;
2465*4882a593Smuzhiyun
2466*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
2467*4882a593Smuzhiyun if ((rg_result & BIT(i)) == 0) {
2468*4882a593Smuzhiyun byte_map |= byte << (i * 2);
2469*4882a593Smuzhiyun byte++;
2470*4882a593Smuzhiyun }
2471*4882a593Smuzhiyun }
2472*4882a593Smuzhiyun if (byte != 1 && byte != 2 && byte != 4) {
2473*4882a593Smuzhiyun printascii("DTT result is abnormal: ");
2474*4882a593Smuzhiyun printdec(byte);
2475*4882a593Smuzhiyun printascii("byte\n");
2476*4882a593Smuzhiyun return -1;
2477*4882a593Smuzhiyun }
2478*4882a593Smuzhiyun cap_info->bw = byte / 2;
2479*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
2480*4882a593Smuzhiyun if ((rg_result & BIT(i)) != 0) {
2481*4882a593Smuzhiyun byte_map |= byte << (i * 2);
2482*4882a593Smuzhiyun byte++;
2483*4882a593Smuzhiyun }
2484*4882a593Smuzhiyun }
2485*4882a593Smuzhiyun
2486*4882a593Smuzhiyun if ((u8)byte_map != (u8)(map_info->byte_map[0] >> byte_map_shift)) {
2487*4882a593Smuzhiyun clrsetbits_le32(&map_info->byte_map[0],
2488*4882a593Smuzhiyun 0xff << byte_map_shift, byte_map << byte_map_shift);
2489*4882a593Smuzhiyun pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info, dramtype);
2490*4882a593Smuzhiyun return 1;
2491*4882a593Smuzhiyun }
2492*4882a593Smuzhiyun
2493*4882a593Smuzhiyun return 0;
2494*4882a593Smuzhiyun }
2495*4882a593Smuzhiyun
sdram_init_(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 post_init)2496*4882a593Smuzhiyun int sdram_init_(struct dram_info *dram, struct rv1126_sdram_params *sdram_params, u32 post_init)
2497*4882a593Smuzhiyun {
2498*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2499*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
2500*4882a593Smuzhiyun u32 ddr4_vref;
2501*4882a593Smuzhiyun u32 mr_tmp, tmp;
2502*4882a593Smuzhiyun int delay = 1000;
2503*4882a593Smuzhiyun
2504*4882a593Smuzhiyun rkclk_configure_ddr(dram, sdram_params);
2505*4882a593Smuzhiyun
2506*4882a593Smuzhiyun rkclk_ddr_reset(dram, 1, 1, 1, 1);
2507*4882a593Smuzhiyun udelay(10);
2508*4882a593Smuzhiyun
2509*4882a593Smuzhiyun rkclk_ddr_reset(dram, 1, 1, 1, 0);
2510*4882a593Smuzhiyun phy_cfg(dram, sdram_params);
2511*4882a593Smuzhiyun
2512*4882a593Smuzhiyun rkclk_ddr_reset(dram, 1, 1, 0, 0);
2513*4882a593Smuzhiyun phy_pll_set(dram, sdram_params->base.ddr_freq * MHZ, 1);
2514*4882a593Smuzhiyun
2515*4882a593Smuzhiyun rkclk_ddr_reset(dram, 1, 0, 0, 0);
2516*4882a593Smuzhiyun pctl_cfg(dram->pctl, &sdram_params->pctl_regs,
2517*4882a593Smuzhiyun dram->sr_idle, dram->pd_idle);
2518*4882a593Smuzhiyun
2519*4882a593Smuzhiyun if (sdram_params->ch.cap_info.bw == 2) {
2520*4882a593Smuzhiyun /* 32bit interface use pageclose */
2521*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
2522*4882a593Smuzhiyun /* pageclose = 1, pageclose_timer = 0 will err in lp4 328MHz */
2523*4882a593Smuzhiyun clrsetbits_le32(pctl_base + DDR_PCTL2_SCHED1, 0xff, 0x1 << 0);
2524*4882a593Smuzhiyun } else {
2525*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_SCHED, 1 << 2);
2526*4882a593Smuzhiyun }
2527*4882a593Smuzhiyun
2528*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
2529*4882a593Smuzhiyun u32 trefi;
2530*4882a593Smuzhiyun
2531*4882a593Smuzhiyun tmp = readl(pctl_base + DDR_PCTL2_RFSHTMG);
2532*4882a593Smuzhiyun trefi = (tmp >> 16) & 0xfff;
2533*4882a593Smuzhiyun writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
2534*4882a593Smuzhiyun pctl_base + DDR_PCTL2_RFSHTMG);
2535*4882a593Smuzhiyun #endif
2536*4882a593Smuzhiyun
2537*4882a593Smuzhiyun /* set frequency_mode */
2538*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
2539*4882a593Smuzhiyun /* set target_frequency to Frequency 0 */
2540*4882a593Smuzhiyun clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, 0);
2541*4882a593Smuzhiyun
2542*4882a593Smuzhiyun set_ds_odt(dram, sdram_params, 0);
2543*4882a593Smuzhiyun sdram_params->ch.cap_info.ddrconfig = calculate_ddrconfig(sdram_params);
2544*4882a593Smuzhiyun set_ctl_address_map(dram, sdram_params);
2545*4882a593Smuzhiyun
2546*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_DFIMISC, (1 << 5) | (1 << 4));
2547*4882a593Smuzhiyun
2548*4882a593Smuzhiyun rkclk_ddr_reset(dram, 0, 0, 0, 0);
2549*4882a593Smuzhiyun
2550*4882a593Smuzhiyun while ((readl(pctl_base + DDR_PCTL2_STAT) & 0x7) == 0) {
2551*4882a593Smuzhiyun udelay(1);
2552*4882a593Smuzhiyun if (delay-- <= 0) {
2553*4882a593Smuzhiyun printascii("ERROR: Cannot wait dfi_init_done!\n");
2554*4882a593Smuzhiyun while (1)
2555*4882a593Smuzhiyun ;
2556*4882a593Smuzhiyun }
2557*4882a593Smuzhiyun }
2558*4882a593Smuzhiyun
2559*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR3) {
2560*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, LPDDR3);
2561*4882a593Smuzhiyun } else if (sdram_params->base.dramtype == LPDDR4 ||
2562*4882a593Smuzhiyun sdram_params->base.dramtype == LPDDR4X) {
2563*4882a593Smuzhiyun mr_tmp = readl(pctl_base + DDR_PCTL2_INIT6);
2564*4882a593Smuzhiyun /* MR11 */
2565*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 11,
2566*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
2567*4882a593Smuzhiyun LPDDR4);
2568*4882a593Smuzhiyun /* MR12 */
2569*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 12,
2570*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
2571*4882a593Smuzhiyun LPDDR4);
2572*4882a593Smuzhiyun
2573*4882a593Smuzhiyun mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
2574*4882a593Smuzhiyun /* MR22 */
2575*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 22,
2576*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
2577*4882a593Smuzhiyun LPDDR4);
2578*4882a593Smuzhiyun }
2579*4882a593Smuzhiyun
2580*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR3 && post_init == 0)
2581*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
2582*4882a593Smuzhiyun tmp = data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) & 0xf;
2583*4882a593Smuzhiyun
2584*4882a593Smuzhiyun if (tmp != 0) {
2585*4882a593Smuzhiyun if (post_init != 0) {
2586*4882a593Smuzhiyun printascii("DTT cs0 error\n");
2587*4882a593Smuzhiyun return -1;
2588*4882a593Smuzhiyun }
2589*4882a593Smuzhiyun if (sdram_params->base.dramtype != DDR3 || tmp == 0xf)
2590*4882a593Smuzhiyun return -1;
2591*4882a593Smuzhiyun }
2592*4882a593Smuzhiyun
2593*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR3 && post_init == 0) {
2594*4882a593Smuzhiyun if (modify_ddr34_bw_byte_map((u8)tmp, sdram_params) != 0)
2595*4882a593Smuzhiyun return -1;
2596*4882a593Smuzhiyun }
2597*4882a593Smuzhiyun
2598*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR4) {
2599*4882a593Smuzhiyun mr_tmp = read_mr(dram, 1, 14, LPDDR4);
2600*4882a593Smuzhiyun
2601*4882a593Smuzhiyun if (mr_tmp != 0x4d)
2602*4882a593Smuzhiyun return -1;
2603*4882a593Smuzhiyun }
2604*4882a593Smuzhiyun
2605*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR4 ||
2606*4882a593Smuzhiyun sdram_params->base.dramtype == LPDDR4X) {
2607*4882a593Smuzhiyun mr_tmp = readl(pctl_base + DDR_PCTL2_INIT7);
2608*4882a593Smuzhiyun /* MR14 */
2609*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 14,
2610*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
2611*4882a593Smuzhiyun LPDDR4);
2612*4882a593Smuzhiyun }
2613*4882a593Smuzhiyun if (post_init != 0 && sdram_params->ch.cap_info.rank == 2) {
2614*4882a593Smuzhiyun if (data_training(dram, 1, sdram_params, 0,
2615*4882a593Smuzhiyun READ_GATE_TRAINING) != 0) {
2616*4882a593Smuzhiyun printascii("DTT cs1 error\n");
2617*4882a593Smuzhiyun return -1;
2618*4882a593Smuzhiyun }
2619*4882a593Smuzhiyun }
2620*4882a593Smuzhiyun
2621*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4) {
2622*4882a593Smuzhiyun ddr4_vref = readl(PHY_REG(phy_base, 0x105)) * 39;
2623*4882a593Smuzhiyun pctl_write_vrefdq(dram->pctl, 0x3, ddr4_vref,
2624*4882a593Smuzhiyun sdram_params->base.dramtype);
2625*4882a593Smuzhiyun }
2626*4882a593Smuzhiyun
2627*4882a593Smuzhiyun dram_all_config(dram, sdram_params);
2628*4882a593Smuzhiyun enable_low_power(dram, sdram_params);
2629*4882a593Smuzhiyun
2630*4882a593Smuzhiyun return 0;
2631*4882a593Smuzhiyun }
2632*4882a593Smuzhiyun
dram_detect_cap(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,unsigned char channel)2633*4882a593Smuzhiyun static u64 dram_detect_cap(struct dram_info *dram,
2634*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params,
2635*4882a593Smuzhiyun unsigned char channel)
2636*4882a593Smuzhiyun {
2637*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2638*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2639*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
2640*4882a593Smuzhiyun u32 mr8;
2641*4882a593Smuzhiyun
2642*4882a593Smuzhiyun u32 bktmp;
2643*4882a593Smuzhiyun u32 coltmp;
2644*4882a593Smuzhiyun u32 rowtmp;
2645*4882a593Smuzhiyun u32 cs;
2646*4882a593Smuzhiyun u32 dram_type = sdram_params->base.dramtype;
2647*4882a593Smuzhiyun u32 pwrctl;
2648*4882a593Smuzhiyun u32 i, dq_map;
2649*4882a593Smuzhiyun u32 byte1 = 0, byte0 = 0;
2650*4882a593Smuzhiyun
2651*4882a593Smuzhiyun if (dram_type != LPDDR4 && dram_type != LPDDR4X) {
2652*4882a593Smuzhiyun if (dram_type != DDR4) {
2653*4882a593Smuzhiyun if (dram_type == DDR3)
2654*4882a593Smuzhiyun coltmp = 11;
2655*4882a593Smuzhiyun else
2656*4882a593Smuzhiyun coltmp = 12;
2657*4882a593Smuzhiyun bktmp = 3;
2658*4882a593Smuzhiyun if (dram_type == LPDDR2)
2659*4882a593Smuzhiyun rowtmp = 15;
2660*4882a593Smuzhiyun else
2661*4882a593Smuzhiyun rowtmp = 16;
2662*4882a593Smuzhiyun
2663*4882a593Smuzhiyun if (sdram_detect_col(cap_info, coltmp) != 0)
2664*4882a593Smuzhiyun goto cap_err;
2665*4882a593Smuzhiyun
2666*4882a593Smuzhiyun sdram_detect_bank(cap_info, coltmp, bktmp);
2667*4882a593Smuzhiyun if (dram_type != LPDDR3)
2668*4882a593Smuzhiyun sdram_detect_dbw(cap_info, dram_type);
2669*4882a593Smuzhiyun } else {
2670*4882a593Smuzhiyun coltmp = 10;
2671*4882a593Smuzhiyun bktmp = 4;
2672*4882a593Smuzhiyun rowtmp = 17;
2673*4882a593Smuzhiyun
2674*4882a593Smuzhiyun cap_info->col = 10;
2675*4882a593Smuzhiyun cap_info->bk = 2;
2676*4882a593Smuzhiyun sdram_detect_bg(cap_info, coltmp);
2677*4882a593Smuzhiyun }
2678*4882a593Smuzhiyun
2679*4882a593Smuzhiyun if (sdram_detect_row(cap_info, coltmp, bktmp, rowtmp) != 0)
2680*4882a593Smuzhiyun goto cap_err;
2681*4882a593Smuzhiyun
2682*4882a593Smuzhiyun sdram_detect_row_3_4(cap_info, coltmp, bktmp);
2683*4882a593Smuzhiyun } else {
2684*4882a593Smuzhiyun cap_info->col = 10;
2685*4882a593Smuzhiyun cap_info->bk = 3;
2686*4882a593Smuzhiyun mr8 = read_mr(dram, 1, 8, dram_type);
2687*4882a593Smuzhiyun cap_info->dbw = ((mr8 >> 6) & 0x3) == 0 ? 1 : 0;
2688*4882a593Smuzhiyun mr8 = (mr8 >> 2) & 0xf;
2689*4882a593Smuzhiyun if (mr8 >= 0 && mr8 <= 6) {
2690*4882a593Smuzhiyun cap_info->cs0_row = 14 + (mr8 + 1) / 2;
2691*4882a593Smuzhiyun } else if (mr8 == 0xc) {
2692*4882a593Smuzhiyun cap_info->cs0_row = 13;
2693*4882a593Smuzhiyun } else {
2694*4882a593Smuzhiyun printascii("Cap ERR: Fail to get cap of LPDDR4/X from MR8\n");
2695*4882a593Smuzhiyun goto cap_err;
2696*4882a593Smuzhiyun }
2697*4882a593Smuzhiyun if (cap_info->dbw == 0)
2698*4882a593Smuzhiyun cap_info->cs0_row++;
2699*4882a593Smuzhiyun cap_info->row_3_4 = mr8 % 2 == 1 ? 1 : 0;
2700*4882a593Smuzhiyun if (cap_info->cs0_row >= 17) {
2701*4882a593Smuzhiyun printascii("Cap ERR: ");
2702*4882a593Smuzhiyun printascii("RV1126 LPDDR4/X cannot support row >= 17\n");
2703*4882a593Smuzhiyun goto cap_err;
2704*4882a593Smuzhiyun // cap_info->cs0_row = 16;
2705*4882a593Smuzhiyun // cap_info->row_3_4 = 0;
2706*4882a593Smuzhiyun }
2707*4882a593Smuzhiyun }
2708*4882a593Smuzhiyun
2709*4882a593Smuzhiyun pwrctl = readl(pctl_base + DDR_PCTL2_PWRCTL);
2710*4882a593Smuzhiyun writel(0, pctl_base + DDR_PCTL2_PWRCTL);
2711*4882a593Smuzhiyun
2712*4882a593Smuzhiyun if (data_training(dram, 1, sdram_params, 0, READ_GATE_TRAINING) == 0)
2713*4882a593Smuzhiyun cs = 1;
2714*4882a593Smuzhiyun else
2715*4882a593Smuzhiyun cs = 0;
2716*4882a593Smuzhiyun cap_info->rank = cs + 1;
2717*4882a593Smuzhiyun
2718*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0xf), 0xf);
2719*4882a593Smuzhiyun
2720*4882a593Smuzhiyun if (dram_type != DDR3) {
2721*4882a593Smuzhiyun if ((data_training_rg(dram, 0, dram_type) & 0xf) == 0) {
2722*4882a593Smuzhiyun cap_info->bw = 2;
2723*4882a593Smuzhiyun } else {
2724*4882a593Smuzhiyun dq_map = readl(PHY_REG(phy_base, 0x4f));
2725*4882a593Smuzhiyun for (i = 0; i < 4; i++) {
2726*4882a593Smuzhiyun if (((dq_map >> (i * 2)) & 0x3) == 0)
2727*4882a593Smuzhiyun byte0 = i;
2728*4882a593Smuzhiyun if (((dq_map >> (i * 2)) & 0x3) == 1)
2729*4882a593Smuzhiyun byte1 = i;
2730*4882a593Smuzhiyun }
2731*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0xf), PHY_DQ_WIDTH_MASK,
2732*4882a593Smuzhiyun BIT(byte0) | BIT(byte1));
2733*4882a593Smuzhiyun if (data_training(dram, 0, sdram_params, 0, READ_GATE_TRAINING) == 0)
2734*4882a593Smuzhiyun cap_info->bw = 1;
2735*4882a593Smuzhiyun else
2736*4882a593Smuzhiyun cap_info->bw = 0;
2737*4882a593Smuzhiyun }
2738*4882a593Smuzhiyun }
2739*4882a593Smuzhiyun if (cap_info->bw > 0)
2740*4882a593Smuzhiyun cap_info->dbw = 1;
2741*4882a593Smuzhiyun
2742*4882a593Smuzhiyun writel(pwrctl, pctl_base + DDR_PCTL2_PWRCTL);
2743*4882a593Smuzhiyun
2744*4882a593Smuzhiyun cap_info->cs0_high16bit_row = cap_info->cs0_row;
2745*4882a593Smuzhiyun if (cs) {
2746*4882a593Smuzhiyun cap_info->cs1_row = cap_info->cs0_row;
2747*4882a593Smuzhiyun cap_info->cs1_high16bit_row = cap_info->cs0_row;
2748*4882a593Smuzhiyun } else {
2749*4882a593Smuzhiyun cap_info->cs1_row = 0;
2750*4882a593Smuzhiyun cap_info->cs1_high16bit_row = 0;
2751*4882a593Smuzhiyun }
2752*4882a593Smuzhiyun
2753*4882a593Smuzhiyun if (dram_type == LPDDR3)
2754*4882a593Smuzhiyun sdram_detect_dbw(cap_info, dram_type);
2755*4882a593Smuzhiyun
2756*4882a593Smuzhiyun return 0;
2757*4882a593Smuzhiyun cap_err:
2758*4882a593Smuzhiyun return -1;
2759*4882a593Smuzhiyun }
2760*4882a593Smuzhiyun
dram_detect_cs1_row(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,unsigned char channel)2761*4882a593Smuzhiyun static int dram_detect_cs1_row(struct dram_info *dram,
2762*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params,
2763*4882a593Smuzhiyun unsigned char channel)
2764*4882a593Smuzhiyun {
2765*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2766*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2767*4882a593Smuzhiyun u32 ret = 0;
2768*4882a593Smuzhiyun void __iomem *test_addr;
2769*4882a593Smuzhiyun u32 row, bktmp, coltmp, bw;
2770*4882a593Smuzhiyun u64 cs0_cap;
2771*4882a593Smuzhiyun u32 byte_mask;
2772*4882a593Smuzhiyun u32 cs_pst;
2773*4882a593Smuzhiyun u32 cs_add = 0;
2774*4882a593Smuzhiyun u32 max_row;
2775*4882a593Smuzhiyun
2776*4882a593Smuzhiyun if (cap_info->rank == 2) {
2777*4882a593Smuzhiyun cs_pst = (readl(pctl_base + DDR_PCTL2_ADDRMAP0) & 0x1f) +
2778*4882a593Smuzhiyun 6 + 2;
2779*4882a593Smuzhiyun if (cs_pst < 28)
2780*4882a593Smuzhiyun cs_add = 1;
2781*4882a593Smuzhiyun
2782*4882a593Smuzhiyun cs0_cap = 1 << cs_pst;
2783*4882a593Smuzhiyun
2784*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR4) {
2785*4882a593Smuzhiyun if (cap_info->dbw == 0)
2786*4882a593Smuzhiyun bktmp = cap_info->bk + 2;
2787*4882a593Smuzhiyun else
2788*4882a593Smuzhiyun bktmp = cap_info->bk + 1;
2789*4882a593Smuzhiyun } else {
2790*4882a593Smuzhiyun bktmp = cap_info->bk;
2791*4882a593Smuzhiyun }
2792*4882a593Smuzhiyun bw = cap_info->bw;
2793*4882a593Smuzhiyun coltmp = cap_info->col;
2794*4882a593Smuzhiyun
2795*4882a593Smuzhiyun if (bw == 2)
2796*4882a593Smuzhiyun byte_mask = 0xFFFF;
2797*4882a593Smuzhiyun else
2798*4882a593Smuzhiyun byte_mask = 0xFF;
2799*4882a593Smuzhiyun
2800*4882a593Smuzhiyun max_row = (cs_pst == 31) ? 30 : 31;
2801*4882a593Smuzhiyun
2802*4882a593Smuzhiyun max_row = max_row - bktmp - coltmp - bw - cs_add + 1;
2803*4882a593Smuzhiyun
2804*4882a593Smuzhiyun row = (cap_info->cs0_row > max_row) ? max_row :
2805*4882a593Smuzhiyun cap_info->cs0_row;
2806*4882a593Smuzhiyun
2807*4882a593Smuzhiyun for (; row > 12; row--) {
2808*4882a593Smuzhiyun test_addr = (void __iomem *)(CONFIG_SYS_SDRAM_BASE +
2809*4882a593Smuzhiyun (u32)cs0_cap +
2810*4882a593Smuzhiyun (1ul << (row + bktmp + coltmp +
2811*4882a593Smuzhiyun cs_add + bw - 1ul)));
2812*4882a593Smuzhiyun
2813*4882a593Smuzhiyun writel(0, CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap);
2814*4882a593Smuzhiyun writel(PATTERN, test_addr);
2815*4882a593Smuzhiyun
2816*4882a593Smuzhiyun if (((readl(test_addr) & byte_mask) ==
2817*4882a593Smuzhiyun (PATTERN & byte_mask)) &&
2818*4882a593Smuzhiyun ((readl(CONFIG_SYS_SDRAM_BASE + (u32)cs0_cap) &
2819*4882a593Smuzhiyun byte_mask) == 0)) {
2820*4882a593Smuzhiyun ret = row;
2821*4882a593Smuzhiyun break;
2822*4882a593Smuzhiyun }
2823*4882a593Smuzhiyun }
2824*4882a593Smuzhiyun }
2825*4882a593Smuzhiyun
2826*4882a593Smuzhiyun return ret;
2827*4882a593Smuzhiyun }
2828*4882a593Smuzhiyun
2829*4882a593Smuzhiyun /* return: 0 = success, other = fail */
sdram_init_detect(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)2830*4882a593Smuzhiyun static int sdram_init_detect(struct dram_info *dram,
2831*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
2832*4882a593Smuzhiyun {
2833*4882a593Smuzhiyun struct sdram_cap_info *cap_info = &sdram_params->ch.cap_info;
2834*4882a593Smuzhiyun u32 ret;
2835*4882a593Smuzhiyun u32 sys_reg = 0;
2836*4882a593Smuzhiyun u32 sys_reg3 = 0;
2837*4882a593Smuzhiyun
2838*4882a593Smuzhiyun if (sdram_init_(dram, sdram_params, 0)) {
2839*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR3) {
2840*4882a593Smuzhiyun if (sdram_init_(dram, sdram_params, 0))
2841*4882a593Smuzhiyun return -1;
2842*4882a593Smuzhiyun } else {
2843*4882a593Smuzhiyun return -1;
2844*4882a593Smuzhiyun }
2845*4882a593Smuzhiyun }
2846*4882a593Smuzhiyun
2847*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR3) {
2848*4882a593Smuzhiyun writel(PATTERN, CONFIG_SYS_SDRAM_BASE);
2849*4882a593Smuzhiyun if (readl(CONFIG_SYS_SDRAM_BASE) != PATTERN)
2850*4882a593Smuzhiyun return -1;
2851*4882a593Smuzhiyun }
2852*4882a593Smuzhiyun
2853*4882a593Smuzhiyun split_bypass(dram);
2854*4882a593Smuzhiyun if (dram_detect_cap(dram, sdram_params, 0) != 0)
2855*4882a593Smuzhiyun return -1;
2856*4882a593Smuzhiyun
2857*4882a593Smuzhiyun pctl_remodify_sdram_params(&sdram_params->pctl_regs, cap_info,
2858*4882a593Smuzhiyun sdram_params->base.dramtype);
2859*4882a593Smuzhiyun ret = sdram_init_(dram, sdram_params, 1);
2860*4882a593Smuzhiyun if (ret != 0)
2861*4882a593Smuzhiyun goto out;
2862*4882a593Smuzhiyun
2863*4882a593Smuzhiyun cap_info->cs1_row =
2864*4882a593Smuzhiyun dram_detect_cs1_row(dram, sdram_params, 0);
2865*4882a593Smuzhiyun if (cap_info->cs1_row) {
2866*4882a593Smuzhiyun sys_reg = readl(&dram->pmugrf->os_reg[2]);
2867*4882a593Smuzhiyun sys_reg3 = readl(&dram->pmugrf->os_reg[3]);
2868*4882a593Smuzhiyun SYS_REG_ENC_CS1_ROW(cap_info->cs1_row,
2869*4882a593Smuzhiyun sys_reg, sys_reg3, 0);
2870*4882a593Smuzhiyun writel(sys_reg, &dram->pmugrf->os_reg[2]);
2871*4882a593Smuzhiyun writel(sys_reg3, &dram->pmugrf->os_reg[3]);
2872*4882a593Smuzhiyun }
2873*4882a593Smuzhiyun
2874*4882a593Smuzhiyun sdram_detect_high_row(cap_info, sdram_params->base.dramtype);
2875*4882a593Smuzhiyun split_setup(dram, sdram_params);
2876*4882a593Smuzhiyun out:
2877*4882a593Smuzhiyun return ret;
2878*4882a593Smuzhiyun }
2879*4882a593Smuzhiyun
get_default_sdram_config(u32 freq_mhz)2880*4882a593Smuzhiyun struct rv1126_sdram_params *get_default_sdram_config(u32 freq_mhz)
2881*4882a593Smuzhiyun {
2882*4882a593Smuzhiyun u32 i;
2883*4882a593Smuzhiyun u32 offset = 0;
2884*4882a593Smuzhiyun struct ddr2_3_4_lp2_3_info *ddr_info;
2885*4882a593Smuzhiyun
2886*4882a593Smuzhiyun if (!freq_mhz) {
2887*4882a593Smuzhiyun ddr_info = get_ddr_drv_odt_info(sdram_configs[0].base.dramtype);
2888*4882a593Smuzhiyun if (ddr_info)
2889*4882a593Smuzhiyun freq_mhz =
2890*4882a593Smuzhiyun (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
2891*4882a593Smuzhiyun DDR_FREQ_MASK;
2892*4882a593Smuzhiyun else
2893*4882a593Smuzhiyun freq_mhz = 0;
2894*4882a593Smuzhiyun }
2895*4882a593Smuzhiyun
2896*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(sdram_configs); i++) {
2897*4882a593Smuzhiyun if (sdram_configs[i].base.ddr_freq == 0 ||
2898*4882a593Smuzhiyun freq_mhz < sdram_configs[i].base.ddr_freq)
2899*4882a593Smuzhiyun break;
2900*4882a593Smuzhiyun }
2901*4882a593Smuzhiyun offset = i == 0 ? 0 : i - 1;
2902*4882a593Smuzhiyun
2903*4882a593Smuzhiyun return &sdram_configs[offset];
2904*4882a593Smuzhiyun }
2905*4882a593Smuzhiyun
2906*4882a593Smuzhiyun static const u16 pctl_need_update_reg[] = {
2907*4882a593Smuzhiyun DDR_PCTL2_RFSHTMG,
2908*4882a593Smuzhiyun DDR_PCTL2_INIT3,
2909*4882a593Smuzhiyun DDR_PCTL2_INIT4,
2910*4882a593Smuzhiyun DDR_PCTL2_INIT6,
2911*4882a593Smuzhiyun DDR_PCTL2_INIT7,
2912*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG0,
2913*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG1,
2914*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG2,
2915*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG3,
2916*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG4,
2917*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG5,
2918*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG6,
2919*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG7,
2920*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG8,
2921*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG9,
2922*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG12,
2923*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG13,
2924*4882a593Smuzhiyun DDR_PCTL2_DRAMTMG14,
2925*4882a593Smuzhiyun DDR_PCTL2_ZQCTL0,
2926*4882a593Smuzhiyun DDR_PCTL2_DFITMG0,
2927*4882a593Smuzhiyun DDR_PCTL2_ODTCFG
2928*4882a593Smuzhiyun };
2929*4882a593Smuzhiyun
2930*4882a593Smuzhiyun static const u16 phy_need_update_reg[] = {
2931*4882a593Smuzhiyun 0x14,
2932*4882a593Smuzhiyun 0x18,
2933*4882a593Smuzhiyun 0x1c
2934*4882a593Smuzhiyun };
2935*4882a593Smuzhiyun
pre_set_rate(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 dst_fsp,u32 dst_fsp_lp4)2936*4882a593Smuzhiyun static void pre_set_rate(struct dram_info *dram,
2937*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params,
2938*4882a593Smuzhiyun u32 dst_fsp, u32 dst_fsp_lp4)
2939*4882a593Smuzhiyun {
2940*4882a593Smuzhiyun u32 i, j, find;
2941*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
2942*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
2943*4882a593Smuzhiyun u32 phy_offset;
2944*4882a593Smuzhiyun u32 mr_tmp;
2945*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
2946*4882a593Smuzhiyun
2947*4882a593Smuzhiyun sw_set_req(dram);
2948*4882a593Smuzhiyun /* pctl timing update */
2949*4882a593Smuzhiyun for (i = 0, find = 0; i < ARRAY_SIZE(pctl_need_update_reg); i++) {
2950*4882a593Smuzhiyun for (j = find; sdram_params->pctl_regs.pctl[j][0] != 0xFFFFFFFF;
2951*4882a593Smuzhiyun j++) {
2952*4882a593Smuzhiyun if (sdram_params->pctl_regs.pctl[j][0] ==
2953*4882a593Smuzhiyun pctl_need_update_reg[i]) {
2954*4882a593Smuzhiyun writel(sdram_params->pctl_regs.pctl[j][1],
2955*4882a593Smuzhiyun pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2956*4882a593Smuzhiyun pctl_need_update_reg[i]);
2957*4882a593Smuzhiyun find = j;
2958*4882a593Smuzhiyun break;
2959*4882a593Smuzhiyun }
2960*4882a593Smuzhiyun }
2961*4882a593Smuzhiyun }
2962*4882a593Smuzhiyun
2963*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
2964*4882a593Smuzhiyun u32 tmp, trefi;
2965*4882a593Smuzhiyun
2966*4882a593Smuzhiyun tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
2967*4882a593Smuzhiyun trefi = (tmp >> 16) & 0xfff;
2968*4882a593Smuzhiyun writel((tmp & 0xf000ffff) | (trefi / 2) << 16,
2969*4882a593Smuzhiyun pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_RFSHTMG);
2970*4882a593Smuzhiyun #endif
2971*4882a593Smuzhiyun
2972*4882a593Smuzhiyun sw_set_ack(dram);
2973*4882a593Smuzhiyun
2974*4882a593Smuzhiyun /* phy timing update */
2975*4882a593Smuzhiyun if (dst_fsp == 0)
2976*4882a593Smuzhiyun phy_offset = 0;
2977*4882a593Smuzhiyun else
2978*4882a593Smuzhiyun phy_offset = PHY_REG(0, 0x387 - 5 + (dst_fsp - 1) * 3);
2979*4882a593Smuzhiyun /* cl cwl al update */
2980*4882a593Smuzhiyun for (i = 0, find = 0; i < ARRAY_SIZE(phy_need_update_reg); i++) {
2981*4882a593Smuzhiyun for (j = find; sdram_params->phy_regs.phy[j][0] != 0xFFFFFFFF;
2982*4882a593Smuzhiyun j++) {
2983*4882a593Smuzhiyun if (sdram_params->phy_regs.phy[j][0] ==
2984*4882a593Smuzhiyun phy_need_update_reg[i]) {
2985*4882a593Smuzhiyun writel(sdram_params->phy_regs.phy[j][1],
2986*4882a593Smuzhiyun phy_base + phy_offset +
2987*4882a593Smuzhiyun phy_need_update_reg[i]);
2988*4882a593Smuzhiyun find = j;
2989*4882a593Smuzhiyun break;
2990*4882a593Smuzhiyun }
2991*4882a593Smuzhiyun }
2992*4882a593Smuzhiyun }
2993*4882a593Smuzhiyun
2994*4882a593Smuzhiyun set_ds_odt(dram, sdram_params, dst_fsp);
2995*4882a593Smuzhiyun if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
2996*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
2997*4882a593Smuzhiyun DDR_PCTL2_INIT4);
2998*4882a593Smuzhiyun /* MR13 */
2999*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 13,
3000*4882a593Smuzhiyun ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3001*4882a593Smuzhiyun PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
3002*4882a593Smuzhiyun ((0x2 << 6) >> dst_fsp_lp4), dramtype);
3003*4882a593Smuzhiyun writel(((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3004*4882a593Smuzhiyun PCTL2_MR_MASK) & (~(BIT(7) | BIT(6)))) |
3005*4882a593Smuzhiyun ((0x2 << 6) >> dst_fsp_lp4),
3006*4882a593Smuzhiyun PHY_REG(phy_base, 0x1b));
3007*4882a593Smuzhiyun /* MR3 */
3008*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 3,
3009*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT &
3010*4882a593Smuzhiyun PCTL2_MR_MASK,
3011*4882a593Smuzhiyun dramtype);
3012*4882a593Smuzhiyun writel(mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT & PCTL2_MR_MASK,
3013*4882a593Smuzhiyun PHY_REG(phy_base, 0x19));
3014*4882a593Smuzhiyun
3015*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3016*4882a593Smuzhiyun DDR_PCTL2_INIT3);
3017*4882a593Smuzhiyun /* MR1 */
3018*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 1,
3019*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT &
3020*4882a593Smuzhiyun PCTL2_MR_MASK,
3021*4882a593Smuzhiyun dramtype);
3022*4882a593Smuzhiyun writel(mr_tmp >> PCTL2_LPDDR234_MR1_SHIFT & PCTL2_MR_MASK,
3023*4882a593Smuzhiyun PHY_REG(phy_base, 0x17));
3024*4882a593Smuzhiyun /* MR2 */
3025*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 2, mr_tmp & PCTL2_MR_MASK,
3026*4882a593Smuzhiyun dramtype);
3027*4882a593Smuzhiyun writel(mr_tmp & PCTL2_MR_MASK,
3028*4882a593Smuzhiyun PHY_REG(phy_base, 0x18));
3029*4882a593Smuzhiyun
3030*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3031*4882a593Smuzhiyun DDR_PCTL2_INIT6);
3032*4882a593Smuzhiyun /* MR11 */
3033*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 11,
3034*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
3035*4882a593Smuzhiyun dramtype);
3036*4882a593Smuzhiyun writel(mr_tmp >> PCTL2_LPDDR4_MR11_SHIFT & PCTL2_MR_MASK,
3037*4882a593Smuzhiyun PHY_REG(phy_base, 0x1a));
3038*4882a593Smuzhiyun /* MR12 */
3039*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 12,
3040*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR12_SHIFT & PCTL2_MR_MASK,
3041*4882a593Smuzhiyun dramtype);
3042*4882a593Smuzhiyun
3043*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3044*4882a593Smuzhiyun DDR_PCTL2_INIT7);
3045*4882a593Smuzhiyun /* MR22 */
3046*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 22,
3047*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
3048*4882a593Smuzhiyun dramtype);
3049*4882a593Smuzhiyun writel(mr_tmp >> PCTL2_LPDDR4_MR22_SHIFT & PCTL2_MR_MASK,
3050*4882a593Smuzhiyun PHY_REG(phy_base, 0x1d));
3051*4882a593Smuzhiyun /* MR14 */
3052*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 14,
3053*4882a593Smuzhiyun mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
3054*4882a593Smuzhiyun dramtype);
3055*4882a593Smuzhiyun writel(mr_tmp >> PCTL2_LPDDR4_MR14_SHIFT & PCTL2_MR_MASK,
3056*4882a593Smuzhiyun PHY_REG(phy_base, 0x1c));
3057*4882a593Smuzhiyun }
3058*4882a593Smuzhiyun
3059*4882a593Smuzhiyun update_noc_timing(dram, sdram_params);
3060*4882a593Smuzhiyun }
3061*4882a593Smuzhiyun
save_fsp_param(struct dram_info * dram,u32 dst_fsp,struct rv1126_sdram_params * sdram_params)3062*4882a593Smuzhiyun static void save_fsp_param(struct dram_info *dram, u32 dst_fsp,
3063*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
3064*4882a593Smuzhiyun {
3065*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
3066*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
3067*4882a593Smuzhiyun struct rv1126_fsp_param *p_fsp_param = &fsp_param[dst_fsp];
3068*4882a593Smuzhiyun u32 temp, temp1;
3069*4882a593Smuzhiyun struct ddr2_3_4_lp2_3_info *ddr_info;
3070*4882a593Smuzhiyun
3071*4882a593Smuzhiyun ddr_info = get_ddr_drv_odt_info(sdram_params->base.dramtype);
3072*4882a593Smuzhiyun
3073*4882a593Smuzhiyun p_fsp_param->freq_mhz = sdram_params->base.ddr_freq;
3074*4882a593Smuzhiyun
3075*4882a593Smuzhiyun if (sdram_params->base.dramtype == LPDDR4 ||
3076*4882a593Smuzhiyun sdram_params->base.dramtype == LPDDR4X) {
3077*4882a593Smuzhiyun p_fsp_param->rd_odt_up_en = 0;
3078*4882a593Smuzhiyun p_fsp_param->rd_odt_down_en = 1;
3079*4882a593Smuzhiyun } else {
3080*4882a593Smuzhiyun p_fsp_param->rd_odt_up_en =
3081*4882a593Smuzhiyun ODT_INFO_PULLUP_EN(ddr_info->odt_info);
3082*4882a593Smuzhiyun p_fsp_param->rd_odt_down_en =
3083*4882a593Smuzhiyun ODT_INFO_PULLDOWN_EN(ddr_info->odt_info);
3084*4882a593Smuzhiyun }
3085*4882a593Smuzhiyun
3086*4882a593Smuzhiyun if (p_fsp_param->rd_odt_up_en)
3087*4882a593Smuzhiyun p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x111));
3088*4882a593Smuzhiyun else if (p_fsp_param->rd_odt_down_en)
3089*4882a593Smuzhiyun p_fsp_param->rd_odt = readl(PHY_REG(phy_base, 0x110));
3090*4882a593Smuzhiyun else
3091*4882a593Smuzhiyun p_fsp_param->rd_odt = 0;
3092*4882a593Smuzhiyun p_fsp_param->wr_dq_drv = readl(PHY_REG(phy_base, 0x112));
3093*4882a593Smuzhiyun p_fsp_param->wr_ca_drv = readl(PHY_REG(phy_base, 0x100));
3094*4882a593Smuzhiyun p_fsp_param->wr_ckcs_drv = readl(PHY_REG(phy_base, 0x102));
3095*4882a593Smuzhiyun p_fsp_param->vref_inner = readl(PHY_REG(phy_base, 0x128));
3096*4882a593Smuzhiyun p_fsp_param->vref_out = readl(PHY_REG(phy_base, 0x105));
3097*4882a593Smuzhiyun
3098*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR3) {
3099*4882a593Smuzhiyun temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3100*4882a593Smuzhiyun DDR_PCTL2_INIT3);
3101*4882a593Smuzhiyun temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
3102*4882a593Smuzhiyun p_fsp_param->ds_pdds = temp & DDR3_DS_MASK;
3103*4882a593Smuzhiyun p_fsp_param->dq_odt = temp & DDR3_RTT_NOM_MASK;
3104*4882a593Smuzhiyun p_fsp_param->ca_odt = p_fsp_param->dq_odt;
3105*4882a593Smuzhiyun } else if (sdram_params->base.dramtype == DDR4) {
3106*4882a593Smuzhiyun temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3107*4882a593Smuzhiyun DDR_PCTL2_INIT3);
3108*4882a593Smuzhiyun temp = (temp >> PCTL2_DDR34_MR1_SHIFT) & PCTL2_MR_MASK;
3109*4882a593Smuzhiyun p_fsp_param->ds_pdds = temp & DDR4_DS_MASK;
3110*4882a593Smuzhiyun p_fsp_param->dq_odt = temp & DDR4_RTT_NOM_MASK;
3111*4882a593Smuzhiyun p_fsp_param->ca_odt = p_fsp_param->dq_odt;
3112*4882a593Smuzhiyun } else if (sdram_params->base.dramtype == LPDDR3) {
3113*4882a593Smuzhiyun temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3114*4882a593Smuzhiyun DDR_PCTL2_INIT4);
3115*4882a593Smuzhiyun temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
3116*4882a593Smuzhiyun p_fsp_param->ds_pdds = temp & 0xf;
3117*4882a593Smuzhiyun
3118*4882a593Smuzhiyun p_fsp_param->dq_odt = lp3_odt_value;
3119*4882a593Smuzhiyun p_fsp_param->ca_odt = p_fsp_param->dq_odt;
3120*4882a593Smuzhiyun } else if (sdram_params->base.dramtype == LPDDR4 ||
3121*4882a593Smuzhiyun sdram_params->base.dramtype == LPDDR4X) {
3122*4882a593Smuzhiyun temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3123*4882a593Smuzhiyun DDR_PCTL2_INIT4);
3124*4882a593Smuzhiyun temp = (temp >> PCTL2_LPDDR234_MR3_SHIFT) & PCTL2_MR_MASK;
3125*4882a593Smuzhiyun p_fsp_param->ds_pdds = temp & LPDDR4_PDDS_MASK;
3126*4882a593Smuzhiyun
3127*4882a593Smuzhiyun temp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3128*4882a593Smuzhiyun DDR_PCTL2_INIT6);
3129*4882a593Smuzhiyun temp = (temp >> PCTL2_LPDDR4_MR11_SHIFT) & PCTL2_MR_MASK;
3130*4882a593Smuzhiyun p_fsp_param->dq_odt = temp & LPDDR4_DQODT_MASK;
3131*4882a593Smuzhiyun p_fsp_param->ca_odt = temp & LPDDR4_CAODT_MASK;
3132*4882a593Smuzhiyun
3133*4882a593Smuzhiyun temp = MAX(readl(PHY_REG(phy_base, 0x3ae)),
3134*4882a593Smuzhiyun readl(PHY_REG(phy_base, 0x3ce)));
3135*4882a593Smuzhiyun temp1 = MIN(readl(PHY_REG(phy_base, 0x3be)),
3136*4882a593Smuzhiyun readl(PHY_REG(phy_base, 0x3de)));
3137*4882a593Smuzhiyun p_fsp_param->vref_ca[0] = (temp + temp1) / 2;
3138*4882a593Smuzhiyun temp = MAX(readl(PHY_REG(phy_base, 0x3af)),
3139*4882a593Smuzhiyun readl(PHY_REG(phy_base, 0x3cf)));
3140*4882a593Smuzhiyun temp1 = MIN(readl(PHY_REG(phy_base, 0x3bf)),
3141*4882a593Smuzhiyun readl(PHY_REG(phy_base, 0x3df)));
3142*4882a593Smuzhiyun p_fsp_param->vref_ca[1] = (temp + temp1) / 2;
3143*4882a593Smuzhiyun p_fsp_param->vref_ca[0] |=
3144*4882a593Smuzhiyun (readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
3145*4882a593Smuzhiyun p_fsp_param->vref_ca[1] |=
3146*4882a593Smuzhiyun (readl(PHY_REG(phy_base, 0x1e)) & BIT(6));
3147*4882a593Smuzhiyun
3148*4882a593Smuzhiyun p_fsp_param->lp4_drv_pd_en = (readl(PHY_REG(phy_base, 0x114)) >>
3149*4882a593Smuzhiyun 3) & 0x1;
3150*4882a593Smuzhiyun }
3151*4882a593Smuzhiyun
3152*4882a593Smuzhiyun p_fsp_param->noc_timings.ddrtiminga0 =
3153*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrtiminga0;
3154*4882a593Smuzhiyun p_fsp_param->noc_timings.ddrtimingb0 =
3155*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrtimingb0;
3156*4882a593Smuzhiyun p_fsp_param->noc_timings.ddrtimingc0 =
3157*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrtimingc0;
3158*4882a593Smuzhiyun p_fsp_param->noc_timings.devtodev0 =
3159*4882a593Smuzhiyun sdram_params->ch.noc_timings.devtodev0;
3160*4882a593Smuzhiyun p_fsp_param->noc_timings.ddrmode =
3161*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddrmode;
3162*4882a593Smuzhiyun p_fsp_param->noc_timings.ddr4timing =
3163*4882a593Smuzhiyun sdram_params->ch.noc_timings.ddr4timing;
3164*4882a593Smuzhiyun p_fsp_param->noc_timings.agingx0 =
3165*4882a593Smuzhiyun sdram_params->ch.noc_timings.agingx0;
3166*4882a593Smuzhiyun p_fsp_param->noc_timings.aging0 =
3167*4882a593Smuzhiyun sdram_params->ch.noc_timings.aging0;
3168*4882a593Smuzhiyun p_fsp_param->noc_timings.aging1 =
3169*4882a593Smuzhiyun sdram_params->ch.noc_timings.aging1;
3170*4882a593Smuzhiyun p_fsp_param->noc_timings.aging2 =
3171*4882a593Smuzhiyun sdram_params->ch.noc_timings.aging2;
3172*4882a593Smuzhiyun p_fsp_param->noc_timings.aging3 =
3173*4882a593Smuzhiyun sdram_params->ch.noc_timings.aging3;
3174*4882a593Smuzhiyun
3175*4882a593Smuzhiyun p_fsp_param->flag = FSP_FLAG;
3176*4882a593Smuzhiyun }
3177*4882a593Smuzhiyun
3178*4882a593Smuzhiyun #ifndef CONFIG_SPL_KERNEL_BOOT
copy_fsp_param_to_ddr(void)3179*4882a593Smuzhiyun static void copy_fsp_param_to_ddr(void)
3180*4882a593Smuzhiyun {
3181*4882a593Smuzhiyun memcpy((void *)FSP_PARAM_STORE_ADDR, (void *)&fsp_param,
3182*4882a593Smuzhiyun sizeof(fsp_param));
3183*4882a593Smuzhiyun }
3184*4882a593Smuzhiyun #endif
3185*4882a593Smuzhiyun
pctl_modify_trfc(struct ddr_pctl_regs * pctl_regs,struct sdram_cap_info * cap_info,u32 dram_type,u32 freq)3186*4882a593Smuzhiyun static void pctl_modify_trfc(struct ddr_pctl_regs *pctl_regs,
3187*4882a593Smuzhiyun struct sdram_cap_info *cap_info, u32 dram_type,
3188*4882a593Smuzhiyun u32 freq)
3189*4882a593Smuzhiyun {
3190*4882a593Smuzhiyun u64 cs0_cap;
3191*4882a593Smuzhiyun u32 die_cap;
3192*4882a593Smuzhiyun u32 trfc_ns, trfc4_ns;
3193*4882a593Smuzhiyun u32 trfc, txsnr;
3194*4882a593Smuzhiyun u32 txs_abort_fast = 0;
3195*4882a593Smuzhiyun u32 tmp;
3196*4882a593Smuzhiyun
3197*4882a593Smuzhiyun cs0_cap = sdram_get_cs_cap(cap_info, 0, dram_type);
3198*4882a593Smuzhiyun die_cap = (u32)(cs0_cap >> (20 + (cap_info->bw - cap_info->dbw)));
3199*4882a593Smuzhiyun
3200*4882a593Smuzhiyun switch (dram_type) {
3201*4882a593Smuzhiyun case DDR3:
3202*4882a593Smuzhiyun if (die_cap <= DIE_CAP_512MBIT)
3203*4882a593Smuzhiyun trfc_ns = 90;
3204*4882a593Smuzhiyun else if (die_cap <= DIE_CAP_1GBIT)
3205*4882a593Smuzhiyun trfc_ns = 110;
3206*4882a593Smuzhiyun else if (die_cap <= DIE_CAP_2GBIT)
3207*4882a593Smuzhiyun trfc_ns = 160;
3208*4882a593Smuzhiyun else if (die_cap <= DIE_CAP_4GBIT)
3209*4882a593Smuzhiyun trfc_ns = 260;
3210*4882a593Smuzhiyun else
3211*4882a593Smuzhiyun trfc_ns = 350;
3212*4882a593Smuzhiyun txsnr = MAX(5, ((trfc_ns + 10) * freq + 999) / 1000);
3213*4882a593Smuzhiyun break;
3214*4882a593Smuzhiyun
3215*4882a593Smuzhiyun case DDR4:
3216*4882a593Smuzhiyun if (die_cap <= DIE_CAP_2GBIT) {
3217*4882a593Smuzhiyun trfc_ns = 160;
3218*4882a593Smuzhiyun trfc4_ns = 90;
3219*4882a593Smuzhiyun } else if (die_cap <= DIE_CAP_4GBIT) {
3220*4882a593Smuzhiyun trfc_ns = 260;
3221*4882a593Smuzhiyun trfc4_ns = 110;
3222*4882a593Smuzhiyun } else if (die_cap <= DIE_CAP_8GBIT) {
3223*4882a593Smuzhiyun trfc_ns = 350;
3224*4882a593Smuzhiyun trfc4_ns = 160;
3225*4882a593Smuzhiyun } else {
3226*4882a593Smuzhiyun trfc_ns = 550;
3227*4882a593Smuzhiyun trfc4_ns = 260;
3228*4882a593Smuzhiyun }
3229*4882a593Smuzhiyun txsnr = ((trfc_ns + 10) * freq + 999) / 1000;
3230*4882a593Smuzhiyun txs_abort_fast = ((trfc4_ns + 10) * freq + 999) / 1000;
3231*4882a593Smuzhiyun break;
3232*4882a593Smuzhiyun
3233*4882a593Smuzhiyun case LPDDR3:
3234*4882a593Smuzhiyun if (die_cap <= DIE_CAP_4GBIT)
3235*4882a593Smuzhiyun trfc_ns = 130;
3236*4882a593Smuzhiyun else
3237*4882a593Smuzhiyun trfc_ns = 210;
3238*4882a593Smuzhiyun txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
3239*4882a593Smuzhiyun break;
3240*4882a593Smuzhiyun
3241*4882a593Smuzhiyun case LPDDR4:
3242*4882a593Smuzhiyun case LPDDR4X:
3243*4882a593Smuzhiyun if (die_cap <= DIE_CAP_2GBIT)
3244*4882a593Smuzhiyun trfc_ns = 130;
3245*4882a593Smuzhiyun else if (die_cap <= DIE_CAP_4GBIT)
3246*4882a593Smuzhiyun trfc_ns = 180;
3247*4882a593Smuzhiyun else if (die_cap <= DIE_CAP_8GBIT)
3248*4882a593Smuzhiyun trfc_ns = 280;
3249*4882a593Smuzhiyun else
3250*4882a593Smuzhiyun trfc_ns = 380;
3251*4882a593Smuzhiyun txsnr = MAX(2, ((trfc_ns + 10) * freq + 999) / 1000);
3252*4882a593Smuzhiyun break;
3253*4882a593Smuzhiyun
3254*4882a593Smuzhiyun default:
3255*4882a593Smuzhiyun return;
3256*4882a593Smuzhiyun }
3257*4882a593Smuzhiyun trfc = (trfc_ns * freq + 999) / 1000;
3258*4882a593Smuzhiyun
3259*4882a593Smuzhiyun for (int i = 0; pctl_regs->pctl[i][0] != 0xffffffff; i++) {
3260*4882a593Smuzhiyun switch (pctl_regs->pctl[i][0]) {
3261*4882a593Smuzhiyun case DDR_PCTL2_RFSHTMG:
3262*4882a593Smuzhiyun tmp = pctl_regs->pctl[i][1];
3263*4882a593Smuzhiyun /* t_rfc_min */
3264*4882a593Smuzhiyun tmp &= ~((u32)0x3ff);
3265*4882a593Smuzhiyun tmp |= ((trfc + 1) / 2) & 0x3ff;
3266*4882a593Smuzhiyun pctl_regs->pctl[i][1] = tmp;
3267*4882a593Smuzhiyun break;
3268*4882a593Smuzhiyun
3269*4882a593Smuzhiyun case DDR_PCTL2_DRAMTMG8:
3270*4882a593Smuzhiyun if (dram_type == DDR3 || dram_type == DDR4) {
3271*4882a593Smuzhiyun tmp = pctl_regs->pctl[i][1];
3272*4882a593Smuzhiyun /* t_xs_x32 */
3273*4882a593Smuzhiyun tmp &= ~((u32)0x7f);
3274*4882a593Smuzhiyun tmp |= ((txsnr + 63) / 64 + 1) & 0x7f;
3275*4882a593Smuzhiyun
3276*4882a593Smuzhiyun if (dram_type == DDR4) {
3277*4882a593Smuzhiyun /* t_xs_abort_x32 */
3278*4882a593Smuzhiyun tmp &= ~((u32)(0x7f << 16));
3279*4882a593Smuzhiyun tmp |= (((txs_abort_fast + 63) / 64 + 1) & 0x7f) << 16;
3280*4882a593Smuzhiyun /* t_xs_fast_x32 */
3281*4882a593Smuzhiyun tmp &= ~((u32)(0x7f << 24));
3282*4882a593Smuzhiyun tmp |= (((txs_abort_fast + 63) / 64 + 1) & 0x7f) << 24;
3283*4882a593Smuzhiyun }
3284*4882a593Smuzhiyun
3285*4882a593Smuzhiyun pctl_regs->pctl[i][1] = tmp;
3286*4882a593Smuzhiyun }
3287*4882a593Smuzhiyun break;
3288*4882a593Smuzhiyun
3289*4882a593Smuzhiyun case DDR_PCTL2_DRAMTMG14:
3290*4882a593Smuzhiyun if (dram_type == LPDDR3 ||
3291*4882a593Smuzhiyun dram_type == LPDDR4 || dram_type == LPDDR4X) {
3292*4882a593Smuzhiyun tmp = pctl_regs->pctl[i][1];
3293*4882a593Smuzhiyun /* t_xsr */
3294*4882a593Smuzhiyun tmp &= ~((u32)0xfff);
3295*4882a593Smuzhiyun tmp |= ((txsnr + 1) / 2) & 0xfff;
3296*4882a593Smuzhiyun pctl_regs->pctl[i][1] = tmp;
3297*4882a593Smuzhiyun }
3298*4882a593Smuzhiyun break;
3299*4882a593Smuzhiyun
3300*4882a593Smuzhiyun default:
3301*4882a593Smuzhiyun break;
3302*4882a593Smuzhiyun }
3303*4882a593Smuzhiyun }
3304*4882a593Smuzhiyun }
3305*4882a593Smuzhiyun
ddr_set_rate(struct dram_info * dram,struct rv1126_sdram_params * sdram_params,u32 freq,u32 cur_freq,u32 dst_fsp,u32 dst_fsp_lp4,u32 training_en)3306*4882a593Smuzhiyun void ddr_set_rate(struct dram_info *dram,
3307*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params,
3308*4882a593Smuzhiyun u32 freq, u32 cur_freq, u32 dst_fsp,
3309*4882a593Smuzhiyun u32 dst_fsp_lp4, u32 training_en)
3310*4882a593Smuzhiyun {
3311*4882a593Smuzhiyun u32 dest_dll_off, cur_init3, dst_init3, cur_fsp, cur_dll_off;
3312*4882a593Smuzhiyun u32 mr_tmp;
3313*4882a593Smuzhiyun u32 lp_stat;
3314*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
3315*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params_new;
3316*4882a593Smuzhiyun void __iomem *pctl_base = dram->pctl;
3317*4882a593Smuzhiyun void __iomem *phy_base = dram->phy;
3318*4882a593Smuzhiyun int delay = 1000;
3319*4882a593Smuzhiyun
3320*4882a593Smuzhiyun lp_stat = low_power_update(dram, 0);
3321*4882a593Smuzhiyun sdram_params_new = get_default_sdram_config(freq);
3322*4882a593Smuzhiyun sdram_params_new->ch.cap_info.rank = sdram_params->ch.cap_info.rank;
3323*4882a593Smuzhiyun sdram_params_new->ch.cap_info.bw = sdram_params->ch.cap_info.bw;
3324*4882a593Smuzhiyun
3325*4882a593Smuzhiyun pctl_modify_trfc(&sdram_params_new->pctl_regs,
3326*4882a593Smuzhiyun &sdram_params->ch.cap_info, dramtype, freq);
3327*4882a593Smuzhiyun pre_set_rate(dram, sdram_params_new, dst_fsp, dst_fsp_lp4);
3328*4882a593Smuzhiyun
3329*4882a593Smuzhiyun while ((readl(pctl_base + DDR_PCTL2_STAT) &
3330*4882a593Smuzhiyun PCTL2_OPERATING_MODE_MASK) ==
3331*4882a593Smuzhiyun PCTL2_OPERATING_MODE_SR)
3332*4882a593Smuzhiyun continue;
3333*4882a593Smuzhiyun
3334*4882a593Smuzhiyun dest_dll_off = 0;
3335*4882a593Smuzhiyun dst_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3336*4882a593Smuzhiyun DDR_PCTL2_INIT3);
3337*4882a593Smuzhiyun if ((dramtype == DDR3 && (dst_init3 & 1)) ||
3338*4882a593Smuzhiyun (dramtype == DDR4 && !(dst_init3 & 1)))
3339*4882a593Smuzhiyun dest_dll_off = 1;
3340*4882a593Smuzhiyun
3341*4882a593Smuzhiyun cur_fsp = readl(pctl_base + DDR_PCTL2_MSTR2) & 0x3;
3342*4882a593Smuzhiyun cur_init3 = readl(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) +
3343*4882a593Smuzhiyun DDR_PCTL2_INIT3);
3344*4882a593Smuzhiyun cur_init3 &= PCTL2_MR_MASK;
3345*4882a593Smuzhiyun cur_dll_off = 1;
3346*4882a593Smuzhiyun if ((dramtype == DDR3 && !(cur_init3 & 1)) ||
3347*4882a593Smuzhiyun (dramtype == DDR4 && (cur_init3 & 1)))
3348*4882a593Smuzhiyun cur_dll_off = 0;
3349*4882a593Smuzhiyun
3350*4882a593Smuzhiyun if (!cur_dll_off) {
3351*4882a593Smuzhiyun if (dramtype == DDR3)
3352*4882a593Smuzhiyun cur_init3 |= 1;
3353*4882a593Smuzhiyun else
3354*4882a593Smuzhiyun cur_init3 &= ~1;
3355*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 2, 1, cur_init3, dramtype);
3356*4882a593Smuzhiyun }
3357*4882a593Smuzhiyun
3358*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
3359*4882a593Smuzhiyun PCTL2_DIS_AUTO_REFRESH);
3360*4882a593Smuzhiyun update_refresh_reg(dram);
3361*4882a593Smuzhiyun
3362*4882a593Smuzhiyun enter_sr(dram, 1);
3363*4882a593Smuzhiyun
3364*4882a593Smuzhiyun writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
3365*4882a593Smuzhiyun PMUGRF_CON_DDRPHY_BUFFEREN_EN,
3366*4882a593Smuzhiyun &dram->pmugrf->soc_con[0]);
3367*4882a593Smuzhiyun sw_set_req(dram);
3368*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_DFIMISC,
3369*4882a593Smuzhiyun PCTL2_DFI_INIT_COMPLETE_EN);
3370*4882a593Smuzhiyun sw_set_ack(dram);
3371*4882a593Smuzhiyun
3372*4882a593Smuzhiyun sw_set_req(dram);
3373*4882a593Smuzhiyun if ((dramtype == DDR3 || dramtype == DDR4) && dest_dll_off)
3374*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
3375*4882a593Smuzhiyun else
3376*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_MSTR, PCTL2_DLL_OFF_MODE);
3377*4882a593Smuzhiyun
3378*4882a593Smuzhiyun setbits_le32(pctl_base + UMCTL2_REGS_FREQ(cur_fsp) + DDR_PCTL2_ZQCTL0,
3379*4882a593Smuzhiyun PCTL2_DIS_SRX_ZQCL);
3380*4882a593Smuzhiyun setbits_le32(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_ZQCTL0,
3381*4882a593Smuzhiyun PCTL2_DIS_SRX_ZQCL);
3382*4882a593Smuzhiyun sw_set_ack(dram);
3383*4882a593Smuzhiyun
3384*4882a593Smuzhiyun writel(DDR_MSCH_EN_MASK | (0x1 << DDR_MSCH_EN_SHIFT),
3385*4882a593Smuzhiyun &dram->cru->clkgate_con[21]);
3386*4882a593Smuzhiyun writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
3387*4882a593Smuzhiyun (0x1 << CLK_DDR_UPCTL_EN_SHIFT) |
3388*4882a593Smuzhiyun (0x1 << ACLK_DDR_UPCTL_EN_SHIFT),
3389*4882a593Smuzhiyun BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
3390*4882a593Smuzhiyun
3391*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
3392*4882a593Smuzhiyun rkclk_set_dpll(dram, freq * MHz / 2);
3393*4882a593Smuzhiyun phy_pll_set(dram, freq * MHz, 0);
3394*4882a593Smuzhiyun phy_pll_set(dram, freq * MHz, 1);
3395*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0), ANALOG_DERESET | DIGITAL_DERESET);
3396*4882a593Smuzhiyun
3397*4882a593Smuzhiyun writel(PMUGRF_CON_DDRPHY_BUFFEREN_MASK |
3398*4882a593Smuzhiyun PMUGRF_CON_DDRPHY_BUFFEREN_DIS,
3399*4882a593Smuzhiyun &dram->pmugrf->soc_con[0]);
3400*4882a593Smuzhiyun writel(DDR_MSCH_EN_MASK | (0x0 << DDR_MSCH_EN_SHIFT),
3401*4882a593Smuzhiyun &dram->cru->clkgate_con[21]);
3402*4882a593Smuzhiyun writel(CLK_DDR_UPCTL_EN_MASK | ACLK_DDR_UPCTL_EN_MASK |
3403*4882a593Smuzhiyun (0x0 << CLK_DDR_UPCTL_EN_SHIFT) |
3404*4882a593Smuzhiyun (0x0 << ACLK_DDR_UPCTL_EN_SHIFT),
3405*4882a593Smuzhiyun BUS_SGRF_BASE_ADDR + SGRF_SOC_CON12);
3406*4882a593Smuzhiyun while ((readl(pctl_base + DDR_PCTL2_DFISTAT) &
3407*4882a593Smuzhiyun PCTL2_DFI_INIT_COMPLETE) != PCTL2_DFI_INIT_COMPLETE) {
3408*4882a593Smuzhiyun udelay(1);
3409*4882a593Smuzhiyun if (delay-- <= 0) {
3410*4882a593Smuzhiyun printascii("ERROR: Cannot wait DFI_INIT_COMPLETE\n");
3411*4882a593Smuzhiyun while (1)
3412*4882a593Smuzhiyun ;
3413*4882a593Smuzhiyun }
3414*4882a593Smuzhiyun }
3415*4882a593Smuzhiyun
3416*4882a593Smuzhiyun sw_set_req(dram);
3417*4882a593Smuzhiyun setbits_le32(pctl_base + DDR_PCTL2_MSTR, 0x1 << 29);
3418*4882a593Smuzhiyun clrsetbits_le32(pctl_base + DDR_PCTL2_MSTR2, 0x3, dst_fsp);
3419*4882a593Smuzhiyun sw_set_ack(dram);
3420*4882a593Smuzhiyun update_refresh_reg(dram);
3421*4882a593Smuzhiyun clrsetbits_le32(PHY_REG(phy_base, 0xc), 0x3 << 2, dst_fsp << 2);
3422*4882a593Smuzhiyun
3423*4882a593Smuzhiyun enter_sr(dram, 0);
3424*4882a593Smuzhiyun
3425*4882a593Smuzhiyun setbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
3426*4882a593Smuzhiyun clrbits_le32(PHY_REG(phy_base, 0x71), 1 << 5);
3427*4882a593Smuzhiyun
3428*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) + DDR_PCTL2_INIT4);
3429*4882a593Smuzhiyun if (dramtype == LPDDR3) {
3430*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 1,
3431*4882a593Smuzhiyun (dst_init3 >> PCTL2_LPDDR234_MR1_SHIFT) &
3432*4882a593Smuzhiyun PCTL2_MR_MASK,
3433*4882a593Smuzhiyun dramtype);
3434*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 2, dst_init3 & PCTL2_MR_MASK,
3435*4882a593Smuzhiyun dramtype);
3436*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 3,
3437*4882a593Smuzhiyun (mr_tmp >> PCTL2_LPDDR234_MR3_SHIFT) &
3438*4882a593Smuzhiyun PCTL2_MR_MASK,
3439*4882a593Smuzhiyun dramtype);
3440*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 11, lp3_odt_value, dramtype);
3441*4882a593Smuzhiyun } else if ((dramtype == DDR3) || (dramtype == DDR4)) {
3442*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 1, dst_init3 & PCTL2_MR_MASK,
3443*4882a593Smuzhiyun dramtype);
3444*4882a593Smuzhiyun if (!dest_dll_off) {
3445*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 0,
3446*4882a593Smuzhiyun ((dst_init3 >> PCTL2_DDR34_MR0_SHIFT) &
3447*4882a593Smuzhiyun PCTL2_MR_MASK) | DDR3_DLL_RESET,
3448*4882a593Smuzhiyun dramtype);
3449*4882a593Smuzhiyun udelay(2);
3450*4882a593Smuzhiyun }
3451*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 0,
3452*4882a593Smuzhiyun (dst_init3 >> PCTL2_DDR34_MR0_SHIFT &
3453*4882a593Smuzhiyun PCTL2_MR_MASK) & (~DDR3_DLL_RESET),
3454*4882a593Smuzhiyun dramtype);
3455*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 2,
3456*4882a593Smuzhiyun ((mr_tmp >> PCTL2_DDR34_MR2_SHIFT) &
3457*4882a593Smuzhiyun PCTL2_MR_MASK), dramtype);
3458*4882a593Smuzhiyun if (dramtype == DDR4) {
3459*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 3, mr_tmp & PCTL2_MR_MASK,
3460*4882a593Smuzhiyun dramtype);
3461*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3462*4882a593Smuzhiyun DDR_PCTL2_INIT6);
3463*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 4,
3464*4882a593Smuzhiyun (mr_tmp >> PCTL2_DDR4_MR4_SHIFT) &
3465*4882a593Smuzhiyun PCTL2_MR_MASK,
3466*4882a593Smuzhiyun dramtype);
3467*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 5,
3468*4882a593Smuzhiyun mr_tmp >> PCTL2_DDR4_MR5_SHIFT &
3469*4882a593Smuzhiyun PCTL2_MR_MASK,
3470*4882a593Smuzhiyun dramtype);
3471*4882a593Smuzhiyun
3472*4882a593Smuzhiyun mr_tmp = readl(pctl_base + UMCTL2_REGS_FREQ(dst_fsp) +
3473*4882a593Smuzhiyun DDR_PCTL2_INIT7);
3474*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 6,
3475*4882a593Smuzhiyun mr_tmp >> PCTL2_DDR4_MR6_SHIFT &
3476*4882a593Smuzhiyun PCTL2_MR_MASK,
3477*4882a593Smuzhiyun dramtype);
3478*4882a593Smuzhiyun }
3479*4882a593Smuzhiyun } else if (dramtype == LPDDR4 || dramtype == LPDDR4X) {
3480*4882a593Smuzhiyun pctl_write_mr(dram->pctl, 3, 13,
3481*4882a593Smuzhiyun ((mr_tmp >> PCTL2_LPDDR4_MR13_SHIFT &
3482*4882a593Smuzhiyun PCTL2_MR_MASK) & (~(BIT(7)))) |
3483*4882a593Smuzhiyun dst_fsp_lp4 << 7, dramtype);
3484*4882a593Smuzhiyun }
3485*4882a593Smuzhiyun clrbits_le32(pctl_base + DDR_PCTL2_RFSHCTL3,
3486*4882a593Smuzhiyun PCTL2_DIS_AUTO_REFRESH);
3487*4882a593Smuzhiyun update_refresh_reg(dram);
3488*4882a593Smuzhiyun
3489*4882a593Smuzhiyun /* training */
3490*4882a593Smuzhiyun high_freq_training(dram, sdram_params_new, dst_fsp);
3491*4882a593Smuzhiyun low_power_update(dram, lp_stat);
3492*4882a593Smuzhiyun
3493*4882a593Smuzhiyun save_fsp_param(dram, dst_fsp, sdram_params_new);
3494*4882a593Smuzhiyun }
3495*4882a593Smuzhiyun
ddr_set_rate_for_fsp(struct dram_info * dram,struct rv1126_sdram_params * sdram_params)3496*4882a593Smuzhiyun static void ddr_set_rate_for_fsp(struct dram_info *dram,
3497*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params)
3498*4882a593Smuzhiyun {
3499*4882a593Smuzhiyun struct ddr2_3_4_lp2_3_info *ddr_info;
3500*4882a593Smuzhiyun u32 f0;
3501*4882a593Smuzhiyun u32 dramtype = sdram_params->base.dramtype;
3502*4882a593Smuzhiyun #ifndef CONFIG_SPL_KERNEL_BOOT
3503*4882a593Smuzhiyun u32 f1, f2, f3;
3504*4882a593Smuzhiyun #endif
3505*4882a593Smuzhiyun
3506*4882a593Smuzhiyun ddr_info = get_ddr_drv_odt_info(dramtype);
3507*4882a593Smuzhiyun if (!ddr_info)
3508*4882a593Smuzhiyun return;
3509*4882a593Smuzhiyun
3510*4882a593Smuzhiyun f0 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F0_SHIFT) &
3511*4882a593Smuzhiyun DDR_FREQ_MASK;
3512*4882a593Smuzhiyun
3513*4882a593Smuzhiyun #ifndef CONFIG_SPL_KERNEL_BOOT
3514*4882a593Smuzhiyun memset((void *)FSP_PARAM_STORE_ADDR, 0, sizeof(fsp_param));
3515*4882a593Smuzhiyun memset((void *)&fsp_param, 0, sizeof(fsp_param));
3516*4882a593Smuzhiyun
3517*4882a593Smuzhiyun f1 = (ddr_info->ddr_freq0_1 >> DDR_FREQ_F1_SHIFT) &
3518*4882a593Smuzhiyun DDR_FREQ_MASK;
3519*4882a593Smuzhiyun f2 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F2_SHIFT) &
3520*4882a593Smuzhiyun DDR_FREQ_MASK;
3521*4882a593Smuzhiyun f3 = (ddr_info->ddr_freq2_3 >> DDR_FREQ_F3_SHIFT) &
3522*4882a593Smuzhiyun DDR_FREQ_MASK;
3523*4882a593Smuzhiyun #endif
3524*4882a593Smuzhiyun
3525*4882a593Smuzhiyun if (get_wrlvl_val(dram, sdram_params))
3526*4882a593Smuzhiyun printascii("get wrlvl value fail\n");
3527*4882a593Smuzhiyun
3528*4882a593Smuzhiyun #ifndef CONFIG_SPL_KERNEL_BOOT
3529*4882a593Smuzhiyun printascii("change to: ");
3530*4882a593Smuzhiyun printdec(f1);
3531*4882a593Smuzhiyun printascii("MHz\n");
3532*4882a593Smuzhiyun ddr_set_rate(&dram_info, sdram_params, f1,
3533*4882a593Smuzhiyun sdram_params->base.ddr_freq, 1, 1, 1);
3534*4882a593Smuzhiyun printascii("change to: ");
3535*4882a593Smuzhiyun printdec(f2);
3536*4882a593Smuzhiyun printascii("MHz\n");
3537*4882a593Smuzhiyun ddr_set_rate(&dram_info, sdram_params, f2, f1, 2, 0, 1);
3538*4882a593Smuzhiyun printascii("change to: ");
3539*4882a593Smuzhiyun printdec(f3);
3540*4882a593Smuzhiyun printascii("MHz\n");
3541*4882a593Smuzhiyun ddr_set_rate(&dram_info, sdram_params, f3, f2, 3, 1, 1);
3542*4882a593Smuzhiyun #endif
3543*4882a593Smuzhiyun printascii("change to: ");
3544*4882a593Smuzhiyun printdec(f0);
3545*4882a593Smuzhiyun printascii("MHz(final freq)\n");
3546*4882a593Smuzhiyun #ifndef CONFIG_SPL_KERNEL_BOOT
3547*4882a593Smuzhiyun ddr_set_rate(&dram_info, sdram_params, f0, f3, 0, 0, 1);
3548*4882a593Smuzhiyun #else
3549*4882a593Smuzhiyun ddr_set_rate(&dram_info, sdram_params, f0, sdram_params->base.ddr_freq, 1, 1, 1);
3550*4882a593Smuzhiyun #endif
3551*4882a593Smuzhiyun }
3552*4882a593Smuzhiyun
get_uart_config(void)3553*4882a593Smuzhiyun int get_uart_config(void)
3554*4882a593Smuzhiyun {
3555*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
3556*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
3557*4882a593Smuzhiyun struct global_info *gbl_info;
3558*4882a593Smuzhiyun
3559*4882a593Smuzhiyun gbl_info = (struct global_info *)((void *)common_info +
3560*4882a593Smuzhiyun index->global_index.offset * 4);
3561*4882a593Smuzhiyun
3562*4882a593Smuzhiyun return gbl_info->uart_info;
3563*4882a593Smuzhiyun }
3564*4882a593Smuzhiyun
3565*4882a593Smuzhiyun /* return: 0 = success, other = fail */
sdram_init(void)3566*4882a593Smuzhiyun int sdram_init(void)
3567*4882a593Smuzhiyun {
3568*4882a593Smuzhiyun struct rv1126_sdram_params *sdram_params;
3569*4882a593Smuzhiyun int ret = 0;
3570*4882a593Smuzhiyun struct sdram_head_info_index_v2 *index =
3571*4882a593Smuzhiyun (struct sdram_head_info_index_v2 *)common_info;
3572*4882a593Smuzhiyun struct global_info *gbl_info;
3573*4882a593Smuzhiyun
3574*4882a593Smuzhiyun dram_info.phy = (void *)DDR_PHY_BASE_ADDR;
3575*4882a593Smuzhiyun dram_info.pctl = (void *)UPCTL2_BASE_ADDR;
3576*4882a593Smuzhiyun dram_info.grf = (void *)GRF_BASE_ADDR;
3577*4882a593Smuzhiyun dram_info.cru = (void *)CRU_BASE_ADDR;
3578*4882a593Smuzhiyun dram_info.msch = (void *)SERVER_MSCH_BASE_ADDR;
3579*4882a593Smuzhiyun dram_info.ddrgrf = (void *)DDR_GRF_BASE_ADDR;
3580*4882a593Smuzhiyun dram_info.pmugrf = (void *)PMU_GRF_BASE_ADDR;
3581*4882a593Smuzhiyun
3582*4882a593Smuzhiyun #ifdef CONFIG_ROCKCHIP_DRAM_EXTENDED_TEMP_SUPPORT
3583*4882a593Smuzhiyun printascii("extended temp support\n");
3584*4882a593Smuzhiyun #endif
3585*4882a593Smuzhiyun if (index->version_info != 2 ||
3586*4882a593Smuzhiyun (index->global_index.size != sizeof(struct global_info) / 4) ||
3587*4882a593Smuzhiyun (index->ddr3_index.size !=
3588*4882a593Smuzhiyun sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3589*4882a593Smuzhiyun (index->ddr4_index.size !=
3590*4882a593Smuzhiyun sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3591*4882a593Smuzhiyun (index->lp3_index.size !=
3592*4882a593Smuzhiyun sizeof(struct ddr2_3_4_lp2_3_info) / 4) ||
3593*4882a593Smuzhiyun (index->lp4_index.size != (sizeof(struct lp4_info) / 4)) ||
3594*4882a593Smuzhiyun (index->lp4x_index.size != (sizeof(struct lp4_info) / 4)) ||
3595*4882a593Smuzhiyun index->global_index.offset == 0 ||
3596*4882a593Smuzhiyun index->ddr3_index.offset == 0 ||
3597*4882a593Smuzhiyun index->ddr4_index.offset == 0 ||
3598*4882a593Smuzhiyun index->lp3_index.offset == 0 ||
3599*4882a593Smuzhiyun index->lp4_index.offset == 0 ||
3600*4882a593Smuzhiyun index->lp4x_index.offset == 0) {
3601*4882a593Smuzhiyun printascii("common info error\n");
3602*4882a593Smuzhiyun goto error;
3603*4882a593Smuzhiyun }
3604*4882a593Smuzhiyun
3605*4882a593Smuzhiyun gbl_info = (struct global_info *)((void *)common_info +
3606*4882a593Smuzhiyun index->global_index.offset * 4);
3607*4882a593Smuzhiyun
3608*4882a593Smuzhiyun dram_info.sr_idle = SR_INFO(gbl_info->sr_pd_info);
3609*4882a593Smuzhiyun dram_info.pd_idle = PD_INFO(gbl_info->sr_pd_info);
3610*4882a593Smuzhiyun
3611*4882a593Smuzhiyun sdram_params = &sdram_configs[0];
3612*4882a593Smuzhiyun #if (CONFIG_ROCKCHIP_TPL_INIT_DRAM_TYPE == 8)
3613*4882a593Smuzhiyun for (int j = 0; j < ARRAY_SIZE(sdram_configs); j++)
3614*4882a593Smuzhiyun sdram_configs[j].base.dramtype = LPDDR4X;
3615*4882a593Smuzhiyun #endif
3616*4882a593Smuzhiyun if (sdram_params->base.dramtype == DDR3 ||
3617*4882a593Smuzhiyun sdram_params->base.dramtype == DDR4) {
3618*4882a593Smuzhiyun if (DDR_2T_INFO(gbl_info->info_2t))
3619*4882a593Smuzhiyun sdram_params->pctl_regs.pctl[0][1] |= 0x1 << 10;
3620*4882a593Smuzhiyun else
3621*4882a593Smuzhiyun sdram_params->pctl_regs.pctl[0][1] &=
3622*4882a593Smuzhiyun ~(0x1 << 10);
3623*4882a593Smuzhiyun }
3624*4882a593Smuzhiyun ret = sdram_init_detect(&dram_info, sdram_params);
3625*4882a593Smuzhiyun if (ret) {
3626*4882a593Smuzhiyun sdram_print_dram_type(sdram_params->base.dramtype);
3627*4882a593Smuzhiyun printascii(", ");
3628*4882a593Smuzhiyun printdec(sdram_params->base.ddr_freq);
3629*4882a593Smuzhiyun printascii("MHz\n");
3630*4882a593Smuzhiyun goto error;
3631*4882a593Smuzhiyun }
3632*4882a593Smuzhiyun print_ddr_info(sdram_params);
3633*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
3634*4882a593Smuzhiyun init_rw_trn_result_struct(&rw_trn_result, dram_info.phy,
3635*4882a593Smuzhiyun (u8)sdram_params->ch.cap_info.rank);
3636*4882a593Smuzhiyun #endif
3637*4882a593Smuzhiyun
3638*4882a593Smuzhiyun ddr_set_rate_for_fsp(&dram_info, sdram_params);
3639*4882a593Smuzhiyun #ifndef CONFIG_SPL_KERNEL_BOOT
3640*4882a593Smuzhiyun copy_fsp_param_to_ddr();
3641*4882a593Smuzhiyun #endif
3642*4882a593Smuzhiyun
3643*4882a593Smuzhiyun ddr_set_atags(&dram_info, sdram_params);
3644*4882a593Smuzhiyun #if defined(CONFIG_CMD_DDR_TEST_TOOL)
3645*4882a593Smuzhiyun save_rw_trn_result_to_ddr(&rw_trn_result);
3646*4882a593Smuzhiyun #endif
3647*4882a593Smuzhiyun
3648*4882a593Smuzhiyun printascii("out\n");
3649*4882a593Smuzhiyun
3650*4882a593Smuzhiyun return ret;
3651*4882a593Smuzhiyun error:
3652*4882a593Smuzhiyun printascii("error\n");
3653*4882a593Smuzhiyun return (-1);
3654*4882a593Smuzhiyun }
3655*4882a593Smuzhiyun #endif /* CONFIG_TPL_BUILD */
3656