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_DQS_C(s, d, l) \
20ff9112dfSStefan Roese DEBUG_DQS_S(s); DEBUG_DQS_D(d, l); DEBUG_DQS_S("\n")
21ff9112dfSStefan Roese #define DEBUG_DQS_FULL_C(s, d, l) \
22ff9112dfSStefan Roese DEBUG_DQS_FULL_S(s); DEBUG_DQS_FULL_D(d, l); DEBUG_DQS_FULL_S("\n")
23ff9112dfSStefan Roese #define DEBUG_DQS_RESULTS_C(s, d, l) \
24ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S(s); DEBUG_DQS_RESULTS_D(d, l); DEBUG_DQS_RESULTS_S("\n")
25ff9112dfSStefan Roese #define DEBUG_PER_DQ_C(s, d, l) \
26ff9112dfSStefan Roese puts(s); printf("%x", d); puts("\n")
27ff9112dfSStefan Roese
28ff9112dfSStefan Roese #define DEBUG_DQS_RESULTS_S(s) \
29ff9112dfSStefan Roese debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%s", s)
30ff9112dfSStefan Roese #define DEBUG_DQS_RESULTS_D(d, l) \
31ff9112dfSStefan Roese debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_2, "%x", d)
32ff9112dfSStefan Roese
33ff9112dfSStefan Roese #define DEBUG_PER_DQ_S(s) \
34ff9112dfSStefan Roese debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%s", s)
35ff9112dfSStefan Roese #define DEBUG_PER_DQ_D(d, l) \
36ff9112dfSStefan Roese debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%x", d)
37ff9112dfSStefan Roese #define DEBUG_PER_DQ_DD(d, l) \
38ff9112dfSStefan Roese debug_cond(ddr3_get_log_level() >= MV_LOG_LEVEL_3, "%d", d)
39ff9112dfSStefan Roese
40ff9112dfSStefan Roese #ifdef MV_DEBUG_DQS
41ff9112dfSStefan Roese #define DEBUG_DQS_S(s) puts(s)
42ff9112dfSStefan Roese #define DEBUG_DQS_D(d, l) printf("%x", d)
43ff9112dfSStefan Roese #else
44ff9112dfSStefan Roese #define DEBUG_DQS_S(s)
45ff9112dfSStefan Roese #define DEBUG_DQS_D(d, l)
46ff9112dfSStefan Roese #endif
47ff9112dfSStefan Roese
48ff9112dfSStefan Roese #ifdef MV_DEBUG_DQS_FULL
49ff9112dfSStefan Roese #define DEBUG_DQS_FULL_S(s) puts(s)
50ff9112dfSStefan Roese #define DEBUG_DQS_FULL_D(d, l) printf("%x", d)
51ff9112dfSStefan Roese #else
52ff9112dfSStefan Roese #define DEBUG_DQS_FULL_S(s)
53ff9112dfSStefan Roese #define DEBUG_DQS_FULL_D(d, l)
54ff9112dfSStefan Roese #endif
55ff9112dfSStefan Roese
56ff9112dfSStefan Roese /* State machine for centralization - find low & high limit */
57ff9112dfSStefan Roese enum {
58ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_FAIL,
59ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_PASS,
60ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS,
61ff9112dfSStefan Roese };
62ff9112dfSStefan Roese
63ff9112dfSStefan Roese /* Hold centralization low results */
64ff9112dfSStefan Roese static int centralization_low_limit[MAX_PUP_NUM] = { 0 };
65ff9112dfSStefan Roese /* Hold centralization high results */
66ff9112dfSStefan Roese static int centralization_high_limit[MAX_PUP_NUM] = { 0 };
67ff9112dfSStefan Roese
68ff9112dfSStefan Roese int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx);
69ff9112dfSStefan Roese int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
70ff9112dfSStefan Roese int *size_valid);
71ff9112dfSStefan Roese static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
72ff9112dfSStefan Roese int is_tx);
73ff9112dfSStefan Roese int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
74ff9112dfSStefan Roese int is_tx, u32 special_pattern_pup);
75ff9112dfSStefan Roese int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
76ff9112dfSStefan Roese int is_tx, u32 special_pattern_pup);
77ff9112dfSStefan Roese int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
78ff9112dfSStefan Roese int is_tx);
79ff9112dfSStefan Roese
80ff9112dfSStefan Roese #ifdef MV88F78X60
81ff9112dfSStefan Roese extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
82ff9112dfSStefan Roese extern u32 killer_pattern_64b[DQ_NUM][LEN_SPECIAL_PATTERN];
83ff9112dfSStefan Roese extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
84ff9112dfSStefan Roese #else
85ff9112dfSStefan Roese extern u32 killer_pattern[DQ_NUM][LEN_16BIT_KILLER_PATTERN];
86ff9112dfSStefan Roese extern u32 killer_pattern_32b[DQ_NUM][LEN_SPECIAL_PATTERN];
87ff9112dfSStefan Roese #if defined(MV88F672X)
88ff9112dfSStefan Roese extern int per_bit_data[MAX_PUP_NUM][DQ_NUM];
89ff9112dfSStefan Roese #endif
90ff9112dfSStefan Roese #endif
91ff9112dfSStefan Roese extern u32 special_pattern[DQ_NUM][LEN_SPECIAL_PATTERN];
92ff9112dfSStefan Roese
ddr3_dqs_choose_pattern(MV_DRAM_INFO * dram_info,u32 victim_dq)93ff9112dfSStefan Roese static u32 *ddr3_dqs_choose_pattern(MV_DRAM_INFO *dram_info, u32 victim_dq)
94ff9112dfSStefan Roese {
95ff9112dfSStefan Roese u32 *pattern_ptr;
96ff9112dfSStefan Roese
97ff9112dfSStefan Roese /* Choose pattern */
98ff9112dfSStefan Roese switch (dram_info->ddr_width) {
99ff9112dfSStefan Roese #if defined(MV88F672X)
100ff9112dfSStefan Roese case 16:
101ff9112dfSStefan Roese pattern_ptr = (u32 *)&killer_pattern[victim_dq];
102ff9112dfSStefan Roese break;
103ff9112dfSStefan Roese #endif
104ff9112dfSStefan Roese case 32:
105ff9112dfSStefan Roese pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
106ff9112dfSStefan Roese break;
107ff9112dfSStefan Roese #if defined(MV88F78X60)
108ff9112dfSStefan Roese case 64:
109ff9112dfSStefan Roese pattern_ptr = (u32 *)&killer_pattern_64b[victim_dq];
110ff9112dfSStefan Roese break;
111ff9112dfSStefan Roese #endif
112ff9112dfSStefan Roese default:
113ff9112dfSStefan Roese #if defined(MV88F78X60)
114ff9112dfSStefan Roese pattern_ptr = (u32 *)&killer_pattern_32b[victim_dq];
115ff9112dfSStefan Roese #else
116ff9112dfSStefan Roese pattern_ptr = (u32 *)&killer_pattern[victim_dq];
117ff9112dfSStefan Roese #endif
118ff9112dfSStefan Roese break;
119ff9112dfSStefan Roese }
120ff9112dfSStefan Roese
121ff9112dfSStefan Roese return pattern_ptr;
122ff9112dfSStefan Roese }
123ff9112dfSStefan Roese
124ff9112dfSStefan Roese /*
125ff9112dfSStefan Roese * Name: ddr3_dqs_centralization_rx
126ff9112dfSStefan Roese * Desc: Execute the DQS centralization RX phase.
127ff9112dfSStefan Roese * Args: dram_info
128ff9112dfSStefan Roese * Notes:
129ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
130ff9112dfSStefan Roese */
ddr3_dqs_centralization_rx(MV_DRAM_INFO * dram_info)131ff9112dfSStefan Roese int ddr3_dqs_centralization_rx(MV_DRAM_INFO *dram_info)
132ff9112dfSStefan Roese {
133ff9112dfSStefan Roese u32 cs, ecc, reg;
134ff9112dfSStefan Roese int status;
135ff9112dfSStefan Roese
136ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Centralization RX - Starting procedure\n");
137ff9112dfSStefan Roese
138ff9112dfSStefan Roese /* Enable SW override */
139ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
140ff9112dfSStefan Roese (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
141ff9112dfSStefan Roese
142ff9112dfSStefan Roese /* [0] = 1 - Enable SW override */
143ff9112dfSStefan Roese /* 0x15B8 - Training SW 2 Register */
144ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
145ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Centralization RX - SW Override Enabled\n");
146ff9112dfSStefan Roese
147ff9112dfSStefan Roese reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
148ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
149ff9112dfSStefan Roese
150ff9112dfSStefan Roese /* Loop for each CS */
151ff9112dfSStefan Roese for (cs = 0; cs < MAX_CS; cs++) {
152ff9112dfSStefan Roese if (dram_info->cs_ena & (1 << cs)) {
153ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Centralization RX - CS - ",
154ff9112dfSStefan Roese (u32) cs, 1);
155ff9112dfSStefan Roese
156ff9112dfSStefan Roese for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
157ff9112dfSStefan Roese
158ff9112dfSStefan Roese /* ECC Support - Switch ECC Mux on ecc=1 */
159ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
160ff9112dfSStefan Roese ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
161ff9112dfSStefan Roese reg |= (dram_info->ecc_ena *
162ff9112dfSStefan Roese ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
163ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
164ff9112dfSStefan Roese
165ff9112dfSStefan Roese if (ecc)
166ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Enabled\n");
167ff9112dfSStefan Roese else
168ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - ECC Mux Disabled\n");
169ff9112dfSStefan Roese
170ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Find all limits\n");
171ff9112dfSStefan Roese
172ff9112dfSStefan Roese status = ddr3_find_adll_limits(dram_info, cs,
173ff9112dfSStefan Roese ecc, 0);
174ff9112dfSStefan Roese if (MV_OK != status)
175ff9112dfSStefan Roese return status;
176ff9112dfSStefan Roese
177ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization RX - Start calculating center\n");
178ff9112dfSStefan Roese
179ff9112dfSStefan Roese status = ddr3_center_calc(dram_info, cs, ecc,
180ff9112dfSStefan Roese 0);
181ff9112dfSStefan Roese if (MV_OK != status)
182ff9112dfSStefan Roese return status;
183ff9112dfSStefan Roese }
184ff9112dfSStefan Roese }
185ff9112dfSStefan Roese }
186ff9112dfSStefan Roese
187ff9112dfSStefan Roese /* ECC Support - Disable ECC MUX */
188ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
189ff9112dfSStefan Roese ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
190ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
191ff9112dfSStefan Roese
192ff9112dfSStefan Roese /* Disable SW override - Must be in a different stage */
193ff9112dfSStefan Roese /* [0]=0 - Enable SW override */
194ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
195ff9112dfSStefan Roese reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
196ff9112dfSStefan Roese /* 0x15B8 - Training SW 2 Register */
197ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
198ff9112dfSStefan Roese
199ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
200ff9112dfSStefan Roese (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
201ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
202ff9112dfSStefan Roese
203ff9112dfSStefan Roese return MV_OK;
204ff9112dfSStefan Roese }
205ff9112dfSStefan Roese
206ff9112dfSStefan Roese /*
207ff9112dfSStefan Roese * Name: ddr3_dqs_centralization_tx
208ff9112dfSStefan Roese * Desc: Execute the DQS centralization TX phase.
209ff9112dfSStefan Roese * Args: dram_info
210ff9112dfSStefan Roese * Notes:
211ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
212ff9112dfSStefan Roese */
ddr3_dqs_centralization_tx(MV_DRAM_INFO * dram_info)213ff9112dfSStefan Roese int ddr3_dqs_centralization_tx(MV_DRAM_INFO *dram_info)
214ff9112dfSStefan Roese {
215ff9112dfSStefan Roese u32 cs, ecc, reg;
216ff9112dfSStefan Roese int status;
217ff9112dfSStefan Roese
218ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Centralization TX - Starting procedure\n");
219ff9112dfSStefan Roese
220ff9112dfSStefan Roese /* Enable SW override */
221ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR) |
222ff9112dfSStefan Roese (1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
223ff9112dfSStefan Roese
224ff9112dfSStefan Roese /* [0] = 1 - Enable SW override */
225ff9112dfSStefan Roese /* 0x15B8 - Training SW 2 Register */
226ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
227ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Centralization TX - SW Override Enabled\n");
228ff9112dfSStefan Roese
229ff9112dfSStefan Roese reg = (1 << REG_DRAM_TRAINING_AUTO_OFFS);
230ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_ADDR, reg); /* 0x15B0 - Training Register */
231ff9112dfSStefan Roese
232ff9112dfSStefan Roese /* Loop for each CS */
233ff9112dfSStefan Roese for (cs = 0; cs < MAX_CS; cs++) {
234ff9112dfSStefan Roese if (dram_info->cs_ena & (1 << cs)) {
235ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Centralization TX - CS - ",
236ff9112dfSStefan Roese (u32) cs, 1);
237ff9112dfSStefan Roese for (ecc = 0; ecc < (dram_info->ecc_ena + 1); ecc++) {
238ff9112dfSStefan Roese /* ECC Support - Switch ECC Mux on ecc=1 */
239ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
240ff9112dfSStefan Roese ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
241ff9112dfSStefan Roese reg |= (dram_info->ecc_ena *
242ff9112dfSStefan Roese ecc << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
243ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
244ff9112dfSStefan Roese
245ff9112dfSStefan Roese if (ecc)
246ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Enabled\n");
247ff9112dfSStefan Roese else
248ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - ECC Mux Disabled\n");
249ff9112dfSStefan Roese
250ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Find all limits\n");
251ff9112dfSStefan Roese
252ff9112dfSStefan Roese status = ddr3_find_adll_limits(dram_info, cs,
253ff9112dfSStefan Roese ecc, 1);
254ff9112dfSStefan Roese if (MV_OK != status)
255ff9112dfSStefan Roese return status;
256ff9112dfSStefan Roese
257ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Centralization TX - Start calculating center\n");
258ff9112dfSStefan Roese
259ff9112dfSStefan Roese status = ddr3_center_calc(dram_info, cs, ecc,
260ff9112dfSStefan Roese 1);
261ff9112dfSStefan Roese if (MV_OK != status)
262ff9112dfSStefan Roese return status;
263ff9112dfSStefan Roese }
264ff9112dfSStefan Roese }
265ff9112dfSStefan Roese }
266ff9112dfSStefan Roese
267ff9112dfSStefan Roese /* ECC Support - Disable ECC MUX */
268ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR) &
269ff9112dfSStefan Roese ~(1 << REG_DRAM_TRAINING_2_ECC_MUX_OFFS);
270ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
271ff9112dfSStefan Roese
272ff9112dfSStefan Roese /* Disable SW override - Must be in a different stage */
273ff9112dfSStefan Roese /* [0]=0 - Enable SW override */
274ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_2_ADDR);
275ff9112dfSStefan Roese reg &= ~(1 << REG_DRAM_TRAINING_2_SW_OVRD_OFFS);
276ff9112dfSStefan Roese /* 0x15B8 - Training SW 2 Register */
277ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_2_ADDR, reg);
278ff9112dfSStefan Roese
279ff9112dfSStefan Roese reg = reg_read(REG_DRAM_TRAINING_1_ADDR) |
280ff9112dfSStefan Roese (1 << REG_DRAM_TRAINING_1_TRNBPOINT_OFFS);
281ff9112dfSStefan Roese reg_write(REG_DRAM_TRAINING_1_ADDR, reg);
282ff9112dfSStefan Roese
283ff9112dfSStefan Roese return MV_OK;
284ff9112dfSStefan Roese }
285ff9112dfSStefan Roese
286ff9112dfSStefan Roese /*
287ff9112dfSStefan Roese * Name: ddr3_find_adll_limits
288ff9112dfSStefan Roese * Desc: Execute the Find ADLL limits phase.
289ff9112dfSStefan Roese * Args: dram_info
290ff9112dfSStefan Roese * cs
291ff9112dfSStefan Roese * ecc_ena
292ff9112dfSStefan Roese * is_tx Indicate whether Rx or Tx
293ff9112dfSStefan Roese * Notes:
294ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
295ff9112dfSStefan Roese */
ddr3_find_adll_limits(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx)296ff9112dfSStefan Roese int ddr3_find_adll_limits(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc, int is_tx)
297ff9112dfSStefan Roese {
298ff9112dfSStefan Roese u32 victim_dq, pup, tmp;
299ff9112dfSStefan Roese u32 adll_addr;
300ff9112dfSStefan Roese u32 max_pup; /* maximal pup index */
301ff9112dfSStefan Roese u32 pup_mask = 0;
302ff9112dfSStefan Roese u32 unlock_pup; /* bit array of un locked pups */
303ff9112dfSStefan Roese u32 new_unlock_pup; /* bit array of compare failed pups */
304ff9112dfSStefan Roese u32 curr_adll;
305ff9112dfSStefan Roese u32 adll_start_val; /* adll start loop value - for rx or tx limit */
306ff9112dfSStefan Roese u32 high_limit; /* holds found High Limit */
307ff9112dfSStefan Roese u32 low_limit; /* holds found Low Limit */
308ff9112dfSStefan Roese int win_valid;
309ff9112dfSStefan Roese int update_win;
310ff9112dfSStefan Roese u32 sdram_offset;
311ff9112dfSStefan Roese u32 uj, cs_count, cs_tmp, ii;
312ff9112dfSStefan Roese u32 *pattern_ptr;
313ff9112dfSStefan Roese u32 dq;
314ff9112dfSStefan Roese u32 adll_end_val; /* adll end of loop val - for rx or tx limit */
315ff9112dfSStefan Roese u8 analog_pbs[DQ_NUM][MAX_PUP_NUM][DQ_NUM][2];
316ff9112dfSStefan Roese u8 analog_pbs_sum[MAX_PUP_NUM][DQ_NUM][2];
317ff9112dfSStefan Roese int pup_adll_limit_state[MAX_PUP_NUM]; /* hold state of each pup */
318ff9112dfSStefan Roese
319ff9112dfSStefan Roese adll_addr = ((is_tx == 1) ? PUP_DQS_WR : PUP_DQS_RD);
320ff9112dfSStefan Roese adll_end_val = ((is_tx == 1) ? ADLL_MIN : ADLL_MAX);
321ff9112dfSStefan Roese adll_start_val = ((is_tx == 1) ? ADLL_MAX : ADLL_MIN);
322ff9112dfSStefan Roese max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
323ff9112dfSStefan Roese
324ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - Starting Find ADLL Limits\n");
325ff9112dfSStefan Roese
326ff9112dfSStefan Roese /* init the array */
327ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
328ff9112dfSStefan Roese centralization_low_limit[pup] = ADLL_MIN;
329ff9112dfSStefan Roese centralization_high_limit[pup] = ADLL_MAX;
330ff9112dfSStefan Roese }
331ff9112dfSStefan Roese
332ff9112dfSStefan Roese /* Killer Pattern */
333ff9112dfSStefan Roese cs_count = 0;
334ff9112dfSStefan Roese for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
335ff9112dfSStefan Roese if (dram_info->cs_ena & (1 << cs_tmp))
336ff9112dfSStefan Roese cs_count++;
337ff9112dfSStefan Roese }
338ff9112dfSStefan Roese sdram_offset = cs_count * (SDRAM_CS_SIZE + 1);
339ff9112dfSStefan Roese sdram_offset += ((is_tx == 1) ?
340ff9112dfSStefan Roese SDRAM_DQS_TX_OFFS : SDRAM_DQS_RX_OFFS);
341ff9112dfSStefan Roese
342ff9112dfSStefan Roese /* Prepare pup masks */
343ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++)
344ff9112dfSStefan Roese pup_mask |= (1 << pup);
345ff9112dfSStefan Roese
346ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
347ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM; dq++) {
348ff9112dfSStefan Roese analog_pbs_sum[pup][dq][0] = adll_start_val;
349ff9112dfSStefan Roese analog_pbs_sum[pup][dq][1] = adll_end_val;
350ff9112dfSStefan Roese }
351ff9112dfSStefan Roese }
352ff9112dfSStefan Roese
353ff9112dfSStefan Roese /* Loop - use different pattern for each victim_dq */
354ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
355ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Victim DQ - ",
356ff9112dfSStefan Roese (u32)victim_dq, 1);
357ff9112dfSStefan Roese /*
358ff9112dfSStefan Roese * The pups 3 bit arrays represent state machine. with
359ff9112dfSStefan Roese * 3 stages for each pup.
360ff9112dfSStefan Roese * 1. fail and didn't get pass in earlier compares.
361ff9112dfSStefan Roese * 2. pass compare
362ff9112dfSStefan Roese * 3. fail after pass - end state.
363ff9112dfSStefan Roese * The window limits are the adll values where the adll
364ff9112dfSStefan Roese * was in the pass stage.
365ff9112dfSStefan Roese */
366ff9112dfSStefan Roese
367ff9112dfSStefan Roese /* Set all states to Fail (1st state) */
368ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++)
369ff9112dfSStefan Roese pup_adll_limit_state[pup] = PUP_ADLL_LIMITS_STATE_FAIL;
370ff9112dfSStefan Roese
371ff9112dfSStefan Roese /* Set current valid pups */
372ff9112dfSStefan Roese unlock_pup = pup_mask;
373ff9112dfSStefan Roese
374ff9112dfSStefan Roese /* Set ADLL to start value */
375ff9112dfSStefan Roese curr_adll = adll_start_val;
376ff9112dfSStefan Roese
377ff9112dfSStefan Roese #if defined(MV88F78X60)
378ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
379ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM; dq++) {
380ff9112dfSStefan Roese analog_pbs[victim_dq][pup][dq][0] =
381ff9112dfSStefan Roese adll_start_val;
382ff9112dfSStefan Roese analog_pbs[victim_dq][pup][dq][1] =
383ff9112dfSStefan Roese adll_end_val;
384ff9112dfSStefan Roese per_bit_data[pup][dq] = 0;
385ff9112dfSStefan Roese }
386ff9112dfSStefan Roese }
387ff9112dfSStefan Roese #endif
388ff9112dfSStefan Roese
389ff9112dfSStefan Roese for (uj = 0; uj < ADLL_MAX; uj++) {
390ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Setting ADLL to ",
391ff9112dfSStefan Roese curr_adll, 2);
392ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
393ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
394ff9112dfSStefan Roese tmp = ((is_tx == 1) ? curr_adll +
395ff9112dfSStefan Roese dram_info->wl_val[cs]
396ff9112dfSStefan Roese [pup * (1 - ecc) + ecc * ECC_PUP]
397ff9112dfSStefan Roese [D] : curr_adll);
398ff9112dfSStefan Roese ddr3_write_pup_reg(adll_addr, cs, pup +
399ff9112dfSStefan Roese (ecc * ECC_PUP), 0, tmp);
400ff9112dfSStefan Roese }
401ff9112dfSStefan Roese }
402ff9112dfSStefan Roese
403ff9112dfSStefan Roese /* Choose pattern */
404ff9112dfSStefan Roese pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
405ff9112dfSStefan Roese victim_dq);
406ff9112dfSStefan Roese
407ff9112dfSStefan Roese /* '1' - means pup failed, '0' - means pup pass */
408ff9112dfSStefan Roese new_unlock_pup = 0;
409ff9112dfSStefan Roese
410ff9112dfSStefan Roese /* Read and compare results for Victim_DQ# */
411ff9112dfSStefan Roese for (ii = 0; ii < 3; ii++) {
412ff9112dfSStefan Roese u32 tmp = 0;
413ff9112dfSStefan Roese if (MV_OK != ddr3_sdram_dqs_compare(dram_info,
414ff9112dfSStefan Roese unlock_pup, &tmp,
415ff9112dfSStefan Roese pattern_ptr,
416ff9112dfSStefan Roese LEN_KILLER_PATTERN,
417ff9112dfSStefan Roese sdram_offset +
418ff9112dfSStefan Roese LEN_KILLER_PATTERN *
419ff9112dfSStefan Roese 4 * victim_dq,
420ff9112dfSStefan Roese is_tx, 0, NULL,
421ff9112dfSStefan Roese 0))
422ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_DRAM_COMPARE;
423ff9112dfSStefan Roese
424ff9112dfSStefan Roese new_unlock_pup |= tmp;
425ff9112dfSStefan Roese }
426ff9112dfSStefan Roese
427ff9112dfSStefan Roese pup = 0;
428ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - UnlockPup: ",
429ff9112dfSStefan Roese unlock_pup, 2);
430ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - NewUnlockPup: ",
431ff9112dfSStefan Roese new_unlock_pup, 2);
432ff9112dfSStefan Roese
433ff9112dfSStefan Roese /* Update pup state */
434ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
435ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup) == 0) {
436ff9112dfSStefan Roese DEBUG_DQS_FULL_C("DDR3 - DQS Find Limits - Skipping pup ",
437ff9112dfSStefan Roese pup, 1);
438ff9112dfSStefan Roese continue;
439ff9112dfSStefan Roese }
440ff9112dfSStefan Roese
441ff9112dfSStefan Roese /*
442ff9112dfSStefan Roese * Still didn't find the window limit of the pup
443ff9112dfSStefan Roese */
444ff9112dfSStefan Roese if (IS_PUP_ACTIVE(new_unlock_pup, pup) == 1) {
445ff9112dfSStefan Roese /* Current compare result == fail */
446ff9112dfSStefan Roese if (pup_adll_limit_state[pup] ==
447ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_PASS) {
448ff9112dfSStefan Roese /*
449ff9112dfSStefan Roese * If now it failed but passed
450ff9112dfSStefan Roese * earlier
451ff9112dfSStefan Roese */
452ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Find Limits - PASS to FAIL: CS - ");
453ff9112dfSStefan Roese DEBUG_DQS_D(cs, 1);
454ff9112dfSStefan Roese DEBUG_DQS_S(", DQ - ");
455ff9112dfSStefan Roese DEBUG_DQS_D(victim_dq, 1);
456ff9112dfSStefan Roese DEBUG_DQS_S(", Pup - ");
457ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
458ff9112dfSStefan Roese DEBUG_DQS_S(", ADLL - ");
459ff9112dfSStefan Roese DEBUG_DQS_D(curr_adll, 2);
460ff9112dfSStefan Roese DEBUG_DQS_S("\n");
461ff9112dfSStefan Roese
462ff9112dfSStefan Roese #if defined(MV88F78X60)
463ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM; dq++) {
464ff9112dfSStefan Roese if ((analog_pbs[victim_dq][pup][dq][0] != adll_start_val)
465ff9112dfSStefan Roese && (analog_pbs[victim_dq][pup]
466ff9112dfSStefan Roese [dq][1] == adll_end_val))
467ff9112dfSStefan Roese analog_pbs
468ff9112dfSStefan Roese [victim_dq]
469ff9112dfSStefan Roese [pup][dq]
470ff9112dfSStefan Roese [1] =
471ff9112dfSStefan Roese curr_adll;
472ff9112dfSStefan Roese }
473ff9112dfSStefan Roese #endif
474ff9112dfSStefan Roese win_valid = 1;
475ff9112dfSStefan Roese update_win = 0;
476ff9112dfSStefan Roese
477ff9112dfSStefan Roese /* Keep min / max limit value */
478ff9112dfSStefan Roese if (is_tx == 0) {
479ff9112dfSStefan Roese /* RX - found upper limit */
480ff9112dfSStefan Roese if (centralization_high_limit[pup] >
481ff9112dfSStefan Roese (curr_adll - 1)) {
482ff9112dfSStefan Roese high_limit =
483ff9112dfSStefan Roese curr_adll - 1;
484ff9112dfSStefan Roese low_limit =
485ff9112dfSStefan Roese centralization_low_limit[pup];
486ff9112dfSStefan Roese update_win = 1;
487ff9112dfSStefan Roese }
488ff9112dfSStefan Roese } else {
489ff9112dfSStefan Roese /* TX - found lower limit */
490ff9112dfSStefan Roese if (centralization_low_limit[pup] < (curr_adll + 1)) {
491ff9112dfSStefan Roese high_limit =
492ff9112dfSStefan Roese centralization_high_limit
493ff9112dfSStefan Roese [pup];
494ff9112dfSStefan Roese low_limit =
495ff9112dfSStefan Roese curr_adll + 1;
496ff9112dfSStefan Roese update_win =
497ff9112dfSStefan Roese 1;
498ff9112dfSStefan Roese }
499ff9112dfSStefan Roese }
500ff9112dfSStefan Roese
501ff9112dfSStefan Roese if (update_win == 1) {
502ff9112dfSStefan Roese /*
503ff9112dfSStefan Roese * Before updating
504ff9112dfSStefan Roese * window limits we need
505ff9112dfSStefan Roese * to check that the
506ff9112dfSStefan Roese * limits are valid
507ff9112dfSStefan Roese */
508ff9112dfSStefan Roese if (MV_OK !=
509ff9112dfSStefan Roese ddr3_check_window_limits
510ff9112dfSStefan Roese (pup, high_limit,
511ff9112dfSStefan Roese low_limit, is_tx,
512ff9112dfSStefan Roese &win_valid))
513ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_WIN_LIMITS;
514ff9112dfSStefan Roese
515ff9112dfSStefan Roese if (win_valid == 1) {
516ff9112dfSStefan Roese /*
517ff9112dfSStefan Roese * Window limits
518ff9112dfSStefan Roese * should be
519ff9112dfSStefan Roese * updated
520ff9112dfSStefan Roese */
521ff9112dfSStefan Roese centralization_low_limit
522ff9112dfSStefan Roese [pup] =
523ff9112dfSStefan Roese low_limit;
524ff9112dfSStefan Roese centralization_high_limit
525ff9112dfSStefan Roese [pup] =
526ff9112dfSStefan Roese high_limit;
527ff9112dfSStefan Roese }
528ff9112dfSStefan Roese }
529ff9112dfSStefan Roese
530ff9112dfSStefan Roese if (win_valid == 1) {
531ff9112dfSStefan Roese /* Found end of window - lock the pup */
532ff9112dfSStefan Roese pup_adll_limit_state[pup] =
533ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_FAIL_AFTER_PASS;
534ff9112dfSStefan Roese unlock_pup &= ~(1 << pup);
535ff9112dfSStefan Roese } else {
536ff9112dfSStefan Roese /* Probably false pass - reset status */
537ff9112dfSStefan Roese pup_adll_limit_state[pup] =
538ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_FAIL;
539ff9112dfSStefan Roese
540ff9112dfSStefan Roese #if defined(MV88F78X60)
541ff9112dfSStefan Roese /* Clear logging array of win size (per Dq) */
542ff9112dfSStefan Roese for (dq = 0;
543ff9112dfSStefan Roese dq < DQ_NUM;
544ff9112dfSStefan Roese dq++) {
545ff9112dfSStefan Roese analog_pbs
546ff9112dfSStefan Roese [victim_dq]
547ff9112dfSStefan Roese [pup][dq]
548ff9112dfSStefan Roese [0] =
549ff9112dfSStefan Roese adll_start_val;
550ff9112dfSStefan Roese analog_pbs
551ff9112dfSStefan Roese [victim_dq]
552ff9112dfSStefan Roese [pup][dq]
553ff9112dfSStefan Roese [1] =
554ff9112dfSStefan Roese adll_end_val;
555ff9112dfSStefan Roese per_bit_data
556ff9112dfSStefan Roese [pup][dq]
557ff9112dfSStefan Roese = 0;
558ff9112dfSStefan Roese }
559ff9112dfSStefan Roese #endif
560ff9112dfSStefan Roese }
561ff9112dfSStefan Roese }
562ff9112dfSStefan Roese } else {
563ff9112dfSStefan Roese /* Current compare result == pass */
564ff9112dfSStefan Roese if (pup_adll_limit_state[pup] ==
565ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_FAIL) {
566ff9112dfSStefan Roese /* If now it passed but failed earlier */
567ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Find Limits - FAIL to PASS: CS - ");
568ff9112dfSStefan Roese DEBUG_DQS_D(cs, 1);
569ff9112dfSStefan Roese DEBUG_DQS_S(", DQ - ");
570ff9112dfSStefan Roese DEBUG_DQS_D(victim_dq, 1);
571ff9112dfSStefan Roese DEBUG_DQS_S(", Pup - ");
572ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
573ff9112dfSStefan Roese DEBUG_DQS_S(", ADLL - ");
574ff9112dfSStefan Roese DEBUG_DQS_D(curr_adll, 2);
575ff9112dfSStefan Roese DEBUG_DQS_S("\n");
576ff9112dfSStefan Roese
577ff9112dfSStefan Roese #if defined(MV88F78X60)
578ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM;
579ff9112dfSStefan Roese dq++) {
580ff9112dfSStefan Roese if (analog_pbs[victim_dq][pup][dq][0] == adll_start_val)
581ff9112dfSStefan Roese analog_pbs
582ff9112dfSStefan Roese [victim_dq]
583ff9112dfSStefan Roese [pup][dq]
584ff9112dfSStefan Roese [0] =
585ff9112dfSStefan Roese curr_adll;
586ff9112dfSStefan Roese }
587ff9112dfSStefan Roese #endif
588ff9112dfSStefan Roese /* Found start of window */
589ff9112dfSStefan Roese pup_adll_limit_state[pup] =
590ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_PASS;
591ff9112dfSStefan Roese
592ff9112dfSStefan Roese /* Keep min / max limit value */
593ff9112dfSStefan Roese if (is_tx == 0) {
594ff9112dfSStefan Roese /* RX - found low limit */
595ff9112dfSStefan Roese if (centralization_low_limit[pup] <= curr_adll)
596ff9112dfSStefan Roese centralization_low_limit
597ff9112dfSStefan Roese [pup] =
598ff9112dfSStefan Roese curr_adll;
599ff9112dfSStefan Roese } else {
600ff9112dfSStefan Roese /* TX - found high limit */
601ff9112dfSStefan Roese if (centralization_high_limit[pup] >= curr_adll)
602ff9112dfSStefan Roese centralization_high_limit
603ff9112dfSStefan Roese [pup] =
604ff9112dfSStefan Roese curr_adll;
605ff9112dfSStefan Roese }
606ff9112dfSStefan Roese }
607ff9112dfSStefan Roese }
608ff9112dfSStefan Roese }
609ff9112dfSStefan Roese
610ff9112dfSStefan Roese if (unlock_pup == 0) {
611ff9112dfSStefan Roese /* Found limit to all pups */
612ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Find Limits - found PUP limit\n");
613ff9112dfSStefan Roese break;
614ff9112dfSStefan Roese }
615ff9112dfSStefan Roese
616ff9112dfSStefan Roese /*
617ff9112dfSStefan Roese * Increment / decrement (Move to right / left
618ff9112dfSStefan Roese * one phase - ADLL) dqs RX / TX delay (for all un
619ff9112dfSStefan Roese * lock pups
620ff9112dfSStefan Roese */
621ff9112dfSStefan Roese if (is_tx == 0)
622ff9112dfSStefan Roese curr_adll++;
623ff9112dfSStefan Roese else
624ff9112dfSStefan Roese curr_adll--;
625ff9112dfSStefan Roese }
626ff9112dfSStefan Roese
627ff9112dfSStefan Roese if (unlock_pup != 0) {
628ff9112dfSStefan Roese /*
629ff9112dfSStefan Roese * Found pups that didn't reach to the end of the
630ff9112dfSStefan Roese * state machine
631ff9112dfSStefan Roese */
632ff9112dfSStefan Roese DEBUG_DQS_C("DDR3 - DQS Find Limits - Pups that didn't reached end of the state machine: ",
633ff9112dfSStefan Roese unlock_pup, 1);
634ff9112dfSStefan Roese
635ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
636ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
637ff9112dfSStefan Roese if (pup_adll_limit_state[pup] ==
638ff9112dfSStefan Roese PUP_ADLL_LIMITS_STATE_FAIL) {
639ff9112dfSStefan Roese /* ERROR - found fail for all window size */
640ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Find Limits - Got FAIL for the complete range on pup - ");
641ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
642ff9112dfSStefan Roese DEBUG_DQS_C(" victim DQ ",
643ff9112dfSStefan Roese victim_dq, 1);
644ff9112dfSStefan Roese
645ff9112dfSStefan Roese /* For debug - set min limit to illegal limit */
646ff9112dfSStefan Roese centralization_low_limit[pup]
647ff9112dfSStefan Roese = ADLL_ERROR;
648ff9112dfSStefan Roese /*
649ff9112dfSStefan Roese * In case the pup is in mode
650ff9112dfSStefan Roese * PASS - the limit is the min
651ff9112dfSStefan Roese * / max adll, no need to
652ff9112dfSStefan Roese * update because of the results
653ff9112dfSStefan Roese * array default value
654ff9112dfSStefan Roese */
655ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_PUP_RANGE;
656ff9112dfSStefan Roese }
657ff9112dfSStefan Roese }
658ff9112dfSStefan Roese }
659ff9112dfSStefan Roese }
660ff9112dfSStefan Roese }
661ff9112dfSStefan Roese
662ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Find Limits - DQ values per victim results:\n");
663ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
664ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
665ff9112dfSStefan Roese DEBUG_DQS_S("Victim DQ-");
666ff9112dfSStefan Roese DEBUG_DQS_D(victim_dq, 1);
667ff9112dfSStefan Roese DEBUG_DQS_S(", PUP-");
668ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
669ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM; dq++) {
670ff9112dfSStefan Roese DEBUG_DQS_S(", DQ-");
671ff9112dfSStefan Roese DEBUG_DQS_D(dq, 1);
672ff9112dfSStefan Roese DEBUG_DQS_S(",S-");
673ff9112dfSStefan Roese DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
674ff9112dfSStefan Roese [0], 2);
675ff9112dfSStefan Roese DEBUG_DQS_S(",E-");
676ff9112dfSStefan Roese DEBUG_DQS_D(analog_pbs[victim_dq][pup][dq]
677ff9112dfSStefan Roese [1], 2);
678ff9112dfSStefan Roese
679ff9112dfSStefan Roese if (is_tx == 0) {
680ff9112dfSStefan Roese if (analog_pbs[victim_dq][pup][dq][0]
681ff9112dfSStefan Roese > analog_pbs_sum[pup][dq][0])
682ff9112dfSStefan Roese analog_pbs_sum[pup][dq][0] =
683ff9112dfSStefan Roese analog_pbs[victim_dq][pup]
684ff9112dfSStefan Roese [dq][0];
685ff9112dfSStefan Roese if (analog_pbs[victim_dq][pup][dq][1]
686ff9112dfSStefan Roese < analog_pbs_sum[pup][dq][1])
687ff9112dfSStefan Roese analog_pbs_sum[pup][dq][1] =
688ff9112dfSStefan Roese analog_pbs[victim_dq][pup]
689ff9112dfSStefan Roese [dq][1];
690ff9112dfSStefan Roese } else {
691ff9112dfSStefan Roese if (analog_pbs[victim_dq][pup][dq][0]
692ff9112dfSStefan Roese < analog_pbs_sum[pup][dq][0])
693ff9112dfSStefan Roese analog_pbs_sum[pup][dq][0] =
694ff9112dfSStefan Roese analog_pbs[victim_dq][pup]
695ff9112dfSStefan Roese [dq][0];
696ff9112dfSStefan Roese if (analog_pbs[victim_dq][pup][dq][1]
697ff9112dfSStefan Roese > analog_pbs_sum[pup][dq][1])
698ff9112dfSStefan Roese analog_pbs_sum[pup][dq][1] =
699ff9112dfSStefan Roese analog_pbs[victim_dq][pup]
700ff9112dfSStefan Roese [dq][1];
701ff9112dfSStefan Roese }
702ff9112dfSStefan Roese }
703ff9112dfSStefan Roese DEBUG_DQS_S("\n");
704ff9112dfSStefan Roese }
705ff9112dfSStefan Roese }
706ff9112dfSStefan Roese
707ff9112dfSStefan Roese if (ddr3_get_log_level() >= MV_LOG_LEVEL_3) {
708ff9112dfSStefan Roese u32 dq;
709ff9112dfSStefan Roese
710ff9112dfSStefan Roese DEBUG_PER_DQ_S("\n########## LOG LEVEL 3(Windows margins per-DQ) ##########\n");
711ff9112dfSStefan Roese if (is_tx) {
712ff9112dfSStefan Roese DEBUG_PER_DQ_C("DDR3 - TX CS: ", cs, 1);
713ff9112dfSStefan Roese } else {
714ff9112dfSStefan Roese DEBUG_PER_DQ_C("DDR3 - RX CS: ", cs, 1);
715ff9112dfSStefan Roese }
716ff9112dfSStefan Roese
717ff9112dfSStefan Roese if (ecc == 0) {
718ff9112dfSStefan Roese DEBUG_PER_DQ_S("\n DATA RESULTS:\n");
719ff9112dfSStefan Roese } else {
720ff9112dfSStefan Roese DEBUG_PER_DQ_S("\n ECC RESULTS:\n");
721ff9112dfSStefan Roese }
722ff9112dfSStefan Roese
723ff9112dfSStefan Roese /* Since all dq has the same value we take 0 as representive */
724ff9112dfSStefan Roese dq = 0;
725ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
726ff9112dfSStefan Roese if (ecc == 0) {
727ff9112dfSStefan Roese DEBUG_PER_DQ_S("\nBYTE:");
728ff9112dfSStefan Roese DEBUG_PER_DQ_D(pup, 1);
729ff9112dfSStefan Roese DEBUG_PER_DQ_S("\n");
730ff9112dfSStefan Roese } else {
731ff9112dfSStefan Roese DEBUG_PER_DQ_S("\nECC BYTE:\n");
732ff9112dfSStefan Roese }
733ff9112dfSStefan Roese DEBUG_PER_DQ_S(" DQ's LOW HIGH WIN-SIZE\n");
734ff9112dfSStefan Roese DEBUG_PER_DQ_S("============================================\n");
735ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
736ff9112dfSStefan Roese if (ecc == 0) {
737ff9112dfSStefan Roese DEBUG_PER_DQ_S("DQ[");
738ff9112dfSStefan Roese DEBUG_PER_DQ_DD((victim_dq +
739ff9112dfSStefan Roese DQ_NUM * pup), 2);
740ff9112dfSStefan Roese DEBUG_PER_DQ_S("]");
741ff9112dfSStefan Roese } else {
742ff9112dfSStefan Roese DEBUG_PER_DQ_S("CB[");
743ff9112dfSStefan Roese DEBUG_PER_DQ_DD(victim_dq, 2);
744ff9112dfSStefan Roese DEBUG_PER_DQ_S("]");
745ff9112dfSStefan Roese }
746ff9112dfSStefan Roese if (is_tx) {
747ff9112dfSStefan Roese DEBUG_PER_DQ_S(" 0x");
748ff9112dfSStefan Roese DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1], 2); /* low value */
749ff9112dfSStefan Roese DEBUG_PER_DQ_S(" 0x");
750ff9112dfSStefan Roese DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* high value */
751ff9112dfSStefan Roese DEBUG_PER_DQ_S(" 0x");
752ff9112dfSStefan Roese DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0] - analog_pbs[victim_dq][pup][dq][1], 2); /* win-size */
753ff9112dfSStefan Roese } else {
754ff9112dfSStefan Roese DEBUG_PER_DQ_S(" 0x");
755ff9112dfSStefan Roese DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][0], 2); /* low value */
756ff9112dfSStefan Roese DEBUG_PER_DQ_S(" 0x");
757ff9112dfSStefan Roese DEBUG_PER_DQ_D((analog_pbs[victim_dq][pup][dq][1] - 1), 2); /* high value */
758ff9112dfSStefan Roese DEBUG_PER_DQ_S(" 0x");
759ff9112dfSStefan Roese DEBUG_PER_DQ_D(analog_pbs[victim_dq][pup][dq][1] - analog_pbs[victim_dq][pup][dq][0], 2); /* win-size */
760ff9112dfSStefan Roese }
761ff9112dfSStefan Roese DEBUG_PER_DQ_S("\n");
762ff9112dfSStefan Roese }
763ff9112dfSStefan Roese }
764ff9112dfSStefan Roese DEBUG_PER_DQ_S("\n");
765ff9112dfSStefan Roese }
766ff9112dfSStefan Roese
767ff9112dfSStefan Roese if (is_tx) {
768ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
769ff9112dfSStefan Roese } else {
770ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
771ff9112dfSStefan Roese }
772ff9112dfSStefan Roese
773ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
774ff9112dfSStefan Roese DEBUG_DQS_S("PUP-");
775ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
776ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM; dq++) {
777ff9112dfSStefan Roese DEBUG_DQS_S(", DQ-");
778ff9112dfSStefan Roese DEBUG_DQS_D(dq, 1);
779ff9112dfSStefan Roese DEBUG_DQS_S(",S-");
780ff9112dfSStefan Roese DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
781ff9112dfSStefan Roese DEBUG_DQS_S(",E-");
782ff9112dfSStefan Roese DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
783ff9112dfSStefan Roese }
784ff9112dfSStefan Roese DEBUG_DQS_S("\n");
785ff9112dfSStefan Roese }
786ff9112dfSStefan Roese
787ff9112dfSStefan Roese if (is_tx) {
788ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS TX - Find Limits - DQ values Summary:\n");
789ff9112dfSStefan Roese } else {
790ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS RX - Find Limits - DQ values Summary:\n");
791ff9112dfSStefan Roese }
792ff9112dfSStefan Roese
793ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
794ff9112dfSStefan Roese if (max_pup == 1) {
795ff9112dfSStefan Roese /* For ECC PUP */
796ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS8");
797ff9112dfSStefan Roese } else {
798ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS");
799ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
800ff9112dfSStefan Roese }
801ff9112dfSStefan Roese
802ff9112dfSStefan Roese for (dq = 0; dq < DQ_NUM; dq++) {
803ff9112dfSStefan Roese DEBUG_DQS_S(", DQ-");
804ff9112dfSStefan Roese DEBUG_DQS_D(dq, 1);
805ff9112dfSStefan Roese DEBUG_DQS_S("::S-");
806ff9112dfSStefan Roese DEBUG_DQS_D(analog_pbs_sum[pup][dq][0], 2);
807ff9112dfSStefan Roese DEBUG_DQS_S(",E-");
808ff9112dfSStefan Roese DEBUG_DQS_D(analog_pbs_sum[pup][dq][1], 2);
809ff9112dfSStefan Roese }
810ff9112dfSStefan Roese DEBUG_DQS_S("\n");
811ff9112dfSStefan Roese }
812ff9112dfSStefan Roese
813ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Find Limits - Ended\n");
814ff9112dfSStefan Roese
815ff9112dfSStefan Roese return MV_OK;
816ff9112dfSStefan Roese }
817ff9112dfSStefan Roese
818ff9112dfSStefan Roese /*
819ff9112dfSStefan Roese * Name: ddr3_check_window_limits
820ff9112dfSStefan Roese * Desc: Check window High & Low limits.
821ff9112dfSStefan Roese * Args: pup pup index
822ff9112dfSStefan Roese * high_limit window high limit
823ff9112dfSStefan Roese * low_limit window low limit
824ff9112dfSStefan Roese * is_tx Indicate whether Rx or Tx
825ff9112dfSStefan Roese * size_valid Indicate whether window size is valid
826ff9112dfSStefan Roese * Notes:
827ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
828ff9112dfSStefan Roese */
ddr3_check_window_limits(u32 pup,int high_limit,int low_limit,int is_tx,int * size_valid)829ff9112dfSStefan Roese int ddr3_check_window_limits(u32 pup, int high_limit, int low_limit, int is_tx,
830ff9112dfSStefan Roese int *size_valid)
831ff9112dfSStefan Roese {
832ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Starting\n");
833ff9112dfSStefan Roese
834ff9112dfSStefan Roese if (low_limit > high_limit) {
835ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
836ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
837ff9112dfSStefan Roese DEBUG_DQS_S(" Low Limit grater than High Limit\n");
838ff9112dfSStefan Roese *size_valid = 0;
839ff9112dfSStefan Roese return MV_OK;
840ff9112dfSStefan Roese }
841ff9112dfSStefan Roese
842ff9112dfSStefan Roese /*
843ff9112dfSStefan Roese * Check that window size is valid, if not it was probably false pass
844ff9112dfSStefan Roese * before
845ff9112dfSStefan Roese */
846ff9112dfSStefan Roese if ((high_limit - low_limit) < MIN_WIN_SIZE) {
847ff9112dfSStefan Roese /*
848ff9112dfSStefan Roese * Since window size is too small probably there was false
849ff9112dfSStefan Roese * pass
850ff9112dfSStefan Roese */
851ff9112dfSStefan Roese *size_valid = 0;
852ff9112dfSStefan Roese
853ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
854ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
855ff9112dfSStefan Roese DEBUG_DQS_S(" Window size is smaller than MIN_WIN_SIZE\n");
856ff9112dfSStefan Roese
857ff9112dfSStefan Roese } else if ((high_limit - low_limit) > ADLL_MAX) {
858ff9112dfSStefan Roese *size_valid = 0;
859ff9112dfSStefan Roese
860ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Check Win Limits - Pup ");
861ff9112dfSStefan Roese DEBUG_DQS_D(pup, 1);
862ff9112dfSStefan Roese DEBUG_DQS_S
863ff9112dfSStefan Roese (" Window size is bigger than max ADLL taps (31) Exiting.\n");
864ff9112dfSStefan Roese
865ff9112dfSStefan Roese return MV_FAIL;
866ff9112dfSStefan Roese
867ff9112dfSStefan Roese } else {
868ff9112dfSStefan Roese *size_valid = 1;
869ff9112dfSStefan Roese
870ff9112dfSStefan Roese DEBUG_DQS_FULL_S("DDR3 - DQS Check Win Limits - Pup ");
871ff9112dfSStefan Roese DEBUG_DQS_FULL_D(pup, 1);
872ff9112dfSStefan Roese DEBUG_DQS_FULL_C(" window size is ", (high_limit - low_limit),
873ff9112dfSStefan Roese 2);
874ff9112dfSStefan Roese }
875ff9112dfSStefan Roese
876ff9112dfSStefan Roese return MV_OK;
877ff9112dfSStefan Roese }
878ff9112dfSStefan Roese
879ff9112dfSStefan Roese /*
880ff9112dfSStefan Roese * Name: ddr3_center_calc
881ff9112dfSStefan Roese * Desc: Execute the calculate the center of windows phase.
882ff9112dfSStefan Roese * Args: pDram Info
883ff9112dfSStefan Roese * is_tx Indicate whether Rx or Tx
884ff9112dfSStefan Roese * Notes:
885ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
886ff9112dfSStefan Roese */
ddr3_center_calc(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx)887ff9112dfSStefan Roese static int ddr3_center_calc(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
888ff9112dfSStefan Roese int is_tx)
889ff9112dfSStefan Roese {
890ff9112dfSStefan Roese /* bit array of pups that need specail search */
891ff9112dfSStefan Roese u32 special_pattern_i_pup = 0;
892ff9112dfSStefan Roese u32 special_pattern_ii_pup = 0;
893ff9112dfSStefan Roese u32 pup;
894ff9112dfSStefan Roese u32 max_pup;
895ff9112dfSStefan Roese
896ff9112dfSStefan Roese max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
897ff9112dfSStefan Roese
898ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
899ff9112dfSStefan Roese if (is_tx == 0) {
900ff9112dfSStefan Roese /* Check special pattern I */
901ff9112dfSStefan Roese /*
902ff9112dfSStefan Roese * Special pattern Low limit search - relevant only
903ff9112dfSStefan Roese * for Rx, win size < threshold and low limit = 0
904ff9112dfSStefan Roese */
905ff9112dfSStefan Roese if (((centralization_high_limit[pup] -
906ff9112dfSStefan Roese centralization_low_limit[pup]) < VALID_WIN_THRS)
907ff9112dfSStefan Roese && (centralization_low_limit[pup] == MIN_DELAY))
908ff9112dfSStefan Roese special_pattern_i_pup |= (1 << pup);
909ff9112dfSStefan Roese
910ff9112dfSStefan Roese /* Check special pattern II */
911ff9112dfSStefan Roese /*
912ff9112dfSStefan Roese * Special pattern High limit search - relevant only
913ff9112dfSStefan Roese * for Rx, win size < threshold and high limit = 31
914ff9112dfSStefan Roese */
915ff9112dfSStefan Roese if (((centralization_high_limit[pup] -
916ff9112dfSStefan Roese centralization_low_limit[pup]) < VALID_WIN_THRS)
917ff9112dfSStefan Roese && (centralization_high_limit[pup] == MAX_DELAY))
918ff9112dfSStefan Roese special_pattern_ii_pup |= (1 << pup);
919ff9112dfSStefan Roese }
920ff9112dfSStefan Roese }
921ff9112dfSStefan Roese
922ff9112dfSStefan Roese /* Run special pattern Low limit search - for relevant pup */
923ff9112dfSStefan Roese if (special_pattern_i_pup != 0) {
924ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern I for Low limit search\n");
925ff9112dfSStefan Roese if (MV_OK !=
926ff9112dfSStefan Roese ddr3_special_pattern_i_search(dram_info, cs, ecc, is_tx,
927ff9112dfSStefan Roese special_pattern_i_pup))
928ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_DQS_LOW_LIMIT_SEARCH;
929ff9112dfSStefan Roese }
930ff9112dfSStefan Roese
931ff9112dfSStefan Roese /* Run special pattern High limit search - for relevant pup */
932ff9112dfSStefan Roese if (special_pattern_ii_pup != 0) {
933ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS Center Calc - Entering special pattern II for High limit search\n");
934ff9112dfSStefan Roese if (MV_OK !=
935ff9112dfSStefan Roese ddr3_special_pattern_ii_search(dram_info, cs, ecc, is_tx,
936ff9112dfSStefan Roese special_pattern_ii_pup))
937ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_DQS_HIGH_LIMIT_SEARCH;
938ff9112dfSStefan Roese }
939ff9112dfSStefan Roese
940ff9112dfSStefan Roese /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
941ff9112dfSStefan Roese return ddr3_set_dqs_centralization_results(dram_info, cs, ecc, is_tx);
942ff9112dfSStefan Roese }
943ff9112dfSStefan Roese
944ff9112dfSStefan Roese /*
945ff9112dfSStefan Roese * Name: ddr3_special_pattern_i_search
946ff9112dfSStefan Roese * Desc: Execute special pattern low limit search.
947ff9112dfSStefan Roese * Args:
948ff9112dfSStefan Roese * special_pattern_pup The pups that need the special search
949ff9112dfSStefan Roese * Notes:
950ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
951ff9112dfSStefan Roese */
ddr3_special_pattern_i_search(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx,u32 special_pattern_pup)952ff9112dfSStefan Roese int ddr3_special_pattern_i_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
953ff9112dfSStefan Roese int is_tx, u32 special_pattern_pup)
954ff9112dfSStefan Roese {
955ff9112dfSStefan Roese u32 victim_dq; /* loop index - victim DQ */
956ff9112dfSStefan Roese u32 adll_idx;
957ff9112dfSStefan Roese u32 pup;
958ff9112dfSStefan Roese u32 unlock_pup; /* bit array of the unlock pups */
959ff9112dfSStefan Roese u32 first_fail; /* bit array - of pups that get first fail */
960ff9112dfSStefan Roese u32 new_lockup_pup; /* bit array of compare failed pups */
961ff9112dfSStefan Roese u32 pass_pup; /* bit array of compare pass pup */
962ff9112dfSStefan Roese u32 sdram_offset;
963ff9112dfSStefan Roese u32 max_pup;
964ff9112dfSStefan Roese u32 comp_val;
965ff9112dfSStefan Roese u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
966ff9112dfSStefan Roese
967ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS - Special Pattern I Search - Starting\n");
968ff9112dfSStefan Roese
969ff9112dfSStefan Roese max_pup = ecc + (1 - ecc) * dram_info->num_of_std_pups;
970ff9112dfSStefan Roese
971ff9112dfSStefan Roese /* Init the temporary results to max ADLL value */
972ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++)
973ff9112dfSStefan Roese special_res[pup] = ADLL_MAX;
974ff9112dfSStefan Roese
975ff9112dfSStefan Roese /* Run special pattern for all DQ - use the same pattern */
976ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
977ff9112dfSStefan Roese unlock_pup = special_pattern_pup;
978ff9112dfSStefan Roese first_fail = 0;
979ff9112dfSStefan Roese
980ff9112dfSStefan Roese sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS +
981ff9112dfSStefan Roese LEN_KILLER_PATTERN * 4 * victim_dq;
982ff9112dfSStefan Roese
983ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
984ff9112dfSStefan Roese /* Set adll value per PUP. adll = high limit per pup */
985ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup)) {
986ff9112dfSStefan Roese /* only for pups that need special search */
987ff9112dfSStefan Roese ddr3_write_pup_reg(PUP_DQS_RD, cs,
988ff9112dfSStefan Roese pup + (ecc * ECC_PUP), 0,
989ff9112dfSStefan Roese centralization_high_limit
990ff9112dfSStefan Roese [pup]);
991ff9112dfSStefan Roese }
992ff9112dfSStefan Roese }
993ff9112dfSStefan Roese
994ff9112dfSStefan Roese adll_idx = 0;
995ff9112dfSStefan Roese do {
996ff9112dfSStefan Roese /*
997ff9112dfSStefan Roese * Perform read and compare simultaneously for all
998ff9112dfSStefan Roese * un-locked MC use the special pattern mask
999ff9112dfSStefan Roese */
1000ff9112dfSStefan Roese new_lockup_pup = 0;
1001ff9112dfSStefan Roese
1002ff9112dfSStefan Roese if (MV_OK !=
1003ff9112dfSStefan Roese ddr3_sdram_dqs_compare(dram_info, unlock_pup,
1004ff9112dfSStefan Roese &new_lockup_pup,
1005ff9112dfSStefan Roese special_pattern
1006ff9112dfSStefan Roese [victim_dq],
1007ff9112dfSStefan Roese LEN_SPECIAL_PATTERN,
1008ff9112dfSStefan Roese sdram_offset, 0,
1009ff9112dfSStefan Roese 0, NULL, 1))
1010ff9112dfSStefan Roese return MV_FAIL;
1011ff9112dfSStefan Roese
1012ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS - Special I - ADLL value is: ");
1013ff9112dfSStefan Roese DEBUG_DQS_D(adll_idx, 2);
1014ff9112dfSStefan Roese DEBUG_DQS_S(", UnlockPup: ");
1015ff9112dfSStefan Roese DEBUG_DQS_D(unlock_pup, 2);
1016ff9112dfSStefan Roese DEBUG_DQS_S(", NewLockPup: ");
1017ff9112dfSStefan Roese DEBUG_DQS_D(new_lockup_pup, 2);
1018ff9112dfSStefan Roese DEBUG_DQS_S("\n");
1019ff9112dfSStefan Roese
1020ff9112dfSStefan Roese if (unlock_pup != new_lockup_pup)
1021ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS - Special I - Some Pup passed!\n");
1022ff9112dfSStefan Roese
1023ff9112dfSStefan Roese /* Search for pups with passed compare & already fail */
1024ff9112dfSStefan Roese pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1025ff9112dfSStefan Roese first_fail |= new_lockup_pup;
1026ff9112dfSStefan Roese unlock_pup &= ~pass_pup;
1027ff9112dfSStefan Roese
1028ff9112dfSStefan Roese /* Get pass pups */
1029ff9112dfSStefan Roese if (pass_pup != 0) {
1030ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
1031ff9112dfSStefan Roese if (IS_PUP_ACTIVE(pass_pup, pup) ==
1032ff9112dfSStefan Roese 1) {
1033ff9112dfSStefan Roese /* If pup passed and has first fail = 1 */
1034ff9112dfSStefan Roese /* keep min value of ADLL max value - current adll */
1035ff9112dfSStefan Roese /* (centralization_high_limit[pup] + adll_idx) = current adll !!! */
1036ff9112dfSStefan Roese comp_val =
1037ff9112dfSStefan Roese (ADLL_MAX -
1038ff9112dfSStefan Roese (centralization_high_limit
1039ff9112dfSStefan Roese [pup] + adll_idx));
1040ff9112dfSStefan Roese
1041ff9112dfSStefan Roese DEBUG_DQS_C
1042ff9112dfSStefan Roese ("DDR3 - DQS - Special I - Pup - ",
1043ff9112dfSStefan Roese pup, 1);
1044ff9112dfSStefan Roese DEBUG_DQS_C
1045ff9112dfSStefan Roese (" comp_val = ",
1046ff9112dfSStefan Roese comp_val, 2);
1047ff9112dfSStefan Roese
1048ff9112dfSStefan Roese if (comp_val <
1049ff9112dfSStefan Roese special_res[pup]) {
1050ff9112dfSStefan Roese special_res[pup] =
1051ff9112dfSStefan Roese comp_val;
1052ff9112dfSStefan Roese centralization_low_limit
1053ff9112dfSStefan Roese [pup] =
1054ff9112dfSStefan Roese (-1) *
1055ff9112dfSStefan Roese comp_val;
1056ff9112dfSStefan Roese
1057ff9112dfSStefan Roese DEBUG_DQS_C
1058ff9112dfSStefan Roese ("DDR3 - DQS - Special I - Pup - ",
1059ff9112dfSStefan Roese pup, 1);
1060ff9112dfSStefan Roese DEBUG_DQS_C
1061ff9112dfSStefan Roese (" Changed Low limit to ",
1062ff9112dfSStefan Roese centralization_low_limit
1063ff9112dfSStefan Roese [pup], 2);
1064ff9112dfSStefan Roese }
1065ff9112dfSStefan Roese }
1066ff9112dfSStefan Roese }
1067ff9112dfSStefan Roese }
1068ff9112dfSStefan Roese
1069ff9112dfSStefan Roese /*
1070ff9112dfSStefan Roese * Did all PUP found missing window?
1071ff9112dfSStefan Roese * Check for each pup if adll (different for each pup)
1072ff9112dfSStefan Roese * reach maximum if reach max value - lock the pup
1073ff9112dfSStefan Roese * if not - increment (Move to right one phase - ADLL)
1074ff9112dfSStefan Roese * dqs RX delay
1075ff9112dfSStefan Roese */
1076ff9112dfSStefan Roese adll_idx++;
1077ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
1078ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1079ff9112dfSStefan Roese /* Check only unlocked pups */
1080ff9112dfSStefan Roese if ((centralization_high_limit[pup] +
1081ff9112dfSStefan Roese adll_idx) >= ADLL_MAX) {
1082ff9112dfSStefan Roese /* reach maximum - lock the pup */
1083ff9112dfSStefan Roese DEBUG_DQS_C("DDR3 - DQS - Special I - reach maximum - lock pup ",
1084ff9112dfSStefan Roese pup, 1);
1085ff9112dfSStefan Roese unlock_pup &= ~(1 << pup);
1086ff9112dfSStefan Roese } else {
1087ff9112dfSStefan Roese /* Didn't reach maximum - increment ADLL */
1088ff9112dfSStefan Roese ddr3_write_pup_reg(PUP_DQS_RD,
1089ff9112dfSStefan Roese cs,
1090ff9112dfSStefan Roese pup +
1091ff9112dfSStefan Roese (ecc *
1092ff9112dfSStefan Roese ECC_PUP), 0,
1093ff9112dfSStefan Roese (centralization_high_limit
1094ff9112dfSStefan Roese [pup] +
1095ff9112dfSStefan Roese adll_idx));
1096ff9112dfSStefan Roese }
1097ff9112dfSStefan Roese }
1098ff9112dfSStefan Roese }
1099ff9112dfSStefan Roese } while (unlock_pup != 0);
1100ff9112dfSStefan Roese }
1101ff9112dfSStefan Roese
1102ff9112dfSStefan Roese return MV_OK;
1103ff9112dfSStefan Roese }
1104ff9112dfSStefan Roese
1105ff9112dfSStefan Roese /*
1106ff9112dfSStefan Roese * Name: ddr3_special_pattern_ii_search
1107ff9112dfSStefan Roese * Desc: Execute special pattern high limit search.
1108ff9112dfSStefan Roese * Args:
1109ff9112dfSStefan Roese * special_pattern_pup The pups that need the special search
1110ff9112dfSStefan Roese * Notes:
1111ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
1112ff9112dfSStefan Roese */
ddr3_special_pattern_ii_search(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx,u32 special_pattern_pup)1113ff9112dfSStefan Roese int ddr3_special_pattern_ii_search(MV_DRAM_INFO *dram_info, u32 cs, u32 ecc,
1114ff9112dfSStefan Roese int is_tx, u32 special_pattern_pup)
1115ff9112dfSStefan Roese {
1116ff9112dfSStefan Roese u32 victim_dq; /* loop index - victim DQ */
1117ff9112dfSStefan Roese u32 adll_idx;
1118ff9112dfSStefan Roese u32 pup;
1119ff9112dfSStefan Roese u32 unlock_pup; /* bit array of the unlock pups */
1120ff9112dfSStefan Roese u32 first_fail; /* bit array - of pups that get first fail */
1121ff9112dfSStefan Roese u32 new_lockup_pup; /* bit array of compare failed pups */
1122ff9112dfSStefan Roese u32 pass_pup; /* bit array of compare pass pup */
1123ff9112dfSStefan Roese u32 sdram_offset;
1124ff9112dfSStefan Roese u32 max_pup;
1125ff9112dfSStefan Roese u32 comp_val;
1126ff9112dfSStefan Roese u32 special_res[MAX_PUP_NUM]; /* hold tmp results */
1127ff9112dfSStefan Roese
1128ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS - Special Pattern II Search - Starting\n");
1129ff9112dfSStefan Roese
1130ff9112dfSStefan Roese max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1131ff9112dfSStefan Roese
1132ff9112dfSStefan Roese /* init the tmporary results to max ADLL value */
1133ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++)
1134ff9112dfSStefan Roese special_res[pup] = ADLL_MAX;
1135ff9112dfSStefan Roese
1136ff9112dfSStefan Roese sdram_offset = cs * SDRAM_CS_SIZE + SDRAM_DQS_RX_OFFS;
1137ff9112dfSStefan Roese
1138ff9112dfSStefan Roese /* run special pattern for all DQ - use the same pattern */
1139ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1140ff9112dfSStefan Roese unlock_pup = special_pattern_pup;
1141ff9112dfSStefan Roese first_fail = 0;
1142ff9112dfSStefan Roese
1143ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
1144ff9112dfSStefan Roese /* Set adll value per PUP. adll = 0 */
1145ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup)) {
1146ff9112dfSStefan Roese /* Only for pups that need special search */
1147ff9112dfSStefan Roese ddr3_write_pup_reg(PUP_DQS_RD, cs,
1148ff9112dfSStefan Roese pup + (ecc * ECC_PUP), 0,
1149ff9112dfSStefan Roese ADLL_MIN);
1150ff9112dfSStefan Roese }
1151ff9112dfSStefan Roese }
1152ff9112dfSStefan Roese
1153ff9112dfSStefan Roese adll_idx = 0;
1154ff9112dfSStefan Roese do {
1155ff9112dfSStefan Roese /*
1156ff9112dfSStefan Roese * Perform read and compare simultaneously for all
1157ff9112dfSStefan Roese * un-locked MC use the special pattern mask
1158ff9112dfSStefan Roese */
1159ff9112dfSStefan Roese new_lockup_pup = 0;
1160ff9112dfSStefan Roese
1161ff9112dfSStefan Roese if (MV_OK != ddr3_sdram_dqs_compare(
1162ff9112dfSStefan Roese dram_info, unlock_pup, &new_lockup_pup,
1163ff9112dfSStefan Roese special_pattern[victim_dq],
1164ff9112dfSStefan Roese LEN_SPECIAL_PATTERN,
1165ff9112dfSStefan Roese sdram_offset, 0, 0, NULL, 0))
1166ff9112dfSStefan Roese return MV_FAIL;
1167ff9112dfSStefan Roese
1168ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS - Special II - ADLL value is ");
1169ff9112dfSStefan Roese DEBUG_DQS_D(adll_idx, 2);
1170ff9112dfSStefan Roese DEBUG_DQS_S("unlock_pup ");
1171ff9112dfSStefan Roese DEBUG_DQS_D(unlock_pup, 1);
1172ff9112dfSStefan Roese DEBUG_DQS_S("new_lockup_pup ");
1173ff9112dfSStefan Roese DEBUG_DQS_D(new_lockup_pup, 1);
1174ff9112dfSStefan Roese DEBUG_DQS_S("\n");
1175ff9112dfSStefan Roese
1176ff9112dfSStefan Roese if (unlock_pup != new_lockup_pup) {
1177ff9112dfSStefan Roese DEBUG_DQS_S("DDR3 - DQS - Special II - Some Pup passed!\n");
1178ff9112dfSStefan Roese }
1179ff9112dfSStefan Roese
1180ff9112dfSStefan Roese /* Search for pups with passed compare & already fail */
1181ff9112dfSStefan Roese pass_pup = first_fail & ~new_lockup_pup & unlock_pup;
1182ff9112dfSStefan Roese first_fail |= new_lockup_pup;
1183ff9112dfSStefan Roese unlock_pup &= ~pass_pup;
1184ff9112dfSStefan Roese
1185ff9112dfSStefan Roese /* Get pass pups */
1186ff9112dfSStefan Roese if (pass_pup != 0) {
1187ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
1188ff9112dfSStefan Roese if (IS_PUP_ACTIVE(pass_pup, pup) ==
1189ff9112dfSStefan Roese 1) {
1190ff9112dfSStefan Roese /* If pup passed and has first fail = 1 */
1191ff9112dfSStefan Roese /* keep min value of ADLL max value - current adll */
1192ff9112dfSStefan Roese /* (adll_idx) = current adll !!! */
1193ff9112dfSStefan Roese comp_val = adll_idx;
1194ff9112dfSStefan Roese
1195ff9112dfSStefan Roese DEBUG_DQS_C("DDR3 - DQS - Special II - Pup - ",
1196ff9112dfSStefan Roese pup, 1);
1197ff9112dfSStefan Roese DEBUG_DQS_C(" comp_val = ",
1198ff9112dfSStefan Roese comp_val, 1);
1199ff9112dfSStefan Roese
1200ff9112dfSStefan Roese if (comp_val <
1201ff9112dfSStefan Roese special_res[pup]) {
1202ff9112dfSStefan Roese special_res[pup] =
1203ff9112dfSStefan Roese comp_val;
1204ff9112dfSStefan Roese centralization_high_limit
1205ff9112dfSStefan Roese [pup] =
1206ff9112dfSStefan Roese ADLL_MAX +
1207ff9112dfSStefan Roese comp_val;
1208ff9112dfSStefan Roese
1209ff9112dfSStefan Roese DEBUG_DQS_C
1210ff9112dfSStefan Roese ("DDR3 - DQS - Special II - Pup - ",
1211ff9112dfSStefan Roese pup, 1);
1212ff9112dfSStefan Roese DEBUG_DQS_C
1213ff9112dfSStefan Roese (" Changed High limit to ",
1214ff9112dfSStefan Roese centralization_high_limit
1215ff9112dfSStefan Roese [pup], 2);
1216ff9112dfSStefan Roese }
1217ff9112dfSStefan Roese }
1218ff9112dfSStefan Roese }
1219ff9112dfSStefan Roese }
1220ff9112dfSStefan Roese
1221ff9112dfSStefan Roese /*
1222ff9112dfSStefan Roese * Did all PUP found missing window?
1223ff9112dfSStefan Roese * Check for each pup if adll (different for each pup)
1224ff9112dfSStefan Roese * reach maximum if reach max value - lock the pup
1225ff9112dfSStefan Roese * if not - increment (Move to right one phase - ADLL)
1226ff9112dfSStefan Roese * dqs RX delay
1227ff9112dfSStefan Roese */
1228ff9112dfSStefan Roese adll_idx++;
1229ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
1230ff9112dfSStefan Roese if (IS_PUP_ACTIVE(unlock_pup, pup) == 1) {
1231ff9112dfSStefan Roese /* Check only unlocked pups */
1232ff9112dfSStefan Roese if ((adll_idx) >= ADLL_MAX) {
1233ff9112dfSStefan Roese /* Reach maximum - lock the pup */
1234ff9112dfSStefan Roese DEBUG_DQS_C("DDR3 - DQS - Special II - reach maximum - lock pup ",
1235ff9112dfSStefan Roese pup, 1);
1236ff9112dfSStefan Roese unlock_pup &= ~(1 << pup);
1237ff9112dfSStefan Roese } else {
1238ff9112dfSStefan Roese /* Didn't reach maximum - increment ADLL */
1239ff9112dfSStefan Roese ddr3_write_pup_reg(PUP_DQS_RD,
1240ff9112dfSStefan Roese cs,
1241ff9112dfSStefan Roese pup +
1242ff9112dfSStefan Roese (ecc *
1243ff9112dfSStefan Roese ECC_PUP), 0,
1244ff9112dfSStefan Roese (adll_idx));
1245ff9112dfSStefan Roese }
1246ff9112dfSStefan Roese }
1247ff9112dfSStefan Roese }
1248ff9112dfSStefan Roese } while (unlock_pup != 0);
1249ff9112dfSStefan Roese }
1250ff9112dfSStefan Roese
1251ff9112dfSStefan Roese return MV_OK;
1252ff9112dfSStefan Roese }
1253ff9112dfSStefan Roese
1254ff9112dfSStefan Roese /*
1255ff9112dfSStefan Roese * Name: ddr3_set_dqs_centralization_results
1256ff9112dfSStefan Roese * Desc: Set to HW the DQS centralization phase results.
1257ff9112dfSStefan Roese * Args:
1258ff9112dfSStefan Roese * is_tx Indicates whether to set Tx or RX results
1259ff9112dfSStefan Roese * Notes:
1260ff9112dfSStefan Roese * Returns: MV_OK if success, other error code if fail.
1261ff9112dfSStefan Roese */
ddr3_set_dqs_centralization_results(MV_DRAM_INFO * dram_info,u32 cs,u32 ecc,int is_tx)1262ff9112dfSStefan Roese int ddr3_set_dqs_centralization_results(MV_DRAM_INFO *dram_info, u32 cs,
1263ff9112dfSStefan Roese u32 ecc, int is_tx)
1264ff9112dfSStefan Roese {
1265ff9112dfSStefan Roese u32 pup, pup_num;
1266ff9112dfSStefan Roese int addl_val;
1267ff9112dfSStefan Roese u32 max_pup;
1268ff9112dfSStefan Roese
1269ff9112dfSStefan Roese max_pup = (ecc + (1 - ecc) * dram_info->num_of_std_pups);
1270ff9112dfSStefan Roese
1271*51855e89SMasahiro Yamada DEBUG_DQS_RESULTS_S("\n############ LOG LEVEL 2(Windows margins) ############\n");
1272ff9112dfSStefan Roese
1273ff9112dfSStefan Roese if (is_tx) {
1274ff9112dfSStefan Roese DEBUG_DQS_RESULTS_C("DDR3 - DQS TX - Set Dqs Centralization Results - CS: ",
1275ff9112dfSStefan Roese cs, 1);
1276ff9112dfSStefan Roese } else {
1277ff9112dfSStefan Roese DEBUG_DQS_RESULTS_C("DDR3 - DQS RX - Set Dqs Centralization Results - CS: ",
1278ff9112dfSStefan Roese cs, 1);
1279ff9112dfSStefan Roese }
1280ff9112dfSStefan Roese
1281ff9112dfSStefan Roese /* Set adll to center = (General_High_limit + General_Low_limit)/2 */
1282ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S("\nDQS LOW HIGH WIN-SIZE Set\n");
1283ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S("==============================================\n");
1284ff9112dfSStefan Roese for (pup = 0; pup < max_pup; pup++) {
1285ff9112dfSStefan Roese addl_val = (centralization_high_limit[pup] +
1286ff9112dfSStefan Roese centralization_low_limit[pup]) / 2;
1287ff9112dfSStefan Roese
1288ff9112dfSStefan Roese pup_num = pup * (1 - ecc) + ecc * ECC_PUP;
1289ff9112dfSStefan Roese
1290ff9112dfSStefan Roese DEBUG_DQS_RESULTS_D(pup_num, 1);
1291ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S(" 0x");
1292ff9112dfSStefan Roese DEBUG_DQS_RESULTS_D(centralization_low_limit[pup], 2);
1293ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S(" 0x");
1294ff9112dfSStefan Roese DEBUG_DQS_RESULTS_D(centralization_high_limit[pup], 2);
1295ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S(" 0x");
1296ff9112dfSStefan Roese DEBUG_DQS_RESULTS_D(centralization_high_limit[pup] -
1297ff9112dfSStefan Roese centralization_low_limit[pup], 2);
1298ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S(" 0x");
1299ff9112dfSStefan Roese DEBUG_DQS_RESULTS_D(addl_val, 2);
1300ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S("\n");
1301ff9112dfSStefan Roese
1302ff9112dfSStefan Roese if (addl_val < ADLL_MIN) {
1303ff9112dfSStefan Roese addl_val = ADLL_MIN;
1304ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MIN (since it was lower than 0)\n");
1305ff9112dfSStefan Roese }
1306ff9112dfSStefan Roese
1307ff9112dfSStefan Roese if (addl_val > ADLL_MAX) {
1308ff9112dfSStefan Roese addl_val = ADLL_MAX;
1309ff9112dfSStefan Roese DEBUG_DQS_RESULTS_S("DDR3 - DQS - Setting ADLL value for Pup to MAX (since it was higher than 31)\n");
1310ff9112dfSStefan Roese }
1311ff9112dfSStefan Roese
1312ff9112dfSStefan Roese if (is_tx) {
1313ff9112dfSStefan Roese ddr3_write_pup_reg(PUP_DQS_WR, cs, pup_num, 0,
1314ff9112dfSStefan Roese addl_val +
1315ff9112dfSStefan Roese dram_info->wl_val[cs][pup_num][D]);
1316ff9112dfSStefan Roese } else {
1317ff9112dfSStefan Roese ddr3_write_pup_reg(PUP_DQS_RD, cs, pup_num, 0,
1318ff9112dfSStefan Roese addl_val);
1319ff9112dfSStefan Roese }
1320ff9112dfSStefan Roese }
1321ff9112dfSStefan Roese
1322ff9112dfSStefan Roese return MV_OK;
1323ff9112dfSStefan Roese }
1324ff9112dfSStefan Roese
1325ff9112dfSStefan Roese /*
1326ff9112dfSStefan Roese * Set training patterns
1327ff9112dfSStefan Roese */
ddr3_load_dqs_patterns(MV_DRAM_INFO * dram_info)1328ff9112dfSStefan Roese int ddr3_load_dqs_patterns(MV_DRAM_INFO *dram_info)
1329ff9112dfSStefan Roese {
1330ff9112dfSStefan Roese u32 cs, cs_count, cs_tmp, victim_dq;
1331ff9112dfSStefan Roese u32 sdram_addr;
1332ff9112dfSStefan Roese u32 *pattern_ptr;
1333ff9112dfSStefan Roese
1334ff9112dfSStefan Roese /* Loop for each CS */
1335ff9112dfSStefan Roese for (cs = 0; cs < MAX_CS; cs++) {
1336ff9112dfSStefan Roese if (dram_info->cs_ena & (1 << cs)) {
1337ff9112dfSStefan Roese cs_count = 0;
1338ff9112dfSStefan Roese for (cs_tmp = 0; cs_tmp < cs; cs_tmp++) {
1339ff9112dfSStefan Roese if (dram_info->cs_ena & (1 << cs_tmp))
1340ff9112dfSStefan Roese cs_count++;
1341ff9112dfSStefan Roese }
1342ff9112dfSStefan Roese
1343ff9112dfSStefan Roese /* Init killer pattern */
1344ff9112dfSStefan Roese sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1345ff9112dfSStefan Roese SDRAM_DQS_RX_OFFS);
1346ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1347ff9112dfSStefan Roese pattern_ptr = ddr3_dqs_choose_pattern(dram_info,
1348ff9112dfSStefan Roese victim_dq);
1349ff9112dfSStefan Roese if (MV_OK != ddr3_sdram_dqs_compare(
1350ff9112dfSStefan Roese dram_info, (u32)NULL, NULL,
1351ff9112dfSStefan Roese pattern_ptr, LEN_KILLER_PATTERN,
1352ff9112dfSStefan Roese sdram_addr + LEN_KILLER_PATTERN *
1353ff9112dfSStefan Roese 4 * victim_dq, 1, 0, NULL,
1354ff9112dfSStefan Roese 0))
1355ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1356ff9112dfSStefan Roese }
1357ff9112dfSStefan Roese
1358ff9112dfSStefan Roese /* Init special-killer pattern */
1359ff9112dfSStefan Roese sdram_addr = (cs_count * (SDRAM_CS_SIZE + 1) +
1360ff9112dfSStefan Roese SDRAM_DQS_RX_SPECIAL_OFFS);
1361ff9112dfSStefan Roese for (victim_dq = 0; victim_dq < DQ_NUM; victim_dq++) {
1362ff9112dfSStefan Roese if (MV_OK != ddr3_sdram_dqs_compare(
1363ff9112dfSStefan Roese dram_info, (u32)NULL, NULL,
1364ff9112dfSStefan Roese special_pattern[victim_dq],
1365ff9112dfSStefan Roese LEN_KILLER_PATTERN, sdram_addr +
1366ff9112dfSStefan Roese LEN_KILLER_PATTERN * 4 * victim_dq,
1367ff9112dfSStefan Roese 1, 0, NULL, 0))
1368ff9112dfSStefan Roese return MV_DDR3_TRAINING_ERR_DQS_PATTERN;
1369ff9112dfSStefan Roese }
1370ff9112dfSStefan Roese }
1371ff9112dfSStefan Roese }
1372ff9112dfSStefan Roese
1373ff9112dfSStefan Roese return MV_OK;
1374ff9112dfSStefan Roese }
1375