xref: /openbmc/u-boot/drivers/ddr/marvell/axp/ddr3_write_leveling.c (revision 83d290c56fab2d38cd1ab4c4cc7099559c1d5046)
1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
2ff9112dfSStefan Roese /*
3ff9112dfSStefan Roese  * Copyright (C) Marvell International Ltd. and its affiliates
4ff9112dfSStefan Roese  */
5ff9112dfSStefan Roese 
6ff9112dfSStefan Roese #include <common.h>
7ff9112dfSStefan Roese #include <i2c.h>
8ff9112dfSStefan Roese #include <spl.h>
9ff9112dfSStefan Roese #include <asm/io.h>
10ff9112dfSStefan Roese #include <asm/arch/cpu.h>
11ff9112dfSStefan Roese #include <asm/arch/soc.h>
12ff9112dfSStefan Roese 
13ff9112dfSStefan Roese #include "ddr3_hw_training.h"
14ff9112dfSStefan Roese 
15ff9112dfSStefan Roese /*
16ff9112dfSStefan Roese  * Debug
17ff9112dfSStefan Roese  */
18ff9112dfSStefan Roese #define DEBUG_WL_C(s, d, l) \
19ff9112dfSStefan Roese 	DEBUG_WL_S(s); DEBUG_WL_D(d, l); DEBUG_WL_S("\n")
20ff9112dfSStefan Roese #define DEBUG_WL_FULL_C(s, d, l) \
21ff9112dfSStefan Roese 	DEBUG_WL_FULL_S(s); DEBUG_WL_FULL_D(d, l); DEBUG_WL_FULL_S("\n")
22ff9112dfSStefan Roese 
23ff9112dfSStefan Roese #ifdef MV_DEBUG_WL
247e1e59a7SPhil Sutter #define DEBUG_WL_S(s)			puts(s)
257e1e59a7SPhil Sutter #define DEBUG_WL_D(d, l)		printf("%x", d)
26ff9112dfSStefan Roese #define DEBUG_RL_S(s) \
27ff9112dfSStefan Roese 	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
28ff9112dfSStefan Roese #define DEBUG_RL_D(d, l) \
29ff9112dfSStefan Roese 	debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
30ff9112dfSStefan Roese #else
31ff9112dfSStefan Roese #define DEBUG_WL_S(s)
32ff9112dfSStefan Roese #define DEBUG_WL_D(d, l)
33ff9112dfSStefan Roese #endif
34ff9112dfSStefan Roese 
35ff9112dfSStefan Roese #ifdef MV_DEBUG_WL_FULL
36ff9112dfSStefan Roese #define DEBUG_WL_FULL_S(s)		puts(s)
37ff9112dfSStefan Roese #define DEBUG_WL_FULL_D(d, l)		printf("%x", d)
38ff9112dfSStefan Roese #else
39ff9112dfSStefan Roese #define DEBUG_WL_FULL_S(s)
40ff9112dfSStefan Roese #define DEBUG_WL_FULL_D(d, l)
41ff9112dfSStefan Roese #endif
42ff9112dfSStefan Roese 
43ff9112dfSStefan Roese #define WL_SUP_EXPECTED_DATA		0x21
44ff9112dfSStefan Roese #define WL_SUP_READ_DRAM_ENTRY		0x8
45ff9112dfSStefan Roese 
46ff9112dfSStefan Roese static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
47ff9112dfSStefan Roese 					 u32 *result,
48ff9112dfSStefan Roese 					 MV_DRAM_INFO *dram_info);
49ff9112dfSStefan Roese static void ddr3_write_ctrl_pup_reg(int bc_acc, u32 pup, u32 reg_addr,
50ff9112dfSStefan Roese 				    u32 data);
51ff9112dfSStefan Roese 
52ff9112dfSStefan Roese extern u16 odt_static[ODT_OPT][MAX_CS];
53ff9112dfSStefan Roese extern u16 odt_dynamic[ODT_OPT][MAX_CS];
54ff9112dfSStefan Roese extern u32 wl_sup_pattern[LEN_WL_SUP_PATTERN];
55ff9112dfSStefan Roese 
56ff9112dfSStefan Roese /*
57ff9112dfSStefan Roese  * Name:     ddr3_write_leveling_hw
58ff9112dfSStefan Roese  * Desc:     Execute Write leveling phase by HW
59ff9112dfSStefan Roese  * Args:     freq      - current sequence frequency
60ff9112dfSStefan Roese  *           dram_info   - main struct
61ff9112dfSStefan Roese  * Notes:
62ff9112dfSStefan Roese  * Returns:  MV_OK if success, MV_FAIL if fail.
63ff9112dfSStefan Roese  */
ddr3_write_leveling_hw(u32 freq,MV_DRAM_INFO * dram_info)64ff9112dfSStefan Roese int ddr3_write_leveling_hw(u32 freq, MV_DRAM_INFO *dram_info)
65ff9112dfSStefan Roese {
66ff9112dfSStefan Roese 	u32 reg, phase, delay, cs, pup;
67ff9112dfSStefan Roese #ifdef MV88F67XX
68ff9112dfSStefan Roese 	int dpde_flag = 0;
69ff9112dfSStefan Roese #endif
70ff9112dfSStefan Roese 	/* Debug message - Start Read leveling procedure */
71ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling - Starting HW WL procedure\n");
72ff9112dfSStefan Roese 
73ff9112dfSStefan Roese #ifdef MV88F67XX
74ff9112dfSStefan Roese 	/* Dynamic pad issue (BTS669) during WL */
75ff9112dfSStefan Roese 	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
76ff9112dfSStefan Roese 	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
77ff9112dfSStefan Roese 		dpde_flag = 1;
78ff9112dfSStefan Roese 		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
79ff9112dfSStefan Roese 			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
80ff9112dfSStefan Roese 	}
81ff9112dfSStefan Roese #endif
82ff9112dfSStefan Roese 
83ff9112dfSStefan Roese 	reg = 1 << REG_DRAM_TRAINING_WL_OFFS;
84ff9112dfSStefan Roese 	/* Config the retest number */
85ff9112dfSStefan Roese 	reg |= (COUNT_HW_WL << REG_DRAM_TRAINING_RETEST_OFFS);
86ff9112dfSStefan Roese 	reg |= (dram_info->cs_ena << (REG_DRAM_TRAINING_CS_OFFS));
87ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
88ff9112dfSStefan Roese 
89ff9112dfSStefan Roese 	reg =  reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
90ff9112dfSStefan Roese 		(1 << REG_DRAM_TRAINING_AUTO_OFFS);
91ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
92ff9112dfSStefan Roese 
93ff9112dfSStefan Roese 	/* Wait */
94ff9112dfSStefan Roese 	do {
95ff9112dfSStefan Roese 		reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
96ff9112dfSStefan Roese 			(1 << REG_DRAM_TRAINING_AUTO_OFFS);
97ff9112dfSStefan Roese 	} while (reg);		/* Wait for '0' */
98ff9112dfSStefan Roese 
99ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_ADDR);
100ff9112dfSStefan Roese 	/* Check if Successful */
101ff9112dfSStefan Roese 	if (reg & (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
102ff9112dfSStefan Roese 		/*
103ff9112dfSStefan Roese 		 * Read results to arrays - Results are required for WL
104ff9112dfSStefan Roese 		 * High freq Supplement and DQS Centralization
105ff9112dfSStefan Roese 		 */
106ff9112dfSStefan Roese 		for (cs = 0; cs < MAX_CS; cs++) {
107ff9112dfSStefan Roese 			if (dram_info->cs_ena & (1 << cs)) {
108ff9112dfSStefan Roese 				for (pup = 0;
109ff9112dfSStefan Roese 				     pup < dram_info->num_of_total_pups;
110ff9112dfSStefan Roese 				     pup++) {
111ff9112dfSStefan Roese 					if (pup == dram_info->num_of_std_pups
112ff9112dfSStefan Roese 					    && dram_info->ecc_ena)
113ff9112dfSStefan Roese 						pup = ECC_PUP;
114ff9112dfSStefan Roese 					reg =
115ff9112dfSStefan Roese 					    ddr3_read_pup_reg(PUP_WL_MODE, cs,
116ff9112dfSStefan Roese 							      pup);
117ff9112dfSStefan Roese 					phase =
118ff9112dfSStefan Roese 					    (reg >> REG_PHY_PHASE_OFFS) &
119ff9112dfSStefan Roese 					    PUP_PHASE_MASK;
120ff9112dfSStefan Roese 					delay = reg & PUP_DELAY_MASK;
121ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][P] = phase;
122ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][D] = delay;
123ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][S] =
124ff9112dfSStefan Roese 					    WL_HI_FREQ_STATE - 1;
125ff9112dfSStefan Roese 					reg =
126ff9112dfSStefan Roese 					    ddr3_read_pup_reg(PUP_WL_MODE + 0x1,
127ff9112dfSStefan Roese 							      cs, pup);
128ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][DQS] =
129ff9112dfSStefan Roese 					    (reg & 0x3F);
130ff9112dfSStefan Roese 				}
131ff9112dfSStefan Roese 
132ff9112dfSStefan Roese #ifdef MV_DEBUG_WL
133ff9112dfSStefan Roese 				/* Debug message - Print res for cs[i]: cs,PUP,Phase,Delay */
134ff9112dfSStefan Roese 				DEBUG_WL_S("DDR3 - Write Leveling - Write Leveling Cs - ");
135ff9112dfSStefan Roese 				DEBUG_WL_D((u32) cs, 1);
136ff9112dfSStefan Roese 				DEBUG_WL_S(" Results:\n");
137ff9112dfSStefan Roese 				for (pup = 0;
138ff9112dfSStefan Roese 				     pup < dram_info->num_of_total_pups;
139ff9112dfSStefan Roese 				     pup++) {
140ff9112dfSStefan Roese 					if (pup == dram_info->num_of_std_pups
141ff9112dfSStefan Roese 					    && dram_info->ecc_ena)
142ff9112dfSStefan Roese 						pup = ECC_PUP;
143ff9112dfSStefan Roese 					DEBUG_WL_S("DDR3 - Write Leveling - PUP: ");
144ff9112dfSStefan Roese 					DEBUG_WL_D((u32) pup, 1);
145ff9112dfSStefan Roese 					DEBUG_WL_S(", Phase: ");
146ff9112dfSStefan Roese 					DEBUG_WL_D((u32)
147ff9112dfSStefan Roese 						   dram_info->wl_val[cs][pup]
148ff9112dfSStefan Roese 						   [P], 1);
149ff9112dfSStefan Roese 					DEBUG_WL_S(", Delay: ");
150ff9112dfSStefan Roese 					DEBUG_WL_D((u32)
151ff9112dfSStefan Roese 						   dram_info->wl_val[cs][pup]
152ff9112dfSStefan Roese 						   [D], 2);
153ff9112dfSStefan Roese 					DEBUG_WL_S("\n");
154ff9112dfSStefan Roese 				}
155ff9112dfSStefan Roese #endif
156ff9112dfSStefan Roese 			}
157ff9112dfSStefan Roese 		}
158ff9112dfSStefan Roese 
159ff9112dfSStefan Roese 		/* Dynamic pad issue (BTS669) during WL */
160ff9112dfSStefan Roese #ifdef MV88F67XX
161ff9112dfSStefan Roese 		if (dpde_flag) {
162ff9112dfSStefan Roese 			reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
163ff9112dfSStefan Roese 				(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
164ff9112dfSStefan Roese 			reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
165ff9112dfSStefan Roese 		}
166ff9112dfSStefan Roese #endif
167ff9112dfSStefan Roese 
168ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
169ff9112dfSStefan Roese 
170ff9112dfSStefan Roese 		return MV_OK;
171ff9112dfSStefan Roese 	} else {
172ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Error\n");
173ff9112dfSStefan Roese 		return MV_FAIL;
174ff9112dfSStefan Roese 	}
175ff9112dfSStefan Roese }
176ff9112dfSStefan Roese 
177ff9112dfSStefan Roese /*
178ff9112dfSStefan Roese  * Name:     ddr3_wl_supplement
179ff9112dfSStefan Roese  * Desc:     Write Leveling Supplement
180ff9112dfSStefan Roese  * Args:     dram_info   - main struct
181ff9112dfSStefan Roese  * Notes:
182ff9112dfSStefan Roese  * Returns:  MV_OK if success, MV_FAIL if fail.
183ff9112dfSStefan Roese  */
ddr3_wl_supplement(MV_DRAM_INFO * dram_info)184ff9112dfSStefan Roese int ddr3_wl_supplement(MV_DRAM_INFO *dram_info)
185ff9112dfSStefan Roese {
186ff9112dfSStefan Roese 	u32 cs, cnt, pup_num, sum, phase, delay, max_pup_num, pup, sdram_offset;
187ff9112dfSStefan Roese 	u32 tmp_count, ecc, reg;
188ff9112dfSStefan Roese 	u32 ddr_width, tmp_pup, idx;
189ff9112dfSStefan Roese 	u32 sdram_pup_val, uj;
190ff9112dfSStefan Roese 	u32 one_clk_err = 0, align_err = 0, no_err = 0, err = 0, err_n = 0;
191ff9112dfSStefan Roese 	u32 sdram_data[LEN_WL_SUP_PATTERN] __aligned(32) = { 0 };
192ff9112dfSStefan Roese 
193ff9112dfSStefan Roese 	ddr_width = dram_info->ddr_width;
194ff9112dfSStefan Roese 	no_err = 0;
195ff9112dfSStefan Roese 
196ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - Starting\n");
197ff9112dfSStefan Roese 
198ff9112dfSStefan Roese 	switch (ddr_width) {
199ff9112dfSStefan Roese 		/* Data error from pos-adge to pos-adge */
200ff9112dfSStefan Roese 	case 16:
201ff9112dfSStefan Roese 		one_clk_err = 4;
202ff9112dfSStefan Roese 		align_err = 4;
203ff9112dfSStefan Roese 		break;
204ff9112dfSStefan Roese 	case 32:
205ff9112dfSStefan Roese 		one_clk_err = 8;
206ff9112dfSStefan Roese 		align_err = 8;
207ff9112dfSStefan Roese 		break;
208ff9112dfSStefan Roese 	case 64:
209ff9112dfSStefan Roese 		one_clk_err = 0x10;
210ff9112dfSStefan Roese 		align_err = 0x10;
211ff9112dfSStefan Roese 		break;
212ff9112dfSStefan Roese 	default:
213ff9112dfSStefan Roese 		DEBUG_WL_S("Error - bus width!!!\n");
214ff9112dfSStefan Roese 		return MV_FAIL;
215ff9112dfSStefan Roese 	}
216ff9112dfSStefan Roese 
217ff9112dfSStefan Roese 	/* Enable SW override */
218ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
219ff9112dfSStefan Roese 		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
220ff9112dfSStefan Roese 
221ff9112dfSStefan Roese 	/* [0] = 1 - Enable SW override  */
222ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
223ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
224ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - SW Override Enabled\n");
225ff9112dfSStefan Roese 	reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
226ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
227ff9112dfSStefan Roese 	tmp_count = 0;
228ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
229ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
230ff9112dfSStefan Roese 			sum = 0;
231ff9112dfSStefan Roese 			/*
232ff9112dfSStefan Roese 			 * 2 iterations loop: 1)actual WL results 2) fix WL
233ff9112dfSStefan Roese 			 * if needed
234ff9112dfSStefan Roese 			 */
235ff9112dfSStefan Roese 			for (cnt = 0; cnt < COUNT_WL_HI_FREQ; cnt++) {
236ff9112dfSStefan Roese 				DEBUG_WL_C("COUNT = ", cnt, 1);
237ff9112dfSStefan Roese 				for (ecc = 0; ecc < (dram_info->ecc_ena + 1);
238ff9112dfSStefan Roese 				     ecc++) {
239ff9112dfSStefan Roese 					if (ecc) {
240ff9112dfSStefan Roese 						DEBUG_WL_S("ECC PUP:\n");
241ff9112dfSStefan Roese 					} else {
242ff9112dfSStefan Roese 						DEBUG_WL_S("DATA PUP:\n");
243ff9112dfSStefan Roese 					}
244ff9112dfSStefan Roese 
245ff9112dfSStefan Roese 					max_pup_num =
246ff9112dfSStefan Roese 					    dram_info->num_of_std_pups * (1 -
247ff9112dfSStefan Roese 									  ecc) +
248ff9112dfSStefan Roese 					    ecc;
249ff9112dfSStefan Roese 					/* ECC Support - Switch ECC Mux on ecc=1 */
250ff9112dfSStefan Roese 					reg =
251ff9112dfSStefan Roese 					    (reg_read(REG_DRAM_TRAINING_2_ADDR)
252ff9112dfSStefan Roese 					     & ~(1 <<
253ff9112dfSStefan Roese 						 REG_DRAM_TRAINING_2_ECC_MUX_OFFS));
254ff9112dfSStefan Roese 					reg |=
255ff9112dfSStefan Roese 					    (dram_info->ecc_ena *
256ff9112dfSStefan Roese 					     ecc <<
257ff9112dfSStefan Roese 					     REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
258ff9112dfSStefan Roese 					reg_write(REG_DRAM_TRAINING_2_ADDR,
259ff9112dfSStefan Roese 						  reg);
260ff9112dfSStefan Roese 					ddr3_reset_phy_read_fifo();
261ff9112dfSStefan Roese 
262ff9112dfSStefan Roese 					/* Write to memory */
263ff9112dfSStefan Roese 					sdram_offset =
264ff9112dfSStefan Roese 					    tmp_count * (SDRAM_CS_SIZE + 1) +
265ff9112dfSStefan Roese 					    0x200;
266ff9112dfSStefan Roese 					if (MV_OK != ddr3_dram_sram_burst((u32)
267ff9112dfSStefan Roese 									  wl_sup_pattern,
268ff9112dfSStefan Roese 									  sdram_offset,
269ff9112dfSStefan Roese 									  LEN_WL_SUP_PATTERN))
270ff9112dfSStefan Roese 						return MV_FAIL;
271ff9112dfSStefan Roese 
272ff9112dfSStefan Roese 					/* Read from memory */
273ff9112dfSStefan Roese 					if (MV_OK !=
274ff9112dfSStefan Roese 					    ddr3_dram_sram_burst(sdram_offset,
275ff9112dfSStefan Roese 								 (u32)
276ff9112dfSStefan Roese 								 sdram_data,
277ff9112dfSStefan Roese 								 LEN_WL_SUP_PATTERN))
278ff9112dfSStefan Roese 						return MV_FAIL;
279ff9112dfSStefan Roese 
280ff9112dfSStefan Roese 					/* Print the buffer */
281ff9112dfSStefan Roese 					for (uj = 0; uj < LEN_WL_SUP_PATTERN;
282ff9112dfSStefan Roese 					     uj++) {
283ff9112dfSStefan Roese 						if ((uj % 4 == 0) && (uj != 0)) {
284ff9112dfSStefan Roese 							DEBUG_WL_S("\n");
285ff9112dfSStefan Roese 						}
286ff9112dfSStefan Roese 						DEBUG_WL_D(sdram_data[uj],
287ff9112dfSStefan Roese 							   8);
288ff9112dfSStefan Roese 						DEBUG_WL_S(" ");
289ff9112dfSStefan Roese 					}
290ff9112dfSStefan Roese 
291ff9112dfSStefan Roese 					/* Check pup which DQS/DATA is error */
292ff9112dfSStefan Roese 					for (pup = 0; pup < max_pup_num; pup++) {
293ff9112dfSStefan Roese 						/* ECC support - bit 8 */
294ff9112dfSStefan Roese 						pup_num = (ecc) ? ECC_PUP : pup;
295ff9112dfSStefan Roese 						if (pup < 4) {	/* lower 32 bit */
296ff9112dfSStefan Roese 							tmp_pup = pup;
297ff9112dfSStefan Roese 							idx =
298ff9112dfSStefan Roese 							    WL_SUP_READ_DRAM_ENTRY;
299ff9112dfSStefan Roese 						} else {	/* higher 32 bit */
300ff9112dfSStefan Roese 							tmp_pup = pup - 4;
301ff9112dfSStefan Roese 							idx =
302ff9112dfSStefan Roese 							    WL_SUP_READ_DRAM_ENTRY
303ff9112dfSStefan Roese 							    + 1;
304ff9112dfSStefan Roese 						}
305ff9112dfSStefan Roese 						DEBUG_WL_S("\nCS: ");
306ff9112dfSStefan Roese 						DEBUG_WL_D((u32) cs, 1);
307ff9112dfSStefan Roese 						DEBUG_WL_S(" PUP: ");
308ff9112dfSStefan Roese 						DEBUG_WL_D((u32) pup_num, 1);
309ff9112dfSStefan Roese 						DEBUG_WL_S("\n");
310ff9112dfSStefan Roese 						sdram_pup_val =
311ff9112dfSStefan Roese 						    ((sdram_data[idx] >>
312ff9112dfSStefan Roese 						      ((tmp_pup) * 8)) & 0xFF);
313ff9112dfSStefan Roese 						DEBUG_WL_C("Actual Data = ",
314ff9112dfSStefan Roese 							   sdram_pup_val, 2);
315ff9112dfSStefan Roese 						DEBUG_WL_C("Expected Data = ",
316ff9112dfSStefan Roese 							   (WL_SUP_EXPECTED_DATA
317ff9112dfSStefan Roese 							    + pup), 2);
318ff9112dfSStefan Roese 						/*
319ff9112dfSStefan Roese 						 * ALINGHMENT: calculate
320ff9112dfSStefan Roese 						 * expected data vs actual data
321ff9112dfSStefan Roese 						 */
322ff9112dfSStefan Roese 						err =
323ff9112dfSStefan Roese 						    (WL_SUP_EXPECTED_DATA +
324ff9112dfSStefan Roese 						     pup) - sdram_pup_val;
325ff9112dfSStefan Roese 						/*
326ff9112dfSStefan Roese 						 * CLOCK LONG: calculate
327ff9112dfSStefan Roese 						 * expected data vs actual data
328ff9112dfSStefan Roese 						 */
329ff9112dfSStefan Roese 						err_n =
330ff9112dfSStefan Roese 						    sdram_pup_val -
331ff9112dfSStefan Roese 						    (WL_SUP_EXPECTED_DATA +
332ff9112dfSStefan Roese 						     pup);
333ff9112dfSStefan Roese 						DEBUG_WL_C("err = ", err, 2);
334ff9112dfSStefan Roese 						DEBUG_WL_C("err_n = ", err_n,
335ff9112dfSStefan Roese 							   2);
336ff9112dfSStefan Roese 						if (err == no_err) {
337ff9112dfSStefan Roese 							/* PUP is correct - increment State */
338ff9112dfSStefan Roese 							dram_info->wl_val[cs]
339ff9112dfSStefan Roese 							    [pup_num]
340ff9112dfSStefan Roese 							    [S] = 1;
341ff9112dfSStefan Roese 						} else if (err_n == one_clk_err) {
342ff9112dfSStefan Roese 							/* clock is longer than DQS */
343ff9112dfSStefan Roese 							phase =
344ff9112dfSStefan Roese 							    ((dram_info->wl_val
345ff9112dfSStefan Roese 							      [cs]
346ff9112dfSStefan Roese 							      [pup_num][P] +
347ff9112dfSStefan Roese 							      WL_HI_FREQ_SHIFT)
348ff9112dfSStefan Roese 							     % MAX_PHASE_2TO1);
349ff9112dfSStefan Roese 							dram_info->wl_val[cs]
350ff9112dfSStefan Roese 							    [pup_num]
351ff9112dfSStefan Roese 							    [P] = phase;
352ff9112dfSStefan Roese 							delay =
353ff9112dfSStefan Roese 							    dram_info->wl_val
354ff9112dfSStefan Roese 							    [cs][pup_num]
355ff9112dfSStefan Roese 							    [D];
356ff9112dfSStefan Roese 							DEBUG_WL_S("#### Clock is longer than DQS more than one clk cycle ####\n");
357ff9112dfSStefan Roese 							ddr3_write_pup_reg
358ff9112dfSStefan Roese 							    (PUP_WL_MODE, cs,
359ff9112dfSStefan Roese 							     pup * (1 - ecc) +
360ff9112dfSStefan Roese 							     ECC_PUP * ecc,
361ff9112dfSStefan Roese 							     phase, delay);
362ff9112dfSStefan Roese 						} else if (err == align_err) {
363ff9112dfSStefan Roese 							/* clock is align to DQS */
364ff9112dfSStefan Roese 							phase =
365ff9112dfSStefan Roese 							    dram_info->wl_val
366ff9112dfSStefan Roese 							    [cs][pup_num]
367ff9112dfSStefan Roese 							    [P];
368ff9112dfSStefan Roese 							delay =
369ff9112dfSStefan Roese 							    dram_info->wl_val
370ff9112dfSStefan Roese 							    [cs][pup_num]
371ff9112dfSStefan Roese 							    [D];
372ff9112dfSStefan Roese 							DEBUG_WL_S("#### Alignment PUPS problem ####\n");
373ff9112dfSStefan Roese 							if ((phase == 0)
374ff9112dfSStefan Roese 							    || ((phase == 1)
375ff9112dfSStefan Roese 								&& (delay <=
376ff9112dfSStefan Roese 								    0x10))) {
377ff9112dfSStefan Roese 								DEBUG_WL_S("#### Warning - Possible Layout Violation (DQS is longer than CLK)####\n");
378ff9112dfSStefan Roese 							}
379ff9112dfSStefan Roese 
380ff9112dfSStefan Roese 							phase = 0x0;
381ff9112dfSStefan Roese 							delay = 0x0;
382ff9112dfSStefan Roese 							dram_info->wl_val[cs]
383ff9112dfSStefan Roese 							    [pup_num]
384ff9112dfSStefan Roese 							    [P] = phase;
385ff9112dfSStefan Roese 							dram_info->wl_val[cs]
386ff9112dfSStefan Roese 							    [pup_num]
387ff9112dfSStefan Roese 							    [D] = delay;
388ff9112dfSStefan Roese 							ddr3_write_pup_reg
389ff9112dfSStefan Roese 							    (PUP_WL_MODE, cs,
390ff9112dfSStefan Roese 							     pup * (1 - ecc) +
391ff9112dfSStefan Roese 							     ECC_PUP * ecc,
392ff9112dfSStefan Roese 							     phase, delay);
393ff9112dfSStefan Roese 						}
394ff9112dfSStefan Roese 						/* Stop condition for ECC phase */
395ff9112dfSStefan Roese 						pup = (ecc) ? max_pup_num : pup;
396ff9112dfSStefan Roese 					}
397ff9112dfSStefan Roese 
398ff9112dfSStefan Roese 					/* ECC Support - Disable ECC MUX */
399ff9112dfSStefan Roese 					reg =
400ff9112dfSStefan Roese 					    (reg_read(REG_DRAM_TRAINING_2_ADDR)
401ff9112dfSStefan Roese 					     & ~(1 <<
402ff9112dfSStefan Roese 						 REG_DRAM_TRAINING_2_ECC_MUX_OFFS));
403ff9112dfSStefan Roese 					reg_write(REG_DRAM_TRAINING_2_ADDR,
404ff9112dfSStefan Roese 						  reg);
405ff9112dfSStefan Roese 				}
406ff9112dfSStefan Roese 			}
407ff9112dfSStefan Roese 
408ff9112dfSStefan Roese 			for (pup = 0; pup < dram_info->num_of_std_pups; pup++)
409ff9112dfSStefan Roese 				sum += dram_info->wl_val[cs][pup][S];
410ff9112dfSStefan Roese 
411ff9112dfSStefan Roese 			if (dram_info->ecc_ena)
412ff9112dfSStefan Roese 				sum += dram_info->wl_val[cs][ECC_PUP][S];
413ff9112dfSStefan Roese 
414ff9112dfSStefan Roese 			/* Checks if any pup is not locked after the change */
415ff9112dfSStefan Roese 			if (sum < (WL_HI_FREQ_STATE * (dram_info->num_of_total_pups))) {
416ff9112dfSStefan Roese 				DEBUG_WL_C("DDR3 - Write Leveling Hi-Freq Supplement - didn't work for Cs - ",
417ff9112dfSStefan Roese 					   (u32) cs, 1);
418ff9112dfSStefan Roese 				return MV_FAIL;
419ff9112dfSStefan Roese 			}
420ff9112dfSStefan Roese 			tmp_count++;
421ff9112dfSStefan Roese 		}
422ff9112dfSStefan Roese 	}
423ff9112dfSStefan Roese 
424ff9112dfSStefan Roese 	dram_info->wl_max_phase = 0;
425ff9112dfSStefan Roese 	dram_info->wl_min_phase = 10;
426ff9112dfSStefan Roese 
427ff9112dfSStefan Roese 	/*
428ff9112dfSStefan Roese 	 * Read results to arrays - Results are required for DQS Centralization
429ff9112dfSStefan Roese 	 */
430ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
431ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
432ff9112dfSStefan Roese 			for (pup = 0; pup < dram_info->num_of_total_pups; pup++) {
433ff9112dfSStefan Roese 				if (pup == dram_info->num_of_std_pups
434ff9112dfSStefan Roese 				    && dram_info->ecc_ena)
435ff9112dfSStefan Roese 					pup = ECC_PUP;
436ff9112dfSStefan Roese 				reg = ddr3_read_pup_reg(PUP_WL_MODE, cs, pup);
437ff9112dfSStefan Roese 				phase =
438ff9112dfSStefan Roese 				    (reg >> REG_PHY_PHASE_OFFS) &
439ff9112dfSStefan Roese 				    PUP_PHASE_MASK;
440ff9112dfSStefan Roese 				if (phase > dram_info->wl_max_phase)
441ff9112dfSStefan Roese 					dram_info->wl_max_phase = phase;
442ff9112dfSStefan Roese 				if (phase < dram_info->wl_min_phase)
443ff9112dfSStefan Roese 					dram_info->wl_min_phase = phase;
444ff9112dfSStefan Roese 			}
445ff9112dfSStefan Roese 		}
446ff9112dfSStefan Roese 	}
447ff9112dfSStefan Roese 
448ff9112dfSStefan Roese 	/* Disable SW override - Must be in a different stage */
449ff9112dfSStefan Roese 	/* [0]=0 - Enable SW override  */
450ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
451ff9112dfSStefan Roese 	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
452ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
453ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
454ff9112dfSStefan Roese 
455ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
456ff9112dfSStefan Roese 		(1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
457ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
458ff9112dfSStefan Roese 
459ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling Hi-Freq Supplement - Ended Successfully\n");
460ff9112dfSStefan Roese 
461ff9112dfSStefan Roese 	return MV_OK;
462ff9112dfSStefan Roese }
463ff9112dfSStefan Roese 
464ff9112dfSStefan Roese /*
465ff9112dfSStefan Roese  * Name:     ddr3_write_leveling_hw_reg_dimm
466ff9112dfSStefan Roese  * Desc:     Execute Write leveling phase by HW
467ff9112dfSStefan Roese  * Args:     freq      - current sequence frequency
468ff9112dfSStefan Roese  *           dram_info   - main struct
469ff9112dfSStefan Roese  * Notes:
470ff9112dfSStefan Roese  * Returns:  MV_OK if success, MV_FAIL if fail.
471ff9112dfSStefan Roese  */
ddr3_write_leveling_hw_reg_dimm(u32 freq,MV_DRAM_INFO * dram_info)472ff9112dfSStefan Roese int ddr3_write_leveling_hw_reg_dimm(u32 freq, MV_DRAM_INFO *dram_info)
473ff9112dfSStefan Roese {
474ff9112dfSStefan Roese 	u32 reg, phase, delay, cs, pup, pup_num;
475ff9112dfSStefan Roese 	__maybe_unused int dpde_flag = 0;
476ff9112dfSStefan Roese 
477ff9112dfSStefan Roese 	/* Debug message - Start Read leveling procedure */
478ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling - Starting HW WL procedure\n");
479ff9112dfSStefan Roese 
480ff9112dfSStefan Roese 	if (dram_info->num_cs > 2) {
481ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
482ff9112dfSStefan Roese 		return MV_NO_CHANGE;
483ff9112dfSStefan Roese 	}
484ff9112dfSStefan Roese 
485ff9112dfSStefan Roese 	/* If target freq = 400 move clock start point */
486ff9112dfSStefan Roese 	/* Write to control PUP to Control Deskew Regs */
487ff9112dfSStefan Roese 	if (freq <= DDR_400) {
488ff9112dfSStefan Roese 		for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
489ff9112dfSStefan Roese 			/* PUP_DELAY_MASK 0x1F */
490ff9112dfSStefan Roese 			/* reg = 0x0C10001F + (uj << 16); */
491ff9112dfSStefan Roese 			ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
492ff9112dfSStefan Roese 						0x1F);
493ff9112dfSStefan Roese 		}
494ff9112dfSStefan Roese 	}
495ff9112dfSStefan Roese 
496ff9112dfSStefan Roese #ifdef MV88F67XX
497ff9112dfSStefan Roese 	/* Dynamic pad issue (BTS669) during WL */
498ff9112dfSStefan Roese 	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
499ff9112dfSStefan Roese 	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
500ff9112dfSStefan Roese 		dpde_flag = 1;
501ff9112dfSStefan Roese 		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
502ff9112dfSStefan Roese 			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
503ff9112dfSStefan Roese 	}
504ff9112dfSStefan Roese #endif
505ff9112dfSStefan Roese 
506ff9112dfSStefan Roese 	reg = (1 << REG_DRAM_TRAINING_WL_OFFS);
507ff9112dfSStefan Roese 	/* Config the retest number */
508ff9112dfSStefan Roese 	reg |= (COUNT_HW_WL << REG_DRAM_TRAINING_RETEST_OFFS);
509ff9112dfSStefan Roese 	reg |= (dram_info->cs_ena << (REG_DRAM_TRAINING_CS_OFFS));
510ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_ADDR, reg);	/* 0x15B0 - Training Register */
511ff9112dfSStefan Roese 
512ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) |
513ff9112dfSStefan Roese 		(1 << REG_DRAM_TRAINING_AUTO_OFFS);
514ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_SHADOW_ADDR, reg);
515ff9112dfSStefan Roese 
516ff9112dfSStefan Roese 	/* Wait */
517ff9112dfSStefan Roese 	do {
518ff9112dfSStefan Roese 		reg = reg_read(REG_DRAM_TRAINING_SHADOW_ADDR) &
519ff9112dfSStefan Roese 			(1 << REG_DRAM_TRAINING_AUTO_OFFS);
520ff9112dfSStefan Roese 	} while (reg);		/* Wait for '0' */
521ff9112dfSStefan Roese 
522ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_ADDR);
523ff9112dfSStefan Roese 	/* Check if Successful */
524ff9112dfSStefan Roese 	if (reg & (1 << REG_DRAM_TRAINING_ERROR_OFFS)) {
525ff9112dfSStefan Roese 		/*
526ff9112dfSStefan Roese 		 * Read results to arrays - Results are required for WL High
527ff9112dfSStefan Roese 		 * freq Supplement and DQS Centralization
528ff9112dfSStefan Roese 		 */
529ff9112dfSStefan Roese 		for (cs = 0; cs < MAX_CS; cs++) {
530ff9112dfSStefan Roese 			if (dram_info->cs_ena & (1 << cs)) {
531ff9112dfSStefan Roese 				for (pup = 0;
532ff9112dfSStefan Roese 				     pup < dram_info->num_of_total_pups;
533ff9112dfSStefan Roese 				     pup++) {
534ff9112dfSStefan Roese 					if (pup == dram_info->num_of_std_pups
535ff9112dfSStefan Roese 					    && dram_info->ecc_ena)
536ff9112dfSStefan Roese 						pup = ECC_BIT;
537ff9112dfSStefan Roese 					reg =
538ff9112dfSStefan Roese 					    ddr3_read_pup_reg(PUP_WL_MODE, cs,
539ff9112dfSStefan Roese 							      pup);
540ff9112dfSStefan Roese 					phase =
541ff9112dfSStefan Roese 					    (reg >> REG_PHY_PHASE_OFFS) &
542ff9112dfSStefan Roese 					    PUP_PHASE_MASK;
543ff9112dfSStefan Roese 					delay = reg & PUP_DELAY_MASK;
544ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][P] = phase;
545ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][D] = delay;
546ff9112dfSStefan Roese 					if ((phase == 1) && (delay >= 0x1D)) {
547ff9112dfSStefan Roese 						/*
548ff9112dfSStefan Roese 						 * Need to do it here for
549ff9112dfSStefan Roese 						 * uncorrect WL values
550ff9112dfSStefan Roese 						 */
551ff9112dfSStefan Roese 						ddr3_write_pup_reg(PUP_WL_MODE,
552ff9112dfSStefan Roese 								   cs, pup, 0,
553ff9112dfSStefan Roese 								   0);
554ff9112dfSStefan Roese 						dram_info->wl_val[cs][pup][P] =
555ff9112dfSStefan Roese 						    0;
556ff9112dfSStefan Roese 						dram_info->wl_val[cs][pup][D] =
557ff9112dfSStefan Roese 						    0;
558ff9112dfSStefan Roese 					}
559ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][S] =
560ff9112dfSStefan Roese 					    WL_HI_FREQ_STATE - 1;
561ff9112dfSStefan Roese 					reg =
562ff9112dfSStefan Roese 					    ddr3_read_pup_reg(PUP_WL_MODE + 0x1,
563ff9112dfSStefan Roese 							      cs, pup);
564ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][DQS] =
565ff9112dfSStefan Roese 					    (reg & 0x3F);
566ff9112dfSStefan Roese 				}
567ff9112dfSStefan Roese #ifdef MV_DEBUG_WL
568ff9112dfSStefan Roese 				/*
569ff9112dfSStefan Roese 				 * Debug message - Print res for cs[i]:
570ff9112dfSStefan Roese 				 * cs,PUP,Phase,Delay
571ff9112dfSStefan Roese 				 */
572ff9112dfSStefan Roese 				DEBUG_WL_S("DDR3 - Write Leveling - Write Leveling Cs - ");
573ff9112dfSStefan Roese 				DEBUG_WL_D((u32) cs, 1);
574ff9112dfSStefan Roese 				DEBUG_WL_S(" Results:\n");
575ff9112dfSStefan Roese 				for (pup = 0;
576ff9112dfSStefan Roese 				     pup < dram_info->num_of_total_pups;
577ff9112dfSStefan Roese 				     pup++) {
578ff9112dfSStefan Roese 					DEBUG_WL_S
579ff9112dfSStefan Roese 					    ("DDR3 - Write Leveling - PUP: ");
580ff9112dfSStefan Roese 					DEBUG_WL_D((u32) pup, 1);
581ff9112dfSStefan Roese 					DEBUG_WL_S(", Phase: ");
582ff9112dfSStefan Roese 					DEBUG_WL_D((u32)
583ff9112dfSStefan Roese 						   dram_info->wl_val[cs][pup]
584ff9112dfSStefan Roese 						   [P], 1);
585ff9112dfSStefan Roese 					DEBUG_WL_S(", Delay: ");
586ff9112dfSStefan Roese 					DEBUG_WL_D((u32)
587ff9112dfSStefan Roese 						   dram_info->wl_val[cs][pup]
588ff9112dfSStefan Roese 						   [D], 2);
589ff9112dfSStefan Roese 					DEBUG_WL_S("\n");
590ff9112dfSStefan Roese 				}
591ff9112dfSStefan Roese #endif
592ff9112dfSStefan Roese 			}
593ff9112dfSStefan Roese 		}
594ff9112dfSStefan Roese 
595ff9112dfSStefan Roese #ifdef MV88F67XX
596ff9112dfSStefan Roese 		/* Dynamic pad issue (BTS669) during WL */
597ff9112dfSStefan Roese 		if (dpde_flag) {
598ff9112dfSStefan Roese 			reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
599ff9112dfSStefan Roese 				(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
600ff9112dfSStefan Roese 			reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
601ff9112dfSStefan Roese 		}
602ff9112dfSStefan Roese #endif
603ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
604ff9112dfSStefan Roese 
605ff9112dfSStefan Roese 		/* If target freq = 400 move clock back */
606ff9112dfSStefan Roese 		/* Write to control PUP to Control Deskew Regs */
607ff9112dfSStefan Roese 		if (freq <= DDR_400) {
608ff9112dfSStefan Roese 			for (pup = 0; pup <= dram_info->num_of_total_pups;
609ff9112dfSStefan Roese 			     pup++) {
610ff9112dfSStefan Roese 				ddr3_write_ctrl_pup_reg(1, pup,
611ff9112dfSStefan Roese 							CNTRL_PUP_DESKEW + pup, 0);
612ff9112dfSStefan Roese 			}
613ff9112dfSStefan Roese 		}
614ff9112dfSStefan Roese 
615ff9112dfSStefan Roese 		return MV_OK;
616ff9112dfSStefan Roese 	} else {
617ff9112dfSStefan Roese 		/* Configure Each PUP with locked leveling settings */
618ff9112dfSStefan Roese 		for (cs = 0; cs < MAX_CS; cs++) {
619ff9112dfSStefan Roese 			if (dram_info->cs_ena & (1 << cs)) {
620ff9112dfSStefan Roese 				for (pup = 0;
621ff9112dfSStefan Roese 				     pup < dram_info->num_of_total_pups;
622ff9112dfSStefan Roese 				     pup++) {
623ff9112dfSStefan Roese 					/* ECC support - bit 8 */
624ff9112dfSStefan Roese 					pup_num = (pup == dram_info->num_of_std_pups) ?
625ff9112dfSStefan Roese 						ECC_BIT : pup;
626ff9112dfSStefan Roese 					ddr3_write_pup_reg(PUP_WL_MODE, cs,
627ff9112dfSStefan Roese 							   pup_num, 0, 0);
628ff9112dfSStefan Roese 				}
629ff9112dfSStefan Roese 			}
630ff9112dfSStefan Roese 		}
631ff9112dfSStefan Roese 
632ff9112dfSStefan Roese 		reg_write(REG_DRAM_TRAINING_ADDR, 0);
633ff9112dfSStefan Roese 
634ff9112dfSStefan Roese 		/* If target freq = 400 move clock back */
635ff9112dfSStefan Roese 		/* Write to control PUP to Control Deskew Regs */
636ff9112dfSStefan Roese 		if (freq <= DDR_400) {
637ff9112dfSStefan Roese 			for (pup = 0; pup <= dram_info->num_of_total_pups;
638ff9112dfSStefan Roese 			     pup++) {
639ff9112dfSStefan Roese 				ddr3_write_ctrl_pup_reg(1, pup,
640ff9112dfSStefan Roese 							CNTRL_PUP_DESKEW + pup, 0);
641ff9112dfSStefan Roese 			}
642ff9112dfSStefan Roese 		}
643ff9112dfSStefan Roese 
644ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - HW WL Ended Successfully\n");
645ff9112dfSStefan Roese 		return MV_NO_CHANGE;
646ff9112dfSStefan Roese 	}
647ff9112dfSStefan Roese }
648ff9112dfSStefan Roese 
649ff9112dfSStefan Roese /*
650ff9112dfSStefan Roese  * Name:     ddr3_write_leveling_sw
651ff9112dfSStefan Roese  * Desc:     Execute Write leveling phase by SW
652ff9112dfSStefan Roese  * Args:     freq      - current sequence frequency
653ff9112dfSStefan Roese  *           dram_info   - main struct
654ff9112dfSStefan Roese  * Notes:
655ff9112dfSStefan Roese  * Returns:  MV_OK if success, MV_FAIL if fail.
656ff9112dfSStefan Roese  */
ddr3_write_leveling_sw(u32 freq,int ratio_2to1,MV_DRAM_INFO * dram_info)657ff9112dfSStefan Roese int ddr3_write_leveling_sw(u32 freq, int ratio_2to1, MV_DRAM_INFO *dram_info)
658ff9112dfSStefan Roese {
659ff9112dfSStefan Roese 	u32 reg, cs, cnt, pup, max_pup_num;
660ff9112dfSStefan Roese 	u32 res[MAX_CS];
661ff9112dfSStefan Roese 	max_pup_num = dram_info->num_of_total_pups;
662ff9112dfSStefan Roese 	__maybe_unused int dpde_flag = 0;
663ff9112dfSStefan Roese 
664ff9112dfSStefan Roese 	/* Debug message - Start Write leveling procedure */
665ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling - Starting SW WL procedure\n");
666ff9112dfSStefan Roese 
667ff9112dfSStefan Roese #ifdef MV88F67XX
668ff9112dfSStefan Roese 	/* Dynamic pad issue (BTS669) during WL */
669ff9112dfSStefan Roese 	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
670ff9112dfSStefan Roese 	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
671ff9112dfSStefan Roese 		dpde_flag = 1;
672ff9112dfSStefan Roese 		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
673ff9112dfSStefan Roese 			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
674ff9112dfSStefan Roese 	}
675ff9112dfSStefan Roese #endif
676ff9112dfSStefan Roese 
677ff9112dfSStefan Roese 	/* Set Output buffer-off to all CS and correct ODT values */
678ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
679ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
680ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
681ff9112dfSStefan Roese 				REG_DDR3_MR1_ODT_MASK;
682ff9112dfSStefan Roese 			reg |= odt_static[dram_info->cs_ena][cs];
683ff9112dfSStefan Roese 			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
684ff9112dfSStefan Roese 
685ff9112dfSStefan Roese 			/* 0x15D0 - DDR3 MR0 Register */
686ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
687ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
688ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
689ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
690ff9112dfSStefan Roese 			/*
691ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
692ff9112dfSStefan Roese 			 * enable current cs
693ff9112dfSStefan Roese 			 */
694ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
695ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
696ff9112dfSStefan Roese 
697ff9112dfSStefan Roese 			udelay(MRS_DELAY);
698ff9112dfSStefan Roese 		}
699ff9112dfSStefan Roese 	}
700ff9112dfSStefan Roese 
701ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Qoff and RTT Values are set for all Cs\n");
702ff9112dfSStefan Roese 
703ff9112dfSStefan Roese 	/* Enable SW override */
704ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
705ff9112dfSStefan Roese 		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
706ff9112dfSStefan Roese 	/* [0] = 1 - Enable SW override  */
707ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
708ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
709ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling - SW Override Enabled\n");
710ff9112dfSStefan Roese 
711ff9112dfSStefan Roese 	/* Enable PHY write leveling mode */
712ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
713ff9112dfSStefan Roese 		~(1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
714ff9112dfSStefan Roese 	/* [2] = 0 - TrnWLMode - Enable */
715ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
716ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
717ff9112dfSStefan Roese 	/* Reset WL results arry */
718ff9112dfSStefan Roese 	memset(dram_info->wl_val, 0, sizeof(u32) * MAX_CS * MAX_PUP_NUM * 7);
719ff9112dfSStefan Roese 
720ff9112dfSStefan Roese 	/* Loop for each cs */
721ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
722ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
723ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Starting working with Cs - ",
724ff9112dfSStefan Roese 					(u32) cs, 1);
725ff9112dfSStefan Roese 			/* Refresh X9 current cs */
726ff9112dfSStefan Roese 			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Refresh X9\n");
727ff9112dfSStefan Roese 			for (cnt = 0; cnt < COUNT_WL_RFRS; cnt++) {
728ff9112dfSStefan Roese 				reg =
729ff9112dfSStefan Roese 				    REG_SDRAM_OPERATION_CMD_RFRS & ~(1 <<
730ff9112dfSStefan Roese 								     (REG_SDRAM_OPERATION_CS_OFFS
731ff9112dfSStefan Roese 								      + cs));
732ff9112dfSStefan Roese 				/* [3-0] = 0x2 - refresh, [11-8] - enable current cs */
733ff9112dfSStefan Roese 				reg_write(REG_SDRAM_OPERATION_ADDR, reg);	/* 0x1418 - SDRAM Operation Register */
734ff9112dfSStefan Roese 
735ff9112dfSStefan Roese 				do {
736ff9112dfSStefan Roese 					reg =
737ff9112dfSStefan Roese 					    ((reg_read
738ff9112dfSStefan Roese 					      (REG_SDRAM_OPERATION_ADDR)) &
739ff9112dfSStefan Roese 					     REG_SDRAM_OPERATION_CMD_RFRS_DONE);
740ff9112dfSStefan Roese 				} while (reg);	/* Wait for '0' */
741ff9112dfSStefan Roese 			}
742ff9112dfSStefan Roese 
743ff9112dfSStefan Roese 			/* Configure MR1 in Cs[CsNum] - write leveling on, output buffer on */
744ff9112dfSStefan Roese 			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Configure MR1 for current Cs: WL-on,OB-on\n");
745ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
746ff9112dfSStefan Roese 				REG_DDR3_MR1_OUTBUF_WL_MASK;
747ff9112dfSStefan Roese 			/* Set ODT Values */
748ff9112dfSStefan Roese 			reg &= REG_DDR3_MR1_ODT_MASK;
749ff9112dfSStefan Roese 			reg |= odt_static[dram_info->cs_ena][cs];
750ff9112dfSStefan Roese 			/* Enable WL MODE */
751ff9112dfSStefan Roese 			reg |= (1 << REG_DDR3_MR1_WL_ENA_OFFS);
752ff9112dfSStefan Roese 			/* [7]=1, [12]=0 - Output Buffer and write leveling enabled */
753ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);	/* 0x15D4 - DDR3 MR1 Register */
754ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
755ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
756ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
757ff9112dfSStefan Roese 			/*
758ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
759ff9112dfSStefan Roese 			 * enable current cs
760ff9112dfSStefan Roese 			 */
761ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
762ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
763ff9112dfSStefan Roese 
764ff9112dfSStefan Roese 			udelay(MRS_DELAY);
765ff9112dfSStefan Roese 
766ff9112dfSStefan Roese 			/* Write leveling  cs[cs] */
767ff9112dfSStefan Roese 			if (MV_OK !=
768ff9112dfSStefan Roese 			    ddr3_write_leveling_single_cs(cs, freq, ratio_2to1,
769ff9112dfSStefan Roese 							  (u32 *)(res + cs),
770ff9112dfSStefan Roese 							  dram_info)) {
771ff9112dfSStefan Roese 				DEBUG_WL_FULL_C("DDR3 - Write Leveling single Cs - FAILED -  Cs - ",
772ff9112dfSStefan Roese 						(u32) cs, 1);
773ff9112dfSStefan Roese 				for (pup = 0; pup < max_pup_num; pup++) {
774ff9112dfSStefan Roese 					if (((res[cs] >> pup) & 0x1) == 0) {
775ff9112dfSStefan Roese 						DEBUG_WL_C("Failed Byte : ",
776ff9112dfSStefan Roese 							   pup, 1);
777ff9112dfSStefan Roese 					}
778ff9112dfSStefan Roese 				}
779ff9112dfSStefan Roese 				return MV_FAIL;
780ff9112dfSStefan Roese 			}
781ff9112dfSStefan Roese 
782ff9112dfSStefan Roese 			/* Set TrnWLDeUpd - After each CS is done */
783ff9112dfSStefan Roese 			reg = reg_read(REG_TRAINING_WL_ADDR) |
784ff9112dfSStefan Roese 				(1 << REG_TRAINING_WL_CS_DONE_OFFS);
785ff9112dfSStefan Roese 			/* 0x16AC - Training Write leveling register */
786ff9112dfSStefan Roese 			reg_write(REG_TRAINING_WL_ADDR, reg);
787ff9112dfSStefan Roese 
788ff9112dfSStefan Roese 			/*
789ff9112dfSStefan Roese 			 * Debug message - Finished Write leveling cs[cs] -
790ff9112dfSStefan Roese 			 * each PUP Fail/Success
791ff9112dfSStefan Roese 			 */
792ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Finished Cs - ", (u32) cs,
793ff9112dfSStefan Roese 					1);
794ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling - The Results: 1-PUP locked, 0-PUP failed -",
795ff9112dfSStefan Roese 					(u32) res[cs], 3);
796ff9112dfSStefan Roese 
797ff9112dfSStefan Roese 			/*
798ff9112dfSStefan Roese 			 * Configure MR1 in cs[cs] - write leveling off (0),
799ff9112dfSStefan Roese 			 * output buffer off (1)
800ff9112dfSStefan Roese 			 */
801ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
802ff9112dfSStefan Roese 				REG_DDR3_MR1_OUTBUF_WL_MASK;
803ff9112dfSStefan Roese 			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
804ff9112dfSStefan Roese 			/* No need to sort ODT since it is same CS */
805ff9112dfSStefan Roese 			/* 0x15D4 - DDR3 MR1 Register */
806ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
807ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
808ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
809ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
810ff9112dfSStefan Roese 			/*
811ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
812ff9112dfSStefan Roese 			 * enable current cs
813ff9112dfSStefan Roese 			 */
814ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
815ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
816ff9112dfSStefan Roese 
817ff9112dfSStefan Roese 			udelay(MRS_DELAY);
818ff9112dfSStefan Roese 		}
819ff9112dfSStefan Roese 	}
820ff9112dfSStefan Roese 
821ff9112dfSStefan Roese 	/* Disable WL Mode */
822ff9112dfSStefan Roese 	/* [2]=1 - TrnWLMode - Disable */
823ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
824ff9112dfSStefan Roese 	reg |= (1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
825ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
826ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
827ff9112dfSStefan Roese 
828ff9112dfSStefan Roese 	/* Disable SW override - Must be in a different stage */
829ff9112dfSStefan Roese 	/* [0]=0 - Enable SW override  */
830ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
831ff9112dfSStefan Roese 	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
832ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
833ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
834ff9112dfSStefan Roese 
835ff9112dfSStefan Roese 	/* Set Output buffer-on to all CS and correct ODT values */
836ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
837ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
838ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
839ff9112dfSStefan Roese 				REG_DDR3_MR1_ODT_MASK;
840ff9112dfSStefan Roese 			reg &= REG_DDR3_MR1_OUTBUF_WL_MASK;
841ff9112dfSStefan Roese 			reg |= odt_static[dram_info->cs_ena][cs];
842ff9112dfSStefan Roese 
843ff9112dfSStefan Roese 			/* 0x15D0 - DDR3 MR1 Register */
844ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
845ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
846ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
847ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
848ff9112dfSStefan Roese 			/*
849ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
850ff9112dfSStefan Roese 			 * enable current cs
851ff9112dfSStefan Roese 			 */
852ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
853ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
854ff9112dfSStefan Roese 
855ff9112dfSStefan Roese 			udelay(MRS_DELAY);
856ff9112dfSStefan Roese 		}
857ff9112dfSStefan Roese 	}
858ff9112dfSStefan Roese 
859ff9112dfSStefan Roese #ifdef MV88F67XX
860ff9112dfSStefan Roese 	/* Dynamic pad issue (BTS669) during WL */
861ff9112dfSStefan Roese 	if (dpde_flag) {
862ff9112dfSStefan Roese 		reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
863ff9112dfSStefan Roese 			(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
864ff9112dfSStefan Roese 		reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
865ff9112dfSStefan Roese 	}
866ff9112dfSStefan Roese #endif
867ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Finished WL procedure for all Cs\n");
868ff9112dfSStefan Roese 
869ff9112dfSStefan Roese 	return MV_OK;
870ff9112dfSStefan Roese }
871ff9112dfSStefan Roese 
872ff9112dfSStefan Roese #if !defined(MV88F672X)
873ff9112dfSStefan Roese /*
874ff9112dfSStefan Roese  * Name:     ddr3_write_leveling_sw
875ff9112dfSStefan Roese  * Desc:     Execute Write leveling phase by SW
876ff9112dfSStefan Roese  * Args:     freq        - current sequence frequency
877ff9112dfSStefan Roese  *           dram_info   - main struct
878ff9112dfSStefan Roese  * Notes:
879ff9112dfSStefan Roese  * Returns:  MV_OK if success, MV_FAIL if fail.
880ff9112dfSStefan Roese  */
ddr3_write_leveling_sw_reg_dimm(u32 freq,int ratio_2to1,MV_DRAM_INFO * dram_info)881ff9112dfSStefan Roese int ddr3_write_leveling_sw_reg_dimm(u32 freq, int ratio_2to1,
882ff9112dfSStefan Roese 				    MV_DRAM_INFO *dram_info)
883ff9112dfSStefan Roese {
884ff9112dfSStefan Roese 	u32 reg, cs, cnt, pup;
885ff9112dfSStefan Roese 	u32 res[MAX_CS];
886ff9112dfSStefan Roese 	__maybe_unused int dpde_flag = 0;
887ff9112dfSStefan Roese 
888ff9112dfSStefan Roese 	/* Debug message - Start Write leveling procedure */
889ff9112dfSStefan Roese 	DEBUG_WL_S("DDR3 - Write Leveling - Starting SW WL procedure\n");
890ff9112dfSStefan Roese 
891ff9112dfSStefan Roese #ifdef MV88F67XX
892ff9112dfSStefan Roese 	/* Dynamic pad issue (BTS669) during WL */
893ff9112dfSStefan Roese 	reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR);
894ff9112dfSStefan Roese 	if (reg & (1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS)) {
895ff9112dfSStefan Roese 		dpde_flag = 1;
896ff9112dfSStefan Roese 		reg_write(REG_DUNIT_CTRL_LOW_ADDR,
897ff9112dfSStefan Roese 			  reg & ~(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS));
898ff9112dfSStefan Roese 	}
899ff9112dfSStefan Roese #endif
900ff9112dfSStefan Roese 
901ff9112dfSStefan Roese 	/* If target freq = 400 move clock start point */
902ff9112dfSStefan Roese 	/* Write to control PUP to Control Deskew Regs */
903ff9112dfSStefan Roese 	if (freq <= DDR_400) {
904ff9112dfSStefan Roese 		for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
905ff9112dfSStefan Roese 			/* PUP_DELAY_MASK 0x1F */
906ff9112dfSStefan Roese 			/* reg = 0x0C10001F + (uj << 16); */
907ff9112dfSStefan Roese 			ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
908ff9112dfSStefan Roese 						0x1F);
909ff9112dfSStefan Roese 		}
910ff9112dfSStefan Roese 	}
911ff9112dfSStefan Roese 
912ff9112dfSStefan Roese 	/* Set Output buffer-off to all CS and correct ODT values */
913ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
914ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
915ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
916ff9112dfSStefan Roese 				REG_DDR3_MR1_ODT_MASK;
917ff9112dfSStefan Roese 			reg |= odt_static[dram_info->cs_ena][cs];
918ff9112dfSStefan Roese 			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
919ff9112dfSStefan Roese 
920ff9112dfSStefan Roese 			/* 0x15D0 - DDR3 MR0 Register */
921ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
922ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
923ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
924ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
925ff9112dfSStefan Roese 			/*
926ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
927ff9112dfSStefan Roese 			 * enable current cs
928ff9112dfSStefan Roese 			 */
929ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
930ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
931ff9112dfSStefan Roese 
932ff9112dfSStefan Roese 			udelay(MRS_DELAY);
933ff9112dfSStefan Roese 		}
934ff9112dfSStefan Roese 	}
935ff9112dfSStefan Roese 
936ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Qoff and RTT Values are set for all Cs\n");
937ff9112dfSStefan Roese 
938ff9112dfSStefan Roese 	/* Enable SW override */
939ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
940ff9112dfSStefan Roese 		(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
941ff9112dfSStefan Roese 	/* [0] = 1 - Enable SW override  */
942ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
943ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
944ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling - SW Override Enabled\n");
945ff9112dfSStefan Roese 
946ff9112dfSStefan Roese 	/* Enable PHY write leveling mode */
947ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
948ff9112dfSStefan Roese 		~(1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
949ff9112dfSStefan Roese 	/* [2] = 0 - TrnWLMode - Enable */
950ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
951ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
952ff9112dfSStefan Roese 
953ff9112dfSStefan Roese 	/* Loop for each cs */
954ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
955ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
956ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Starting working with Cs - ",
957ff9112dfSStefan Roese 					(u32) cs, 1);
958ff9112dfSStefan Roese 
959ff9112dfSStefan Roese 			/* Refresh X9 current cs */
960ff9112dfSStefan Roese 			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Refresh X9\n");
961ff9112dfSStefan Roese 			for (cnt = 0; cnt < COUNT_WL_RFRS; cnt++) {
962ff9112dfSStefan Roese 				reg =
963ff9112dfSStefan Roese 				    REG_SDRAM_OPERATION_CMD_RFRS & ~(1 <<
964ff9112dfSStefan Roese 								     (REG_SDRAM_OPERATION_CS_OFFS
965ff9112dfSStefan Roese 								      + cs));
966ff9112dfSStefan Roese 				/* [3-0] = 0x2 - refresh, [11-8] - enable current cs */
967ff9112dfSStefan Roese 				reg_write(REG_SDRAM_OPERATION_ADDR, reg);	/* 0x1418 - SDRAM Operation Register */
968ff9112dfSStefan Roese 
969ff9112dfSStefan Roese 				do {
970ff9112dfSStefan Roese 					reg =
971ff9112dfSStefan Roese 					    ((reg_read
972ff9112dfSStefan Roese 					      (REG_SDRAM_OPERATION_ADDR)) &
973ff9112dfSStefan Roese 					     REG_SDRAM_OPERATION_CMD_RFRS_DONE);
974ff9112dfSStefan Roese 				} while (reg);	/* Wait for '0' */
975ff9112dfSStefan Roese 			}
976ff9112dfSStefan Roese 
977ff9112dfSStefan Roese 			/*
978ff9112dfSStefan Roese 			 * Configure MR1 in Cs[CsNum] - write leveling on,
979ff9112dfSStefan Roese 			 * output buffer on
980ff9112dfSStefan Roese 			 */
981ff9112dfSStefan Roese 			DEBUG_WL_FULL_S("DDR3 - Write Leveling - Configure MR1 for current Cs: WL-on,OB-on\n");
982ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
983ff9112dfSStefan Roese 				REG_DDR3_MR1_OUTBUF_WL_MASK;
984ff9112dfSStefan Roese 			/* Set ODT Values */
985ff9112dfSStefan Roese 			reg &= REG_DDR3_MR1_ODT_MASK;
986ff9112dfSStefan Roese 			reg |= odt_static[dram_info->cs_ena][cs];
987ff9112dfSStefan Roese 			/* Enable WL MODE */
988ff9112dfSStefan Roese 			reg |= (1 << REG_DDR3_MR1_WL_ENA_OFFS);
989ff9112dfSStefan Roese 			/*
990ff9112dfSStefan Roese 			 * [7]=1, [12]=0 - Output Buffer and write leveling
991ff9112dfSStefan Roese 			 * enabled
992ff9112dfSStefan Roese 			 */
993ff9112dfSStefan Roese 			/* 0x15D4 - DDR3 MR1 Register */
994ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
995ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
996ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
997ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
998ff9112dfSStefan Roese 			/*
999ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
1000ff9112dfSStefan Roese 			 * enable current cs
1001ff9112dfSStefan Roese 			 */
1002ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
1003ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
1004ff9112dfSStefan Roese 
1005ff9112dfSStefan Roese 			udelay(MRS_DELAY);
1006ff9112dfSStefan Roese 
1007ff9112dfSStefan Roese 			/* Write leveling  cs[cs] */
1008ff9112dfSStefan Roese 			if (MV_OK !=
1009ff9112dfSStefan Roese 			    ddr3_write_leveling_single_cs(cs, freq, ratio_2to1,
1010ff9112dfSStefan Roese 							  (u32 *)(res + cs),
1011ff9112dfSStefan Roese 							  dram_info)) {
1012ff9112dfSStefan Roese 				DEBUG_WL_FULL_C("DDR3 - Write Leveling single Cs - FAILED -  Cs - ",
1013ff9112dfSStefan Roese 						(u32) cs, 1);
1014ff9112dfSStefan Roese 				return MV_FAIL;
1015ff9112dfSStefan Roese 			}
1016ff9112dfSStefan Roese 
1017ff9112dfSStefan Roese 			/* Set TrnWLDeUpd - After each CS is done */
1018ff9112dfSStefan Roese 			reg = reg_read(REG_TRAINING_WL_ADDR) |
1019ff9112dfSStefan Roese 				(1 << REG_TRAINING_WL_CS_DONE_OFFS);
1020ff9112dfSStefan Roese 			/* 0x16AC - Training Write leveling register */
1021ff9112dfSStefan Roese 			reg_write(REG_TRAINING_WL_ADDR, reg);
1022ff9112dfSStefan Roese 
1023ff9112dfSStefan Roese 			/*
1024ff9112dfSStefan Roese 			 * Debug message - Finished Write leveling cs[cs] -
1025ff9112dfSStefan Roese 			 * each PUP Fail/Success
1026ff9112dfSStefan Roese 			 */
1027ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling - Finished Cs - ", (u32) cs,
1028ff9112dfSStefan Roese 					1);
1029ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling - The Results: 1-PUP locked, 0-PUP failed -",
1030ff9112dfSStefan Roese 					(u32) res[cs], 3);
1031ff9112dfSStefan Roese 
1032ff9112dfSStefan Roese 			/* Configure MR1 in cs[cs] - write leveling off (0), output buffer off (1) */
1033ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
1034ff9112dfSStefan Roese 				REG_DDR3_MR1_OUTBUF_WL_MASK;
1035ff9112dfSStefan Roese 			reg |= (1 << REG_DDR3_MR1_OUTBUF_DIS_OFFS);
1036ff9112dfSStefan Roese 			/* No need to sort ODT since it is same CS */
1037ff9112dfSStefan Roese 			/* 0x15D4 - DDR3 MR1 Register */
1038ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
1039ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
1040ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
1041ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
1042ff9112dfSStefan Roese 			/*
1043ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
1044ff9112dfSStefan Roese 			 * enable current cs
1045ff9112dfSStefan Roese 			 */
1046ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
1047ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
1048ff9112dfSStefan Roese 
1049ff9112dfSStefan Roese 			udelay(MRS_DELAY);
1050ff9112dfSStefan Roese 		}
1051ff9112dfSStefan Roese 	}
1052ff9112dfSStefan Roese 
1053ff9112dfSStefan Roese 	/* Disable WL Mode */
1054ff9112dfSStefan Roese 	/* [2]=1 - TrnWLMode - Disable */
1055ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
1056ff9112dfSStefan Roese 	reg |= (1 << REG_DRAM_TRAINING_2_WL_MODE_OFFS);
1057ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
1058ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
1059ff9112dfSStefan Roese 
1060ff9112dfSStefan Roese 	/* Disable SW override - Must be in a different stage */
1061ff9112dfSStefan Roese 	/* [0]=0 - Enable SW override  */
1062ff9112dfSStefan Roese 	reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
1063ff9112dfSStefan Roese 	reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
1064ff9112dfSStefan Roese 	/* 0x15B8 - Training SW 2 Register */
1065ff9112dfSStefan Roese 	reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
1066ff9112dfSStefan Roese 
1067ff9112dfSStefan Roese 	/* Set Output buffer-on to all CS and correct ODT values */
1068ff9112dfSStefan Roese 	for (cs = 0; cs < MAX_CS; cs++) {
1069ff9112dfSStefan Roese 		if (dram_info->cs_ena & (1 << cs)) {
1070ff9112dfSStefan Roese 			reg = reg_read(REG_DDR3_MR1_ADDR) &
1071ff9112dfSStefan Roese 				REG_DDR3_MR1_ODT_MASK;
1072ff9112dfSStefan Roese 			reg &= REG_DDR3_MR1_OUTBUF_WL_MASK;
1073ff9112dfSStefan Roese 			reg |= odt_static[dram_info->cs_ena][cs];
1074ff9112dfSStefan Roese 
1075ff9112dfSStefan Roese 			/* 0x15D0 - DDR3 MR1 Register */
1076ff9112dfSStefan Roese 			reg_write(REG_DDR3_MR1_ADDR, reg);
1077ff9112dfSStefan Roese 			/* Issue MRS Command to current cs */
1078ff9112dfSStefan Roese 			reg = REG_SDRAM_OPERATION_CMD_MR1 &
1079ff9112dfSStefan Roese 				~(1 << (REG_SDRAM_OPERATION_CS_OFFS + cs));
1080ff9112dfSStefan Roese 			/*
1081ff9112dfSStefan Roese 			 * [3-0] = 0x4 - MR1 Command, [11-8] -
1082ff9112dfSStefan Roese 			 * enable current cs
1083ff9112dfSStefan Roese 			 */
1084ff9112dfSStefan Roese 			/* 0x1418 - SDRAM Operation Register */
1085ff9112dfSStefan Roese 			reg_write(REG_SDRAM_OPERATION_ADDR, reg);
1086ff9112dfSStefan Roese 
1087ff9112dfSStefan Roese 			udelay(MRS_DELAY);
1088ff9112dfSStefan Roese 		}
1089ff9112dfSStefan Roese 	}
1090ff9112dfSStefan Roese 
1091ff9112dfSStefan Roese #ifdef MV88F67XX
1092ff9112dfSStefan Roese 	/* Dynamic pad issue (BTS669) during WL */
1093ff9112dfSStefan Roese 	if (dpde_flag) {
1094ff9112dfSStefan Roese 		reg = reg_read(REG_DUNIT_CTRL_LOW_ADDR) |
1095ff9112dfSStefan Roese 			(1 << REG_DUNIT_CTRL_LOW_DPDE_OFFS);
1096ff9112dfSStefan Roese 		reg_write(REG_DUNIT_CTRL_LOW_ADDR, reg);
1097ff9112dfSStefan Roese 	}
1098ff9112dfSStefan Roese #endif
1099ff9112dfSStefan Roese 
1100ff9112dfSStefan Roese 	/* If target freq = 400 move clock back */
1101ff9112dfSStefan Roese 	/* Write to control PUP to Control Deskew Regs */
1102ff9112dfSStefan Roese 	if (freq <= DDR_400) {
1103ff9112dfSStefan Roese 		for (pup = 0; pup <= dram_info->num_of_total_pups; pup++) {
1104ff9112dfSStefan Roese 			ddr3_write_ctrl_pup_reg(1, pup, CNTRL_PUP_DESKEW + pup,
1105ff9112dfSStefan Roese 						0);
1106ff9112dfSStefan Roese 		}
1107ff9112dfSStefan Roese 	}
1108ff9112dfSStefan Roese 
1109ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling - Finished WL procedure for all Cs\n");
1110ff9112dfSStefan Roese 	return MV_OK;
1111ff9112dfSStefan Roese }
1112ff9112dfSStefan Roese #endif
1113ff9112dfSStefan Roese 
1114ff9112dfSStefan Roese /*
1115ff9112dfSStefan Roese  * Name:     ddr3_write_leveling_single_cs
1116ff9112dfSStefan Roese  * Desc:     Execute Write leveling for single Chip select
1117ff9112dfSStefan Roese  * Args:     cs          - current chip select
1118ff9112dfSStefan Roese  *           freq        - current sequence frequency
1119ff9112dfSStefan Roese  *           result      - res array
1120ff9112dfSStefan Roese  *           dram_info   - main struct
1121ff9112dfSStefan Roese  * Notes:
1122ff9112dfSStefan Roese  * Returns:  MV_OK if success, MV_FAIL if fail.
1123ff9112dfSStefan Roese  */
ddr3_write_leveling_single_cs(u32 cs,u32 freq,int ratio_2to1,u32 * result,MV_DRAM_INFO * dram_info)1124ff9112dfSStefan Roese static int ddr3_write_leveling_single_cs(u32 cs, u32 freq, int ratio_2to1,
1125ff9112dfSStefan Roese 					 u32 *result, MV_DRAM_INFO *dram_info)
1126ff9112dfSStefan Roese {
1127ff9112dfSStefan Roese 	u32 reg, pup_num, delay, phase, phaseMax, max_pup_num, pup,
1128ff9112dfSStefan Roese 		max_pup_mask;
1129ff9112dfSStefan Roese 
1130ff9112dfSStefan Roese 	max_pup_num = dram_info->num_of_total_pups;
1131ff9112dfSStefan Roese 	*result = 0;
1132ff9112dfSStefan Roese 	u32 flag[MAX_PUP_NUM] = { 0 };
1133ff9112dfSStefan Roese 
1134ff9112dfSStefan Roese 	DEBUG_WL_FULL_C("DDR3 - Write Leveling Single Cs - WL for Cs - ",
1135ff9112dfSStefan Roese 			(u32) cs, 1);
1136ff9112dfSStefan Roese 
1137ff9112dfSStefan Roese 	switch (max_pup_num) {
1138ff9112dfSStefan Roese 	case 2:
1139ff9112dfSStefan Roese 		max_pup_mask = 0x3;
1140ff9112dfSStefan Roese 		break;
1141ff9112dfSStefan Roese 	case 4:
1142ff9112dfSStefan Roese 		max_pup_mask = 0xf;
1143ff9112dfSStefan Roese 		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
1144ff9112dfSStefan Roese 		break;
1145ff9112dfSStefan Roese 	case 5:
1146ff9112dfSStefan Roese 		max_pup_mask = 0x1f;
1147ff9112dfSStefan Roese 		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
1148ff9112dfSStefan Roese 		break;
1149ff9112dfSStefan Roese 	case 8:
1150ff9112dfSStefan Roese 		max_pup_mask = 0xff;
1151ff9112dfSStefan Roese 		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
1152ff9112dfSStefan Roese 		break;
1153ff9112dfSStefan Roese 	case 9:
1154ff9112dfSStefan Roese 		max_pup_mask = 0x1ff;
1155ff9112dfSStefan Roese 		DEBUG_WL_C("max_pup_mask =  ", max_pup_mask, 3);
1156ff9112dfSStefan Roese 		break;
1157ff9112dfSStefan Roese 	default:
1158ff9112dfSStefan Roese 		DEBUG_WL_C("ddr3_write_leveling_single_cs wrong max_pup_num =  ",
1159ff9112dfSStefan Roese 			   max_pup_num, 3);
1160ff9112dfSStefan Roese 		return MV_FAIL;
1161ff9112dfSStefan Roese 	}
1162ff9112dfSStefan Roese 
1163ff9112dfSStefan Roese 	/* CS ODT Override */
1164ff9112dfSStefan Roese 	reg = reg_read(REG_SDRAM_ODT_CTRL_HIGH_ADDR) &
1165ff9112dfSStefan Roese 		REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK;
1166ff9112dfSStefan Roese 	reg |= (REG_SDRAM_ODT_CTRL_HIGH_OVRD_ENA << (2 * cs));
1167ff9112dfSStefan Roese 	/* Set 0x3 - Enable ODT on the curent cs and disable on other cs */
1168ff9112dfSStefan Roese 	/* 0x1498 - SDRAM ODT Control high */
1169ff9112dfSStefan Roese 	reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
1170ff9112dfSStefan Roese 
1171ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - ODT Asserted for current Cs\n");
1172ff9112dfSStefan Roese 
1173ff9112dfSStefan Roese 	/* tWLMRD Delay */
1174ff9112dfSStefan Roese 	/* Delay of minimum 40 Dram clock cycles - 20 Tclk cycles */
1175ff9112dfSStefan Roese 	udelay(1);
1176ff9112dfSStefan Roese 
1177ff9112dfSStefan Roese 	/* [1:0] - current cs number */
1178ff9112dfSStefan Roese 	reg = (reg_read(REG_TRAINING_WL_ADDR) & REG_TRAINING_WL_CS_MASK) | cs;
1179ff9112dfSStefan Roese 	reg |= (1 << REG_TRAINING_WL_UPD_OFFS);	/* [2] - trnWLCsUpd */
1180ff9112dfSStefan Roese 	/* 0x16AC - Training Write leveling register */
1181ff9112dfSStefan Roese 	reg_write(REG_TRAINING_WL_ADDR, reg);
1182ff9112dfSStefan Roese 
1183ff9112dfSStefan Roese 	/* Broadcast to all PUPs: Reset DQS phase, reset leveling delay */
1184ff9112dfSStefan Roese 	ddr3_write_pup_reg(PUP_WL_MODE, cs, PUP_BC, 0, 0);
1185ff9112dfSStefan Roese 
1186ff9112dfSStefan Roese 	/* Seek Edge */
1187ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Current Cs\n");
1188ff9112dfSStefan Roese 
1189ff9112dfSStefan Roese 	/* Drive DQS high for one cycle - All data PUPs */
1190ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Driving DQS high for one cycle\n");
1191ff9112dfSStefan Roese 	if (!ratio_2to1) {
1192ff9112dfSStefan Roese 		reg = (reg_read(REG_TRAINING_WL_ADDR) &
1193ff9112dfSStefan Roese 		       REG_TRAINING_WL_RATIO_MASK) | REG_TRAINING_WL_1TO1;
1194ff9112dfSStefan Roese 	} else {
1195ff9112dfSStefan Roese 		reg = (reg_read(REG_TRAINING_WL_ADDR) &
1196ff9112dfSStefan Roese 		       REG_TRAINING_WL_RATIO_MASK) | REG_TRAINING_WL_2TO1;
1197ff9112dfSStefan Roese 	}
1198ff9112dfSStefan Roese 	/* 0x16AC - Training Write leveling register */
1199ff9112dfSStefan Roese 	reg_write(REG_TRAINING_WL_ADDR, reg);
1200ff9112dfSStefan Roese 
1201ff9112dfSStefan Roese 	/* Wait tWLdelay */
1202ff9112dfSStefan Roese 	do {
1203ff9112dfSStefan Roese 		/* [29] - trnWLDelayExp */
1204ff9112dfSStefan Roese 		reg = (reg_read(REG_TRAINING_WL_ADDR)) &
1205ff9112dfSStefan Roese 			REG_TRAINING_WL_DELAYEXP_MASK;
1206ff9112dfSStefan Roese 	} while (reg == 0x0);	/* Wait for '1' */
1207ff9112dfSStefan Roese 
1208ff9112dfSStefan Roese 	/* Read WL res */
1209ff9112dfSStefan Roese 	reg = (reg_read(REG_TRAINING_WL_ADDR) >> REG_TRAINING_WL_RESULTS_OFFS) &
1210ff9112dfSStefan Roese 		REG_TRAINING_WL_RESULTS_MASK;
1211ff9112dfSStefan Roese 	/* [28:20] - TrnWLResult */
1212ff9112dfSStefan Roese 
1213ff9112dfSStefan Roese 	if (!ratio_2to1) /* Different phase options for 2:1 or 1:1 modes */
1214ff9112dfSStefan Roese 		phaseMax = MAX_PHASE_1TO1;
1215ff9112dfSStefan Roese 	else
1216ff9112dfSStefan Roese 		phaseMax = MAX_PHASE_2TO1;
1217ff9112dfSStefan Roese 
1218ff9112dfSStefan Roese 	DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge - Shift DQS + Octet Leveling\n");
1219ff9112dfSStefan Roese 
1220ff9112dfSStefan Roese 	/* Shift DQS + Octet leveling */
1221ff9112dfSStefan Roese 	for (phase = 0; phase < phaseMax; phase++) {
1222ff9112dfSStefan Roese 		for (delay = 0; delay < MAX_DELAY; delay++) {
1223ff9112dfSStefan Roese 			/*  Broadcast to all PUPs: DQS phase,leveling delay */
1224ff9112dfSStefan Roese 			ddr3_write_pup_reg(PUP_WL_MODE, cs, PUP_BC, phase,
1225ff9112dfSStefan Roese 					   delay);
1226ff9112dfSStefan Roese 
1227ff9112dfSStefan Roese 			udelay(1);	/* Delay of  3 Tclk cycles */
1228ff9112dfSStefan Roese 
1229ff9112dfSStefan Roese 			DEBUG_WL_FULL_S("DDR3 - Write Leveling Single Cs - Seek Edge: Phase = ");
1230ff9112dfSStefan Roese 			DEBUG_WL_FULL_D((u32) phase, 1);
1231ff9112dfSStefan Roese 			DEBUG_WL_FULL_S(", Delay = ");
1232ff9112dfSStefan Roese 			DEBUG_WL_FULL_D((u32) delay, 1);
1233ff9112dfSStefan Roese 			DEBUG_WL_FULL_S("\n");
1234ff9112dfSStefan Roese 
1235ff9112dfSStefan Roese 			/* Drive DQS high for one cycle - All data PUPs */
1236ff9112dfSStefan Roese 			if (!ratio_2to1) {
1237ff9112dfSStefan Roese 				reg = (reg_read(REG_TRAINING_WL_ADDR) &
1238ff9112dfSStefan Roese 				       REG_TRAINING_WL_RATIO_MASK) |
1239ff9112dfSStefan Roese 					REG_TRAINING_WL_1TO1;
1240ff9112dfSStefan Roese 			} else {
1241ff9112dfSStefan Roese 				reg = (reg_read(REG_TRAINING_WL_ADDR) &
1242ff9112dfSStefan Roese 				       REG_TRAINING_WL_RATIO_MASK) |
1243ff9112dfSStefan Roese 					REG_TRAINING_WL_2TO1;
1244ff9112dfSStefan Roese 			}
1245ff9112dfSStefan Roese 			reg_write(REG_TRAINING_WL_ADDR, reg);	/* 0x16AC  */
1246ff9112dfSStefan Roese 
1247ff9112dfSStefan Roese 			/* Wait tWLdelay */
1248ff9112dfSStefan Roese 			do {
1249ff9112dfSStefan Roese 				reg = (reg_read(REG_TRAINING_WL_ADDR)) &
1250ff9112dfSStefan Roese 					REG_TRAINING_WL_DELAYEXP_MASK;
1251ff9112dfSStefan Roese 			} while (reg == 0x0);	/* [29] Wait for '1' */
1252ff9112dfSStefan Roese 
1253ff9112dfSStefan Roese 			/* Read WL res */
1254ff9112dfSStefan Roese 			reg = reg_read(REG_TRAINING_WL_ADDR);
1255ff9112dfSStefan Roese 			reg = (reg >> REG_TRAINING_WL_RESULTS_OFFS) &
1256ff9112dfSStefan Roese 				REG_TRAINING_WL_RESULTS_MASK;	/* [28:20] */
1257ff9112dfSStefan Roese 
1258ff9112dfSStefan Roese 			DEBUG_WL_FULL_C("DDR3 - Write Leveling Single Cs - Seek Edge: Results =  ",
1259ff9112dfSStefan Roese 					(u32) reg, 3);
1260ff9112dfSStefan Roese 
1261ff9112dfSStefan Roese 			/* Update State machine */
1262ff9112dfSStefan Roese 			for (pup = 0; pup < (max_pup_num); pup++) {
1263ff9112dfSStefan Roese 				/* ECC support - bit 8 */
1264ff9112dfSStefan Roese 				pup_num = (pup == dram_info->num_of_std_pups) ?
1265ff9112dfSStefan Roese 					ECC_BIT : pup;
1266ff9112dfSStefan Roese 				if (dram_info->wl_val[cs][pup][S] == 0) {
1267ff9112dfSStefan Roese 					/* Update phase to PUP */
1268ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][P] = phase;
1269ff9112dfSStefan Roese 					/* Update delay to PUP */
1270ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][D] = delay;
1271ff9112dfSStefan Roese 				}
1272ff9112dfSStefan Roese 
1273ff9112dfSStefan Roese 				if (((reg >> pup_num) & 0x1) == 0)
1274ff9112dfSStefan Roese 					flag[pup_num] = 1;
1275ff9112dfSStefan Roese 
1276ff9112dfSStefan Roese 				if (((reg >> pup_num) & 0x1)
1277ff9112dfSStefan Roese 				    && (flag[pup_num] == 1)
1278ff9112dfSStefan Roese 				    && (dram_info->wl_val[cs][pup][S] == 0)) {
1279ff9112dfSStefan Roese 					/*
1280ff9112dfSStefan Roese 					 * If the PUP is locked now and in last
1281ff9112dfSStefan Roese 					 * counter states
1282ff9112dfSStefan Roese 					 */
1283ff9112dfSStefan Roese 					/* Go to next state */
1284ff9112dfSStefan Roese 					dram_info->wl_val[cs][pup][S] = 1;
1285ff9112dfSStefan Roese 					/* Set res */
1286ff9112dfSStefan Roese 					*result = *result | (1 << pup_num);
1287ff9112dfSStefan Roese 				}
1288ff9112dfSStefan Roese 			}
1289ff9112dfSStefan Roese 
1290ff9112dfSStefan Roese 			/* If all locked - Break the loops - Finished */
1291ff9112dfSStefan Roese 			if (*result == max_pup_mask) {
1292ff9112dfSStefan Roese 				phase = phaseMax;
1293ff9112dfSStefan Roese 				delay = MAX_DELAY;
1294ff9112dfSStefan Roese 				DEBUG_WL_S("DDR3 - Write Leveling Single Cs - Seek Edge: All Locked\n");
1295ff9112dfSStefan Roese 			}
1296ff9112dfSStefan Roese 		}
1297ff9112dfSStefan Roese 	}
1298ff9112dfSStefan Roese 
1299ff9112dfSStefan Roese 	/* Debug message - Print res for cs[i]: cs,PUP,Phase,Delay */
1300ff9112dfSStefan Roese 	DEBUG_WL_C("DDR3 - Write Leveling - Results for CS - ", (u32) cs, 1);
1301ff9112dfSStefan Roese 	for (pup = 0; pup < (max_pup_num); pup++) {
1302ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - PUP: ");
1303ff9112dfSStefan Roese 		DEBUG_WL_D((u32) pup, 1);
1304ff9112dfSStefan Roese 		DEBUG_WL_S(", Phase: ");
1305ff9112dfSStefan Roese 		DEBUG_WL_D((u32) dram_info->wl_val[cs][pup][P], 1);
1306ff9112dfSStefan Roese 		DEBUG_WL_S(", Delay: ");
1307ff9112dfSStefan Roese 		DEBUG_WL_D((u32) dram_info->wl_val[cs][pup][D], 2);
1308ff9112dfSStefan Roese 		DEBUG_WL_S("\n");
1309ff9112dfSStefan Roese 	}
1310ff9112dfSStefan Roese 
1311ff9112dfSStefan Roese 	/* Check if some not locked and return error */
1312ff9112dfSStefan Roese 	if (*result != max_pup_mask) {
1313ff9112dfSStefan Roese 		DEBUG_WL_S("DDR3 - Write Leveling - ERROR - not all PUPS were locked\n");
1314ff9112dfSStefan Roese 		return MV_FAIL;
1315ff9112dfSStefan Roese 	}
1316ff9112dfSStefan Roese 
1317ff9112dfSStefan Roese 	/* Configure Each PUP with locked leveling settings */
1318ff9112dfSStefan Roese 	for (pup = 0; pup < (max_pup_num); pup++) {
1319ff9112dfSStefan Roese 		/* ECC support - bit 8 */
1320ff9112dfSStefan Roese 		pup_num = (pup == dram_info->num_of_std_pups) ? ECC_BIT : pup;
1321ff9112dfSStefan Roese 		phase = dram_info->wl_val[cs][pup][P];
1322ff9112dfSStefan Roese 		delay = dram_info->wl_val[cs][pup][D];
1323ff9112dfSStefan Roese 		ddr3_write_pup_reg(PUP_WL_MODE, cs, pup_num, phase, delay);
1324ff9112dfSStefan Roese 	}
1325ff9112dfSStefan Roese 
1326ff9112dfSStefan Roese 	/* CS ODT Override */
1327ff9112dfSStefan Roese 	reg =  reg_read(REG_SDRAM_ODT_CTRL_HIGH_ADDR) &
1328ff9112dfSStefan Roese 		REG_SDRAM_ODT_CTRL_HIGH_OVRD_MASK;
1329ff9112dfSStefan Roese 	/* 0x1498 - SDRAM ODT Control high */
1330ff9112dfSStefan Roese 	reg_write(REG_SDRAM_ODT_CTRL_HIGH_ADDR, reg);
1331ff9112dfSStefan Roese 
1332ff9112dfSStefan Roese 	return MV_OK;
1333ff9112dfSStefan Roese }
1334ff9112dfSStefan Roese 
1335ff9112dfSStefan Roese /*
1336ff9112dfSStefan Roese  * Perform DDR3 Control PUP Indirect Write
1337ff9112dfSStefan Roese  */
ddr3_write_ctrl_pup_reg(int bc_acc,u32 pup,u32 reg_addr,u32 data)1338ff9112dfSStefan Roese static void ddr3_write_ctrl_pup_reg(int bc_acc, u32 pup, u32 reg_addr, u32 data)
1339ff9112dfSStefan Roese {
1340ff9112dfSStefan Roese 	u32 reg = 0;
1341ff9112dfSStefan Roese 
1342ff9112dfSStefan Roese 	/* Store value for write */
1343ff9112dfSStefan Roese 	reg = (data & 0xFFFF);
1344ff9112dfSStefan Roese 
1345ff9112dfSStefan Roese 	/* Set bit 26 for control PHY access */
1346ff9112dfSStefan Roese 	reg |= (1 << REG_PHY_CNTRL_OFFS);
1347ff9112dfSStefan Roese 
1348ff9112dfSStefan Roese 	/* Configure BC or UC access to PHYs */
1349ff9112dfSStefan Roese 	if (bc_acc == 1)
1350ff9112dfSStefan Roese 		reg |= (1 << REG_PHY_BC_OFFS);
1351ff9112dfSStefan Roese 	else
1352ff9112dfSStefan Roese 		reg |= (pup << REG_PHY_PUP_OFFS);
1353ff9112dfSStefan Roese 
1354ff9112dfSStefan Roese 	/* Set PHY register address to write to */
1355ff9112dfSStefan Roese 	reg |= (reg_addr << REG_PHY_CS_OFFS);
1356ff9112dfSStefan Roese 
1357ff9112dfSStefan Roese 	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
1358ff9112dfSStefan Roese 	reg |= REG_PHY_REGISTRY_FILE_ACCESS_OP_WR;
1359ff9112dfSStefan Roese 	reg_write(REG_PHY_REGISTRY_FILE_ACCESS_ADDR, reg);	/* 0x16A0 */
1360ff9112dfSStefan Roese 
1361ff9112dfSStefan Roese 	do {
1362ff9112dfSStefan Roese 		reg = (reg_read(REG_PHY_REGISTRY_FILE_ACCESS_ADDR)) &
1363ff9112dfSStefan Roese 			REG_PHY_REGISTRY_FILE_ACCESS_OP_DONE;
1364ff9112dfSStefan Roese 	} while (reg);		/* Wait for '0' to mark the end of the transaction */
1365ff9112dfSStefan Roese }
1366