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