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