183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
2f1df9364SStefan Roese /*
3f1df9364SStefan Roese * Copyright (C) Marvell International Ltd. and its affiliates
4f1df9364SStefan Roese */
5f1df9364SStefan Roese
6f1df9364SStefan Roese #include "ddr3_init.h"
7ebb1a593SChris Packham #include "mv_ddr_regs.h"
8f1df9364SStefan Roese
9f1df9364SStefan Roese #define VREF_INITIAL_STEP 3
10f1df9364SStefan Roese #define VREF_SECOND_STEP 1
11f1df9364SStefan Roese #define VREF_MAX_INDEX 7
12f1df9364SStefan Roese #define MAX_VALUE (1024 - 1)
13f1df9364SStefan Roese #define MIN_VALUE (-MAX_VALUE)
142b4ffbf6SChris Packham #define GET_RD_SAMPLE_DELAY(data, cs) ((data >> rd_sample_mask[cs]) & 0xf)
15f1df9364SStefan Roese
16f1df9364SStefan Roese u32 ca_delay;
17f1df9364SStefan Roese int ddr3_tip_centr_skip_min_win_check = 0;
18f1df9364SStefan Roese u8 current_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
19f1df9364SStefan Roese u8 last_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
20f1df9364SStefan Roese u16 current_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
21f1df9364SStefan Roese u16 last_valid_window[MAX_BUS_NUM][MAX_INTERFACE_NUM];
22f1df9364SStefan Roese u8 lim_vref[MAX_BUS_NUM][MAX_INTERFACE_NUM];
23f1df9364SStefan Roese u8 interface_state[MAX_INTERFACE_NUM];
24f1df9364SStefan Roese u8 vref_window_size[MAX_INTERFACE_NUM][MAX_BUS_NUM];
25f1df9364SStefan Roese u8 vref_window_size_th = 12;
26f1df9364SStefan Roese
27f1df9364SStefan Roese static u8 pup_st[MAX_BUS_NUM][MAX_INTERFACE_NUM];
28f1df9364SStefan Roese
29f1df9364SStefan Roese static u32 rd_sample_mask[] = {
30f1df9364SStefan Roese 0,
31f1df9364SStefan Roese 8,
32f1df9364SStefan Roese 16,
33f1df9364SStefan Roese 24
34f1df9364SStefan Roese };
35f1df9364SStefan Roese
36f1df9364SStefan Roese #define VREF_STEP_1 0
37f1df9364SStefan Roese #define VREF_STEP_2 1
38f1df9364SStefan Roese #define VREF_CONVERGE 2
39f1df9364SStefan Roese
40f1df9364SStefan Roese /*
41f1df9364SStefan Roese * ODT additional timing
42f1df9364SStefan Roese */
ddr3_tip_write_additional_odt_setting(u32 dev_num,u32 if_id)43f1df9364SStefan Roese int ddr3_tip_write_additional_odt_setting(u32 dev_num, u32 if_id)
44f1df9364SStefan Roese {
452b4ffbf6SChris Packham u32 cs_num = 0, max_read_sample = 0, min_read_sample = 0x1f;
46f1df9364SStefan Roese u32 data_read[MAX_INTERFACE_NUM] = { 0 };
47f1df9364SStefan Roese u32 read_sample[MAX_CS_NUM];
48f1df9364SStefan Roese u32 val;
49f1df9364SStefan Roese u32 pup_index;
50f1df9364SStefan Roese int max_phase = MIN_VALUE, current_phase;
51f1df9364SStefan Roese enum hws_access_type access_type = ACCESS_TYPE_UNICAST;
522b4ffbf6SChris Packham u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
53*247c80d6SChris Packham unsigned int max_cs = mv_ddr_cs_num_get();
54f1df9364SStefan Roese
55f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
562b4ffbf6SChris Packham DUNIT_ODT_CTRL_REG,
57f1df9364SStefan Roese 0 << 8, 0x3 << 8));
58f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_if_read(dev_num, access_type, if_id,
592b4ffbf6SChris Packham RD_DATA_SMPL_DLYS_REG,
60f1df9364SStefan Roese data_read, MASK_ALL_BITS));
61f1df9364SStefan Roese val = data_read[if_id];
62f1df9364SStefan Roese
63*247c80d6SChris Packham for (cs_num = 0; cs_num < max_cs; cs_num++) {
64f1df9364SStefan Roese read_sample[cs_num] = GET_RD_SAMPLE_DELAY(val, cs_num);
65f1df9364SStefan Roese
66f1df9364SStefan Roese /* find maximum of read_samples */
67f1df9364SStefan Roese if (read_sample[cs_num] >= max_read_sample) {
682b4ffbf6SChris Packham if (read_sample[cs_num] == max_read_sample)
698bddf678SChris Packham max_phase = MIN_VALUE;
702b4ffbf6SChris Packham else
712b4ffbf6SChris Packham max_read_sample = read_sample[cs_num];
72f1df9364SStefan Roese
73f1df9364SStefan Roese for (pup_index = 0;
742b4ffbf6SChris Packham pup_index < octets_per_if_num;
75f1df9364SStefan Roese pup_index++) {
76f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_bus_read
77f1df9364SStefan Roese (dev_num, if_id,
78f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup_index,
79f1df9364SStefan Roese DDR_PHY_DATA,
802b4ffbf6SChris Packham RL_PHY_REG(cs_num),
81f1df9364SStefan Roese &val));
82f1df9364SStefan Roese
83f1df9364SStefan Roese current_phase = ((int)val & 0xe0) >> 6;
84f1df9364SStefan Roese if (current_phase >= max_phase)
85f1df9364SStefan Roese max_phase = current_phase;
86f1df9364SStefan Roese }
87f1df9364SStefan Roese }
88f1df9364SStefan Roese
89f1df9364SStefan Roese /* find minimum */
90f1df9364SStefan Roese if (read_sample[cs_num] < min_read_sample)
91f1df9364SStefan Roese min_read_sample = read_sample[cs_num];
92f1df9364SStefan Roese }
93f1df9364SStefan Roese
94f1df9364SStefan Roese min_read_sample = min_read_sample - 1;
95f1df9364SStefan Roese max_read_sample = max_read_sample + 4 + (max_phase + 1) / 2 + 1;
962b4ffbf6SChris Packham if (min_read_sample >= 0xf)
972b4ffbf6SChris Packham min_read_sample = 0xf;
98f1df9364SStefan Roese if (max_read_sample >= 0x1f)
99f1df9364SStefan Roese max_read_sample = 0x1f;
100f1df9364SStefan Roese
101f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
1022b4ffbf6SChris Packham DDR_ODT_TIMING_LOW_REG,
103f1df9364SStefan Roese ((min_read_sample - 1) << 12),
104f1df9364SStefan Roese 0xf << 12));
105f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, if_id,
1062b4ffbf6SChris Packham DDR_ODT_TIMING_LOW_REG,
107f1df9364SStefan Roese (max_read_sample << 16),
108f1df9364SStefan Roese 0x1f << 16));
109f1df9364SStefan Roese
110f1df9364SStefan Roese return MV_OK;
111f1df9364SStefan Roese }
112f1df9364SStefan Roese
get_valid_win_rx(u32 dev_num,u32 if_id,u8 res[4])113f1df9364SStefan Roese int get_valid_win_rx(u32 dev_num, u32 if_id, u8 res[4])
114f1df9364SStefan Roese {
1152b4ffbf6SChris Packham u32 reg_pup = RESULT_PHY_REG;
116f1df9364SStefan Roese u32 reg_data;
117f1df9364SStefan Roese u32 cs_num;
118f1df9364SStefan Roese int i;
119f1df9364SStefan Roese
120f1df9364SStefan Roese cs_num = 0;
121f1df9364SStefan Roese
122f1df9364SStefan Roese /* TBD */
123f1df9364SStefan Roese reg_pup += cs_num;
124f1df9364SStefan Roese
125f1df9364SStefan Roese for (i = 0; i < 4; i++) {
126f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_bus_read(dev_num, if_id,
127f1df9364SStefan Roese ACCESS_TYPE_UNICAST, i,
128f1df9364SStefan Roese DDR_PHY_DATA, reg_pup,
129f1df9364SStefan Roese ®_data));
1302b4ffbf6SChris Packham res[i] = (reg_data >> RESULT_PHY_RX_OFFS) & 0x1f;
131f1df9364SStefan Roese }
132f1df9364SStefan Roese
133f1df9364SStefan Roese return 0;
134f1df9364SStefan Roese }
135f1df9364SStefan Roese
136f1df9364SStefan Roese /*
137f1df9364SStefan Roese * This algorithm deals with the vertical optimum from Voltage point of view
138f1df9364SStefan Roese * of the sample signal.
139f1df9364SStefan Roese * Voltage sample point can improve the Eye / window size of the bit and the
140f1df9364SStefan Roese * pup.
141f1df9364SStefan Roese * The problem is that it is tune for all DQ the same so there isn't any
142f1df9364SStefan Roese * PBS like code.
143f1df9364SStefan Roese * It is more like centralization.
144f1df9364SStefan Roese * But because we don't have The training SM support we do it a bit more
145f1df9364SStefan Roese * smart search to save time.
146f1df9364SStefan Roese */
ddr3_tip_vref(u32 dev_num)147f1df9364SStefan Roese int ddr3_tip_vref(u32 dev_num)
148f1df9364SStefan Roese {
149f1df9364SStefan Roese /*
150f1df9364SStefan Roese * The Vref register have non linear order. Need to check what will be
151f1df9364SStefan Roese * in future projects.
152f1df9364SStefan Roese */
153f1df9364SStefan Roese u32 vref_map[8] = {
154f1df9364SStefan Roese 1, 2, 3, 4, 5, 6, 7, 0
155f1df9364SStefan Roese };
156f1df9364SStefan Roese /* State and parameter definitions */
157f1df9364SStefan Roese u32 initial_step = VREF_INITIAL_STEP;
158f1df9364SStefan Roese /* need to be assign with minus ????? */
159f1df9364SStefan Roese u32 second_step = VREF_SECOND_STEP;
160f1df9364SStefan Roese u32 algo_run_flag = 0, currrent_vref = 0;
161f1df9364SStefan Roese u32 while_count = 0;
162f1df9364SStefan Roese u32 pup = 0, if_id = 0, num_pup = 0, rep = 0;
163f1df9364SStefan Roese u32 val = 0;
164f1df9364SStefan Roese u32 reg_addr = 0xa8;
165f1df9364SStefan Roese u32 copy_start_pattern, copy_end_pattern;
166f1df9364SStefan Roese enum hws_result *flow_result = ddr3_tip_get_result_ptr(training_stage);
167f1df9364SStefan Roese u8 res[4];
1682b4ffbf6SChris Packham u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
1692b4ffbf6SChris Packham struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
170f1df9364SStefan Roese
171f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_special_rx(dev_num));
172f1df9364SStefan Roese
173f1df9364SStefan Roese /* save start/end pattern */
174f1df9364SStefan Roese copy_start_pattern = start_pattern;
175f1df9364SStefan Roese copy_end_pattern = end_pattern;
176f1df9364SStefan Roese
177f1df9364SStefan Roese /* set vref as centralization pattern */
178f1df9364SStefan Roese start_pattern = PATTERN_VREF;
179f1df9364SStefan Roese end_pattern = PATTERN_VREF;
180f1df9364SStefan Roese
181f1df9364SStefan Roese /* init params */
182f1df9364SStefan Roese for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
1832b4ffbf6SChris Packham VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
184f1df9364SStefan Roese for (pup = 0;
1852b4ffbf6SChris Packham pup < octets_per_if_num; pup++) {
186f1df9364SStefan Roese current_vref[pup][if_id] = 0;
187f1df9364SStefan Roese last_vref[pup][if_id] = 0;
188f1df9364SStefan Roese lim_vref[pup][if_id] = 0;
189f1df9364SStefan Roese current_valid_window[pup][if_id] = 0;
190f1df9364SStefan Roese last_valid_window[pup][if_id] = 0;
191f1df9364SStefan Roese if (vref_window_size[if_id][pup] >
192f1df9364SStefan Roese vref_window_size_th) {
193f1df9364SStefan Roese pup_st[pup][if_id] = VREF_CONVERGE;
194f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(
195f1df9364SStefan Roese DEBUG_LEVEL_INFO,
196f1df9364SStefan Roese ("VREF config, IF[ %d ]pup[ %d ] - Vref tune not requered (%d)\n",
197f1df9364SStefan Roese if_id, pup, __LINE__));
198f1df9364SStefan Roese } else {
199f1df9364SStefan Roese pup_st[pup][if_id] = VREF_STEP_1;
200f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_bus_read
201f1df9364SStefan Roese (dev_num, if_id,
202f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
203f1df9364SStefan Roese DDR_PHY_DATA, reg_addr, &val));
204f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_bus_write
205f1df9364SStefan Roese (dev_num, ACCESS_TYPE_UNICAST,
206f1df9364SStefan Roese if_id, ACCESS_TYPE_UNICAST,
207f1df9364SStefan Roese pup, DDR_PHY_DATA, reg_addr,
208f1df9364SStefan Roese (val & (~0xf)) | vref_map[0]));
209f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(
210f1df9364SStefan Roese DEBUG_LEVEL_INFO,
211f1df9364SStefan Roese ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
212f1df9364SStefan Roese if_id, pup,
213f1df9364SStefan Roese (val & (~0xf)) | vref_map[0],
214f1df9364SStefan Roese __LINE__));
215f1df9364SStefan Roese }
216f1df9364SStefan Roese }
217f1df9364SStefan Roese interface_state[if_id] = 0;
218f1df9364SStefan Roese }
219f1df9364SStefan Roese
220f1df9364SStefan Roese /* TODO: Set number of active interfaces */
2212b4ffbf6SChris Packham num_pup = octets_per_if_num * MAX_INTERFACE_NUM;
222f1df9364SStefan Roese
223f1df9364SStefan Roese while ((algo_run_flag <= num_pup) & (while_count < 10)) {
224f1df9364SStefan Roese while_count++;
225f1df9364SStefan Roese for (rep = 1; rep < 4; rep++) {
226f1df9364SStefan Roese ddr3_tip_centr_skip_min_win_check = 1;
227f1df9364SStefan Roese ddr3_tip_centralization_rx(dev_num);
228f1df9364SStefan Roese ddr3_tip_centr_skip_min_win_check = 0;
229f1df9364SStefan Roese
230f1df9364SStefan Roese /* Read Valid window results only for non converge pups */
231f1df9364SStefan Roese for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
2322b4ffbf6SChris Packham VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
233f1df9364SStefan Roese if (interface_state[if_id] != 4) {
234f1df9364SStefan Roese get_valid_win_rx(dev_num, if_id, res);
235f1df9364SStefan Roese for (pup = 0;
2362b4ffbf6SChris Packham pup < octets_per_if_num;
237f1df9364SStefan Roese pup++) {
2382b4ffbf6SChris Packham VALIDATE_BUS_ACTIVE
239f1df9364SStefan Roese (tm->bus_act_mask, pup);
240f1df9364SStefan Roese if (pup_st[pup]
241f1df9364SStefan Roese [if_id] ==
242f1df9364SStefan Roese VREF_CONVERGE)
243f1df9364SStefan Roese continue;
244f1df9364SStefan Roese
245f1df9364SStefan Roese current_valid_window[pup]
246f1df9364SStefan Roese [if_id] =
247f1df9364SStefan Roese (current_valid_window[pup]
248f1df9364SStefan Roese [if_id] * (rep - 1) +
249f1df9364SStefan Roese 1000 * res[pup]) / rep;
250f1df9364SStefan Roese }
251f1df9364SStefan Roese }
252f1df9364SStefan Roese }
253f1df9364SStefan Roese }
254f1df9364SStefan Roese
255f1df9364SStefan Roese for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
2562b4ffbf6SChris Packham VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
257f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(
258f1df9364SStefan Roese DEBUG_LEVEL_TRACE,
259f1df9364SStefan Roese ("current_valid_window: IF[ %d ] - ", if_id));
260f1df9364SStefan Roese
261f1df9364SStefan Roese for (pup = 0;
2622b4ffbf6SChris Packham pup < octets_per_if_num; pup++) {
2632b4ffbf6SChris Packham VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
264f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
265f1df9364SStefan Roese ("%d ",
266f1df9364SStefan Roese current_valid_window
267f1df9364SStefan Roese [pup][if_id]));
268f1df9364SStefan Roese }
269f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE, ("\n"));
270f1df9364SStefan Roese }
271f1df9364SStefan Roese
272f1df9364SStefan Roese /* Compare results and respond as function of state */
273f1df9364SStefan Roese for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
2742b4ffbf6SChris Packham VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
275f1df9364SStefan Roese for (pup = 0;
2762b4ffbf6SChris Packham pup < octets_per_if_num; pup++) {
2772b4ffbf6SChris Packham VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
278f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
279f1df9364SStefan Roese ("I/F[ %d ], pup[ %d ] STATE #%d (%d)\n",
280f1df9364SStefan Roese if_id, pup,
281f1df9364SStefan Roese pup_st[pup]
282f1df9364SStefan Roese [if_id], __LINE__));
283f1df9364SStefan Roese
284f1df9364SStefan Roese if (pup_st[pup][if_id] == VREF_CONVERGE)
285f1df9364SStefan Roese continue;
286f1df9364SStefan Roese
287f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(DEBUG_LEVEL_TRACE,
288f1df9364SStefan Roese ("I/F[ %d ], pup[ %d ] CHECK progress - Current %d Last %d, limit VREF %d (%d)\n",
289f1df9364SStefan Roese if_id, pup,
290f1df9364SStefan Roese current_valid_window[pup]
291f1df9364SStefan Roese [if_id],
292f1df9364SStefan Roese last_valid_window[pup]
293f1df9364SStefan Roese [if_id], lim_vref[pup]
294f1df9364SStefan Roese [if_id], __LINE__));
295f1df9364SStefan Roese
296f1df9364SStefan Roese /*
297f1df9364SStefan Roese * The -1 is for solution resolution +/- 1 tap
298f1df9364SStefan Roese * of ADLL
299f1df9364SStefan Roese */
300f1df9364SStefan Roese if (current_valid_window[pup][if_id] + 200 >=
301f1df9364SStefan Roese (last_valid_window[pup][if_id])) {
302f1df9364SStefan Roese if (pup_st[pup][if_id] == VREF_STEP_1) {
303f1df9364SStefan Roese /*
304f1df9364SStefan Roese * We stay in the same state and
305f1df9364SStefan Roese * step just update the window
306f1df9364SStefan Roese * size (take the max) and Vref
307f1df9364SStefan Roese */
308f1df9364SStefan Roese if (current_vref[pup]
309f1df9364SStefan Roese [if_id] == VREF_MAX_INDEX) {
310f1df9364SStefan Roese /*
311f1df9364SStefan Roese * If we step to the end
312f1df9364SStefan Roese * and didn't converge
313f1df9364SStefan Roese * to some particular
314f1df9364SStefan Roese * better Vref value
315f1df9364SStefan Roese * define the pup as
316f1df9364SStefan Roese * converge and step
317f1df9364SStefan Roese * back to nominal
318f1df9364SStefan Roese * Vref.
319f1df9364SStefan Roese */
320f1df9364SStefan Roese pup_st[pup]
321f1df9364SStefan Roese [if_id] =
322f1df9364SStefan Roese VREF_CONVERGE;
323f1df9364SStefan Roese algo_run_flag++;
324f1df9364SStefan Roese interface_state
325f1df9364SStefan Roese [if_id]++;
326f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
327f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
328f1df9364SStefan Roese ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
329f1df9364SStefan Roese if_id, pup,
330f1df9364SStefan Roese current_vref[pup]
331f1df9364SStefan Roese [if_id],
332f1df9364SStefan Roese __LINE__));
333f1df9364SStefan Roese } else {
334f1df9364SStefan Roese /* continue to update the Vref index */
335f1df9364SStefan Roese current_vref[pup]
336f1df9364SStefan Roese [if_id] =
337f1df9364SStefan Roese ((current_vref[pup]
338f1df9364SStefan Roese [if_id] +
339f1df9364SStefan Roese initial_step) >
340f1df9364SStefan Roese VREF_MAX_INDEX) ?
341f1df9364SStefan Roese VREF_MAX_INDEX
342f1df9364SStefan Roese : (current_vref[pup]
343f1df9364SStefan Roese [if_id] +
344f1df9364SStefan Roese initial_step);
345f1df9364SStefan Roese if (current_vref[pup]
346f1df9364SStefan Roese [if_id] ==
347f1df9364SStefan Roese VREF_MAX_INDEX) {
348f1df9364SStefan Roese pup_st[pup]
349f1df9364SStefan Roese [if_id]
350f1df9364SStefan Roese =
351f1df9364SStefan Roese VREF_STEP_2;
352f1df9364SStefan Roese }
353f1df9364SStefan Roese lim_vref[pup]
354f1df9364SStefan Roese [if_id] =
355f1df9364SStefan Roese last_vref[pup]
356f1df9364SStefan Roese [if_id] =
357f1df9364SStefan Roese current_vref[pup]
358f1df9364SStefan Roese [if_id];
359f1df9364SStefan Roese }
360f1df9364SStefan Roese
361f1df9364SStefan Roese last_valid_window[pup]
362f1df9364SStefan Roese [if_id] =
363f1df9364SStefan Roese GET_MAX(current_valid_window
364f1df9364SStefan Roese [pup][if_id],
365f1df9364SStefan Roese last_valid_window
366f1df9364SStefan Roese [pup]
367f1df9364SStefan Roese [if_id]);
368f1df9364SStefan Roese
369f1df9364SStefan Roese /* update the Vref for next stage */
370f1df9364SStefan Roese currrent_vref =
371f1df9364SStefan Roese current_vref[pup]
372f1df9364SStefan Roese [if_id];
373f1df9364SStefan Roese CHECK_STATUS
374f1df9364SStefan Roese (ddr3_tip_bus_read
375f1df9364SStefan Roese (dev_num, if_id,
376f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
377f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
378f1df9364SStefan Roese &val));
379f1df9364SStefan Roese CHECK_STATUS
380f1df9364SStefan Roese (ddr3_tip_bus_write
381f1df9364SStefan Roese (dev_num,
382f1df9364SStefan Roese ACCESS_TYPE_UNICAST,
383f1df9364SStefan Roese if_id,
384f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
385f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
386f1df9364SStefan Roese (val & (~0xf)) |
387f1df9364SStefan Roese vref_map[currrent_vref]));
388f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
389f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
390f1df9364SStefan Roese ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
391f1df9364SStefan Roese if_id, pup,
392f1df9364SStefan Roese (val & (~0xf)) |
393f1df9364SStefan Roese vref_map[currrent_vref],
394f1df9364SStefan Roese __LINE__));
395f1df9364SStefan Roese } else if (pup_st[pup][if_id]
396f1df9364SStefan Roese == VREF_STEP_2) {
397f1df9364SStefan Roese /*
398f1df9364SStefan Roese * We keep on search back with
399f1df9364SStefan Roese * the same step size.
400f1df9364SStefan Roese */
401f1df9364SStefan Roese last_valid_window[pup]
402f1df9364SStefan Roese [if_id] =
403f1df9364SStefan Roese GET_MAX(current_valid_window
404f1df9364SStefan Roese [pup][if_id],
405f1df9364SStefan Roese last_valid_window
406f1df9364SStefan Roese [pup]
407f1df9364SStefan Roese [if_id]);
408f1df9364SStefan Roese last_vref[pup][if_id] =
409f1df9364SStefan Roese current_vref[pup]
410f1df9364SStefan Roese [if_id];
411f1df9364SStefan Roese
412f1df9364SStefan Roese /* we finish all search space */
413f1df9364SStefan Roese if ((current_vref[pup]
414f1df9364SStefan Roese [if_id] - second_step) == lim_vref[pup][if_id]) {
415f1df9364SStefan Roese /*
416f1df9364SStefan Roese * If we step to the end
417f1df9364SStefan Roese * and didn't converge
418f1df9364SStefan Roese * to some particular
419f1df9364SStefan Roese * better Vref value
420f1df9364SStefan Roese * define the pup as
421f1df9364SStefan Roese * converge and step
422f1df9364SStefan Roese * back to nominal
423f1df9364SStefan Roese * Vref.
424f1df9364SStefan Roese */
425f1df9364SStefan Roese pup_st[pup]
426f1df9364SStefan Roese [if_id] =
427f1df9364SStefan Roese VREF_CONVERGE;
428f1df9364SStefan Roese algo_run_flag++;
429f1df9364SStefan Roese
430f1df9364SStefan Roese interface_state
431f1df9364SStefan Roese [if_id]++;
432f1df9364SStefan Roese
433f1df9364SStefan Roese current_vref[pup]
434f1df9364SStefan Roese [if_id] =
435f1df9364SStefan Roese (current_vref[pup]
436f1df9364SStefan Roese [if_id] -
437f1df9364SStefan Roese second_step);
438f1df9364SStefan Roese
439f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
440f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
441f1df9364SStefan Roese ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
442f1df9364SStefan Roese if_id, pup,
443f1df9364SStefan Roese current_vref[pup]
444f1df9364SStefan Roese [if_id],
445f1df9364SStefan Roese __LINE__));
446f1df9364SStefan Roese } else
447f1df9364SStefan Roese /* we finish all search space */
448f1df9364SStefan Roese if (current_vref[pup]
449f1df9364SStefan Roese [if_id] ==
450f1df9364SStefan Roese lim_vref[pup]
451f1df9364SStefan Roese [if_id]) {
452f1df9364SStefan Roese /*
453f1df9364SStefan Roese * If we step to the end
454f1df9364SStefan Roese * and didn't converge
455f1df9364SStefan Roese * to some particular
456f1df9364SStefan Roese * better Vref value
457f1df9364SStefan Roese * define the pup as
458f1df9364SStefan Roese * converge and step
459f1df9364SStefan Roese * back to nominal
460f1df9364SStefan Roese * Vref.
461f1df9364SStefan Roese */
462f1df9364SStefan Roese pup_st[pup]
463f1df9364SStefan Roese [if_id] =
464f1df9364SStefan Roese VREF_CONVERGE;
465f1df9364SStefan Roese
466f1df9364SStefan Roese algo_run_flag++;
467f1df9364SStefan Roese interface_state
468f1df9364SStefan Roese [if_id]++;
469f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
470f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
471f1df9364SStefan Roese ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
472f1df9364SStefan Roese if_id, pup,
473f1df9364SStefan Roese current_vref[pup]
474f1df9364SStefan Roese [if_id],
475f1df9364SStefan Roese __LINE__));
476f1df9364SStefan Roese } else {
477f1df9364SStefan Roese current_vref[pup]
478f1df9364SStefan Roese [if_id] =
479f1df9364SStefan Roese current_vref[pup]
480f1df9364SStefan Roese [if_id] -
481f1df9364SStefan Roese second_step;
482f1df9364SStefan Roese }
483f1df9364SStefan Roese
484f1df9364SStefan Roese /* Update the Vref for next stage */
485f1df9364SStefan Roese currrent_vref =
486f1df9364SStefan Roese current_vref[pup]
487f1df9364SStefan Roese [if_id];
488f1df9364SStefan Roese CHECK_STATUS
489f1df9364SStefan Roese (ddr3_tip_bus_read
490f1df9364SStefan Roese (dev_num, if_id,
491f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
492f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
493f1df9364SStefan Roese &val));
494f1df9364SStefan Roese CHECK_STATUS
495f1df9364SStefan Roese (ddr3_tip_bus_write
496f1df9364SStefan Roese (dev_num,
497f1df9364SStefan Roese ACCESS_TYPE_UNICAST,
498f1df9364SStefan Roese if_id,
499f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
500f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
501f1df9364SStefan Roese (val & (~0xf)) |
502f1df9364SStefan Roese vref_map[currrent_vref]));
503f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
504f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
505f1df9364SStefan Roese ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
506f1df9364SStefan Roese if_id, pup,
507f1df9364SStefan Roese (val & (~0xf)) |
508f1df9364SStefan Roese vref_map[currrent_vref],
509f1df9364SStefan Roese __LINE__));
510f1df9364SStefan Roese }
511f1df9364SStefan Roese } else {
512f1df9364SStefan Roese /* we change state and change step */
513f1df9364SStefan Roese if (pup_st[pup][if_id] == VREF_STEP_1) {
514f1df9364SStefan Roese pup_st[pup][if_id] =
515f1df9364SStefan Roese VREF_STEP_2;
516f1df9364SStefan Roese lim_vref[pup][if_id] =
517f1df9364SStefan Roese current_vref[pup]
518f1df9364SStefan Roese [if_id] - initial_step;
519f1df9364SStefan Roese last_valid_window[pup]
520f1df9364SStefan Roese [if_id] =
521f1df9364SStefan Roese current_valid_window[pup]
522f1df9364SStefan Roese [if_id];
523f1df9364SStefan Roese last_vref[pup][if_id] =
524f1df9364SStefan Roese current_vref[pup]
525f1df9364SStefan Roese [if_id];
526f1df9364SStefan Roese current_vref[pup][if_id] =
527f1df9364SStefan Roese last_vref[pup][if_id] -
528f1df9364SStefan Roese second_step;
529f1df9364SStefan Roese
530f1df9364SStefan Roese /* Update the Vref for next stage */
531f1df9364SStefan Roese CHECK_STATUS
532f1df9364SStefan Roese (ddr3_tip_bus_read
533f1df9364SStefan Roese (dev_num, if_id,
534f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
535f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
536f1df9364SStefan Roese &val));
537f1df9364SStefan Roese CHECK_STATUS
538f1df9364SStefan Roese (ddr3_tip_bus_write
539f1df9364SStefan Roese (dev_num,
540f1df9364SStefan Roese ACCESS_TYPE_UNICAST,
541f1df9364SStefan Roese if_id,
542f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
543f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
544f1df9364SStefan Roese (val & (~0xf)) |
545f1df9364SStefan Roese vref_map[current_vref[pup]
546f1df9364SStefan Roese [if_id]]));
547f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
548f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
549f1df9364SStefan Roese ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
550f1df9364SStefan Roese if_id, pup,
551f1df9364SStefan Roese (val & (~0xf)) |
552f1df9364SStefan Roese vref_map[current_vref[pup]
553f1df9364SStefan Roese [if_id]],
554f1df9364SStefan Roese __LINE__));
555f1df9364SStefan Roese
556f1df9364SStefan Roese } else if (pup_st[pup][if_id] == VREF_STEP_2) {
557f1df9364SStefan Roese /*
558f1df9364SStefan Roese * The last search was the max
559f1df9364SStefan Roese * point set value and exit
560f1df9364SStefan Roese */
561f1df9364SStefan Roese CHECK_STATUS
562f1df9364SStefan Roese (ddr3_tip_bus_read
563f1df9364SStefan Roese (dev_num, if_id,
564f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
565f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
566f1df9364SStefan Roese &val));
567f1df9364SStefan Roese CHECK_STATUS
568f1df9364SStefan Roese (ddr3_tip_bus_write
569f1df9364SStefan Roese (dev_num,
570f1df9364SStefan Roese ACCESS_TYPE_UNICAST,
571f1df9364SStefan Roese if_id,
572f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
573f1df9364SStefan Roese DDR_PHY_DATA, reg_addr,
574f1df9364SStefan Roese (val & (~0xf)) |
575f1df9364SStefan Roese vref_map[last_vref[pup]
576f1df9364SStefan Roese [if_id]]));
577f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
578f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
579f1df9364SStefan Roese ("VREF config, IF[ %d ]pup[ %d ] - Vref = %X (%d)\n",
580f1df9364SStefan Roese if_id, pup,
581f1df9364SStefan Roese (val & (~0xf)) |
582f1df9364SStefan Roese vref_map[last_vref[pup]
583f1df9364SStefan Roese [if_id]],
584f1df9364SStefan Roese __LINE__));
585f1df9364SStefan Roese pup_st[pup][if_id] =
586f1df9364SStefan Roese VREF_CONVERGE;
587f1df9364SStefan Roese algo_run_flag++;
588f1df9364SStefan Roese interface_state[if_id]++;
589f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG
590f1df9364SStefan Roese (DEBUG_LEVEL_TRACE,
591f1df9364SStefan Roese ("I/F[ %d ], pup[ %d ] VREF_CONVERGE - Vref = %X (%d)\n",
592f1df9364SStefan Roese if_id, pup,
593f1df9364SStefan Roese current_vref[pup]
594f1df9364SStefan Roese [if_id], __LINE__));
595f1df9364SStefan Roese }
596f1df9364SStefan Roese }
597f1df9364SStefan Roese }
598f1df9364SStefan Roese }
599f1df9364SStefan Roese }
600f1df9364SStefan Roese
601f1df9364SStefan Roese for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
6022b4ffbf6SChris Packham VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
603f1df9364SStefan Roese for (pup = 0;
6042b4ffbf6SChris Packham pup < octets_per_if_num; pup++) {
6052b4ffbf6SChris Packham VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup);
606f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_bus_read
607f1df9364SStefan Roese (dev_num, if_id,
608f1df9364SStefan Roese ACCESS_TYPE_UNICAST, pup,
609f1df9364SStefan Roese DDR_PHY_DATA, reg_addr, &val));
610f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(
611f1df9364SStefan Roese DEBUG_LEVEL_INFO,
612f1df9364SStefan Roese ("FINAL values: I/F[ %d ], pup[ %d ] - Vref = %X (%d)\n",
613f1df9364SStefan Roese if_id, pup, val, __LINE__));
614f1df9364SStefan Roese }
615f1df9364SStefan Roese }
616f1df9364SStefan Roese
617f1df9364SStefan Roese flow_result[if_id] = TEST_SUCCESS;
618f1df9364SStefan Roese
619f1df9364SStefan Roese /* restore start/end pattern */
620f1df9364SStefan Roese start_pattern = copy_start_pattern;
621f1df9364SStefan Roese end_pattern = copy_end_pattern;
622f1df9364SStefan Roese
623f1df9364SStefan Roese return 0;
624f1df9364SStefan Roese }
625f1df9364SStefan Roese
626f1df9364SStefan Roese /*
627f1df9364SStefan Roese * CK/CA Delay
628f1df9364SStefan Roese */
ddr3_tip_cmd_addr_init_delay(u32 dev_num,u32 adll_tap)629f1df9364SStefan Roese int ddr3_tip_cmd_addr_init_delay(u32 dev_num, u32 adll_tap)
630f1df9364SStefan Roese {
631f1df9364SStefan Roese u32 if_id = 0;
632f1df9364SStefan Roese u32 ck_num_adll_tap = 0, ca_num_adll_tap = 0, data = 0;
6332b4ffbf6SChris Packham struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
634f1df9364SStefan Roese
635f1df9364SStefan Roese /*
636f1df9364SStefan Roese * ck_delay_table is delaying the of the clock signal only.
637f1df9364SStefan Roese * (to overcome timing issues between_c_k & command/address signals)
638f1df9364SStefan Roese */
639f1df9364SStefan Roese /*
640f1df9364SStefan Roese * ca_delay is delaying the of the entire command & Address signals
641f1df9364SStefan Roese * (include Clock signal to overcome DGL error on the Clock versus
642f1df9364SStefan Roese * the DQS).
643f1df9364SStefan Roese */
644f1df9364SStefan Roese
645f1df9364SStefan Roese /* Calc ADLL Tap */
6462b4ffbf6SChris Packham if (ck_delay == PARAM_UNDEFINED)
647f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(
648f1df9364SStefan Roese DEBUG_LEVEL_ERROR,
6492b4ffbf6SChris Packham ("ERROR: ck_delay is not initialized!\n"));
650f1df9364SStefan Roese
651f1df9364SStefan Roese for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
6522b4ffbf6SChris Packham VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
653f1df9364SStefan Roese
6542b4ffbf6SChris Packham /* Calc delay ps in ADLL tap */
6552b4ffbf6SChris Packham ck_num_adll_tap = ck_delay / adll_tap;
656f1df9364SStefan Roese ca_num_adll_tap = ca_delay / adll_tap;
6572b4ffbf6SChris Packham
658f1df9364SStefan Roese data = (ck_num_adll_tap & 0x3f) +
659f1df9364SStefan Roese ((ca_num_adll_tap & 0x3f) << 10);
660f1df9364SStefan Roese
661f1df9364SStefan Roese /*
662f1df9364SStefan Roese * Set the ADLL number to the CK ADLL for Interfaces for
663f1df9364SStefan Roese * all Pup
664f1df9364SStefan Roese */
665f1df9364SStefan Roese DEBUG_TRAINING_HW_ALG(
666f1df9364SStefan Roese DEBUG_LEVEL_TRACE,
667f1df9364SStefan Roese ("ck_num_adll_tap %d ca_num_adll_tap %d adll_tap %d\n",
668f1df9364SStefan Roese ck_num_adll_tap, ca_num_adll_tap, adll_tap));
669f1df9364SStefan Roese
670f1df9364SStefan Roese CHECK_STATUS(ddr3_tip_bus_write(dev_num, ACCESS_TYPE_UNICAST,
671f1df9364SStefan Roese if_id, ACCESS_TYPE_MULTICAST,
672f1df9364SStefan Roese PARAM_NOT_CARE, DDR_PHY_CONTROL,
673f1df9364SStefan Roese 0x0, data));
674f1df9364SStefan Roese }
675f1df9364SStefan Roese
676f1df9364SStefan Roese return MV_OK;
677f1df9364SStefan Roese }
678