• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Marvell International Ltd. and its affiliates
4  */
5 
6 #include "ddr3_init.h"
7 #include "mv_ddr_regs.h"
8 #include "ddr_training_ip_db.h"
9 
10 #define PATTERN_1	0x55555555
11 #define PATTERN_2	0xaaaaaaaa
12 
13 #define VALIDATE_TRAINING_LIMIT(e1, e2)			\
14 	((((e2) - (e1) + 1) > 33) && ((e1) < 67))
15 
16 u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
17 
18 u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS *
19 		 HWS_SEARCH_DIR_LIMIT];
20 u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM];	/* holds the bit status in the byte in wrapper function*/
21 
22 u16 mask_results_dq_reg_map[] = {
23 	RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
24 	RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
25 	RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
26 	RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
27 	RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
28 	RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
29 	RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
30 	RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
31 	RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
32 	RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
33 	RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
34 	RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
35 	RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
36 	RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
37 	RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
38 	RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG,
39 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
40 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
41 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
42 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
43 #if MAX_BUS_NUM == 9
44 	RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG,
45 	RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG,
46 	RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG,
47 	RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG,
48 	RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG,
49 	RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG,
50 	RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG,
51 	RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG,
52 	RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG,
53 	RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG,
54 	RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG,
55 	RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG,
56 	RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG,
57 	RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG,
58 	RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG,
59 	RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG,
60 #endif
61 	0xffff
62 };
63 
64 u16 mask_results_pup_reg_map[] = {
65 	RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
66 	RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG,
67 	RESULT_CONTROL_BYTE_PUP_4_REG,
68 #if MAX_BUS_NUM == 9
69 	RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG,
70 	RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG,
71 #endif
72 	0xffff
73 };
74 
75 #if MAX_BUS_NUM == 5
76 u16 mask_results_dq_reg_map_pup3_ecc[] = {
77 	RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
78 	RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
79 	RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
80 	RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
81 	RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
82 	RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
83 	RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
84 	RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
85 	RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
86 	RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
87 	RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
88 	RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
89 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
90 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
91 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
92 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
93 	RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
94 	RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
95 	RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
96 	RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG
97 };
98 #endif
99 
100 #if MAX_BUS_NUM == 5
101 u16 mask_results_pup_reg_map_pup3_ecc[] = {
102 	RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
103 	RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG,
104 	RESULT_CONTROL_BYTE_PUP_4_REG
105 };
106 #endif
107 
108 struct pattern_info pattern_table_64[] = {
109 	/*
110 	 * num_of_phases_tx, tx_burst_size;
111 	 * delay_between_bursts, num_of_phases_rx,
112 	 * start_addr, pattern_len
113 	 */
114 	{0x7, 0x7, 2, 0x7, 0x00000, 8},		/* PATTERN_PBS1 */
115 	{0x7, 0x7, 2, 0x7, 0x00080, 8},		/* PATTERN_PBS2 */
116 	{0x7, 0x7, 2, 0x7, 0x00100, 8},		/* PATTERN_PBS3 */
117 	{0x7, 0x7, 2, 0x7, 0x00030, 8},		/* PATTERN_TEST */
118 	{0x7, 0x7, 2, 0x7, 0x00100, 8},		/* PATTERN_RL */
119 	{0x7, 0x7, 2, 0x7, 0x00100, 8},		/* PATTERN_RL2 */
120 	{0x1f, 0xf, 2, 0xf, 0x00680, 32},	/* PATTERN_STATIC_PBS */
121 	{0x1f, 0xf, 2, 0xf, 0x00a80, 32},	/* PATTERN_KILLER_DQ0 */
122 	{0x1f, 0xf, 2, 0xf, 0x01280, 32},	/* PATTERN_KILLER_DQ1 */
123 	{0x1f, 0xf, 2, 0xf, 0x01a80, 32},	/* PATTERN_KILLER_DQ2 */
124 	{0x1f, 0xf, 2, 0xf, 0x02280, 32},	/* PATTERN_KILLER_DQ3 */
125 	{0x1f, 0xf, 2, 0xf, 0x02a80, 32},	/* PATTERN_KILLER_DQ4 */
126 	{0x1f, 0xf, 2, 0xf, 0x03280, 32},	/* PATTERN_KILLER_DQ5 */
127 	{0x1f, 0xf, 2, 0xf, 0x03a80, 32},	/* PATTERN_KILLER_DQ6 */
128 	{0x1f, 0xf, 2, 0xf, 0x04280, 32},	/* PATTERN_KILLER_DQ7 */
129 	{0x1f, 0xf, 2, 0xf, 0x00e80, 32},	/* PATTERN_KILLER_DQ0_64 */
130 	{0x1f, 0xf, 2, 0xf, 0x01680, 32},	/* PATTERN_KILLER_DQ1_64 */
131 	{0x1f, 0xf, 2, 0xf, 0x01e80, 32},	/* PATTERN_KILLER_DQ2_64 */
132 	{0x1f, 0xf, 2, 0xf, 0x02680, 32},	/* PATTERN_KILLER_DQ3_64 */
133 	{0x1f, 0xf, 2, 0xf, 0x02e80, 32},	/* PATTERN_KILLER_DQ4_64 */
134 	{0x1f, 0xf, 2, 0xf, 0x03680, 32},	/* PATTERN_KILLER_DQ5_64 */
135 	{0x1f, 0xf, 2, 0xf, 0x03e80, 32},	/* PATTERN_KILLER_DQ6_64 */
136 	{0x1f, 0xf, 2, 0xf, 0x04680, 32},	/* PATTERN_KILLER_DQ7_64 */
137 	{0x1f, 0xf, 2, 0xf, 0x04a80, 32},	/* PATTERN_KILLER_DQ0_INV */
138 	{0x1f, 0xf, 2, 0xf, 0x05280, 32},	/* PATTERN_KILLER_DQ1_INV */
139 	{0x1f, 0xf, 2, 0xf, 0x05a80, 32},	/* PATTERN_KILLER_DQ2_INV */
140 	{0x1f, 0xf, 2, 0xf, 0x06280, 32},	/* PATTERN_KILLER_DQ3_INV */
141 	{0x1f, 0xf, 2, 0xf, 0x06a80, 32},	/* PATTERN_KILLER_DQ4_INV */
142 	{0x1f, 0xf, 2, 0xf, 0x07280, 32},	/* PATTERN_KILLER_DQ5_INV */
143 	{0x1f, 0xf, 2, 0xf, 0x07a80, 32},	/* PATTERN_KILLER_DQ6_INV */
144 	{0x1f, 0xf, 2, 0xf, 0x08280, 32},	/* PATTERN_KILLER_DQ7_INV */
145 	{0x1f, 0xf, 2, 0xf, 0x04e80, 32},	/* PATTERN_KILLER_DQ0_INV_64 */
146 	{0x1f, 0xf, 2, 0xf, 0x05680, 32},	/* PATTERN_KILLER_DQ1_INV_64 */
147 	{0x1f, 0xf, 2, 0xf, 0x05e80, 32},	/* PATTERN_KILLER_DQ2_INV_64 */
148 	{0x1f, 0xf, 2, 0xf, 0x06680, 32},	/* PATTERN_KILLER_DQ3_INV_64 */
149 	{0x1f, 0xf, 2, 0xf, 0x06e80, 32},	/* PATTERN_KILLER_DQ4_INV_64 */
150 	{0x1f, 0xf, 2, 0xf, 0x07680, 32},	/* PATTERN_KILLER_DQ5_INV_64 */
151 	{0x1f, 0xf, 2, 0xf, 0x07e80, 32},	/* PATTERN_KILLER_DQ6_INV_64 */
152 	{0x1f, 0xf, 2, 0xf, 0x08680, 32},	/* PATTERN_KILLER_DQ7_INV_64 */
153 	{0x1f, 0xf, 2, 0xf, 0x08a80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ0 */
154 	{0x1f, 0xf, 2, 0xf, 0x09280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
155 	{0x1f, 0xf, 2, 0xf, 0x09a80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ2 */
156 	{0x1f, 0xf, 2, 0xf, 0x0a280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ3 */
157 	{0x1f, 0xf, 2, 0xf, 0x0aa80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ4 */
158 	{0x1f, 0xf, 2, 0xf, 0x0b280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ5 */
159 	{0x1f, 0xf, 2, 0xf, 0x0ba80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ6 */
160 	{0x1f, 0xf, 2, 0xf, 0x0c280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ7 */
161 	{0x1f, 0xf, 2, 0xf, 0x08e80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ0_64 */
162 	{0x1f, 0xf, 2, 0xf, 0x09680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ1_64 */
163 	{0x1f, 0xf, 2, 0xf, 0x09e80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ2_64 */
164 	{0x1f, 0xf, 2, 0xf, 0x0a680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ3_64 */
165 	{0x1f, 0xf, 2, 0xf, 0x0ae80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ4_64 */
166 	{0x1f, 0xf, 2, 0xf, 0x0b680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ5_64 */
167 	{0x1f, 0xf, 2, 0xf, 0x0be80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ6_64 */
168 	{0x1f, 0xf, 2, 0xf, 0x0c680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ7_64 */
169 	{0x1f, 0xf, 2, 0xf, 0x0ca80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ0 */
170 	{0x1f, 0xf, 2, 0xf, 0x0d280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ1 */
171 	{0x1f, 0xf, 2, 0xf, 0x0da80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ2 */
172 	{0x1f, 0xf, 2, 0xf, 0x0e280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ3 */
173 	{0x1f, 0xf, 2, 0xf, 0x0ea80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ4 */
174 	{0x1f, 0xf, 2, 0xf, 0x0f280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ5 */
175 	{0x1f, 0xf, 2, 0xf, 0x0fa80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ6 */
176 	{0x1f, 0xf, 2, 0xf, 0x10280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ7 */
177 	{0x1f, 0xf, 2, 0xf, 0x0ce80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ0_64 */
178 	{0x1f, 0xf, 2, 0xf, 0x0d680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ1_64 */
179 	{0x1f, 0xf, 2, 0xf, 0x0de80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ2_64 */
180 	{0x1f, 0xf, 2, 0xf, 0x0e680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ3_64 */
181 	{0x1f, 0xf, 2, 0xf, 0x0ee80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ4_64 */
182 	{0x1f, 0xf, 2, 0xf, 0x0f680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ5_64 */
183 	{0x1f, 0xf, 2, 0xf, 0x0fe80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ6_64 */
184 	{0x1f, 0xf, 2, 0xf, 0x10680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ7_64 */
185 	{0x1f, 0xf, 2, 0xf, 0x10a80, 32},	/* PATTERN_ISI_XTALK_FREE */
186 	{0x1f, 0xf, 2, 0xf, 0x10e80, 32},	/* PATTERN_ISI_XTALK_FREE_64 */
187 	{0x1f, 0xf, 2, 0xf, 0x11280, 32},	/* PATTERN_VREF */
188 	{0x1f, 0xf, 2, 0xf, 0x11680, 32},	/* PATTERN_VREF_64 */
189 	{0x1f, 0xf, 2, 0xf, 0x11a80, 32},	/* PATTERN_VREF_INV */
190 	{0x1f, 0xf, 2, 0xf, 0x11e80, 32},	/* PATTERN_FULL_SSO_0T */
191 	{0x1f, 0xf, 2, 0xf, 0x12280, 32},	/* PATTERN_FULL_SSO_1T */
192 	{0x1f, 0xf, 2, 0xf, 0x12680, 32},	/* PATTERN_FULL_SSO_2T */
193 	{0x1f, 0xf, 2, 0xf, 0x12a80, 32},	/* PATTERN_FULL_SSO_3T */
194 	{0x1f, 0xf, 2, 0xf, 0x12e80, 32},	/* PATTERN_RESONANCE_1T */
195 	{0x1f, 0xf, 2, 0xf, 0x13280, 32},	/* PATTERN_RESONANCE_2T */
196 	{0x1f, 0xf, 2, 0xf, 0x13680, 32},	/* PATTERN_RESONANCE_3T */
197 	{0x1f, 0xf, 2, 0xf, 0x13a80, 32},	/* PATTERN_RESONANCE_4T */
198 	{0x1f, 0xf, 2, 0xf, 0x13e80, 32},	/* PATTERN_RESONANCE_5T */
199 	{0x1f, 0xf, 2, 0xf, 0x14280, 32},	/* PATTERN_RESONANCE_6T */
200 	{0x1f, 0xf, 2, 0xf, 0x14680, 32},	/* PATTERN_RESONANCE_7T */
201 	{0x1f, 0xf, 2, 0xf, 0x14a80, 32},	/* PATTERN_RESONANCE_8T */
202 	{0x1f, 0xf, 2, 0xf, 0x14e80, 32},	/* PATTERN_RESONANCE_9T */
203 	{0x1f, 0xf, 2, 0xf, 0x15280, 32},	/* PATTERN_ZERO */
204 	{0x1f, 0xf, 2, 0xf, 0x15680, 32}	/* PATTERN_ONE */
205 	/* Note: actual start_address is "<< 3" of defined address */
206 };
207 
208 struct pattern_info pattern_table_16[] = {
209 	/*
210 	 * num tx phases, tx burst, delay between, rx pattern,
211 	 * start_address, pattern_len
212 	 */
213 	{1, 1, 2, 1, 0x0080, 2},	/* PATTERN_PBS1 */
214 	{1, 1, 2, 1, 0x00c0, 2},	/* PATTERN_PBS2 */
215 	{1, 1, 2, 1, 0x0380, 2},	/* PATTERN_PBS3 */
216 	{1, 1, 2, 1, 0x0040, 2},	/* PATTERN_TEST */
217 	{1, 1, 2, 1, 0x0100, 2},	/* PATTERN_RL */
218 	{1, 1, 2, 1, 0x0000, 2},	/* PATTERN_RL2 */
219 	{0xf, 0x7, 2, 0x7, 0x0140, 16},	/* PATTERN_STATIC_PBS */
220 	{0xf, 0x7, 2, 0x7, 0x0190, 16},	/* PATTERN_KILLER_DQ0 */
221 	{0xf, 0x7, 2, 0x7, 0x01d0, 16},	/* PATTERN_KILLER_DQ1 */
222 	{0xf, 0x7, 2, 0x7, 0x0210, 16},	/* PATTERN_KILLER_DQ2 */
223 	{0xf, 0x7, 2, 0x7, 0x0250, 16},	/* PATTERN_KILLER_DQ3 */
224 	{0xf, 0x7, 2, 0x7, 0x0290, 16},	/* PATTERN_KILLER_DQ4 */
225 	{0xf, 0x7, 2, 0x7, 0x02d0, 16},	/* PATTERN_KILLER_DQ5 */
226 	{0xf, 0x7, 2, 0x7, 0x0310, 16},	/* PATTERN_KILLER_DQ6 */
227 	{0xf, 0x7, 2, 0x7, 0x0350, 16},	/* PATTERN_KILLER_DQ7 */
228 	{0xf, 0x7, 2, 0x7, 0x04c0, 16},	/* PATTERN_VREF */
229 	{0xf, 0x7, 2, 0x7, 0x03c0, 16},	/* PATTERN_FULL_SSO_1T */
230 	{0xf, 0x7, 2, 0x7, 0x0400, 16},	/* PATTERN_FULL_SSO_2T */
231 	{0xf, 0x7, 2, 0x7, 0x0440, 16},	/* PATTERN_FULL_SSO_3T */
232 	{0xf, 0x7, 2, 0x7, 0x0480, 16},	/* PATTERN_FULL_SSO_4T */
233 	{0xf, 7, 2, 7, 0x6280, 16},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
234 	{0xf, 7, 2, 7, 0x6680, 16},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
235 	{0xf, 7, 2, 7, 0x6A80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ2 */
236 	{0xf, 7, 2, 7, 0x6E80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ3 */
237 	{0xf, 7, 2, 7, 0x7280, 16},	/* PATTERN_SSO_FULL_XTALK_DQ4 */
238 	{0xf, 7, 2, 7, 0x7680, 16},	/* PATTERN_SSO_FULL_XTALK_DQ5 */
239 	{0xf, 7, 2, 7, 0x7A80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ6 */
240 	{0xf, 7, 2, 7, 0x7E80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ7 */
241 	{0xf, 7, 2, 7, 0x8280, 16},	/* PATTERN_SSO_XTALK_FREE_DQ0 */
242 	{0xf, 7, 2, 7, 0x8680, 16},	/* PATTERN_SSO_XTALK_FREE_DQ1 */
243 	{0xf, 7, 2, 7, 0x8A80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ2 */
244 	{0xf, 7, 2, 7, 0x8E80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ3 */
245 	{0xf, 7, 2, 7, 0x9280, 16},	/* PATTERN_SSO_XTALK_FREE_DQ4 */
246 	{0xf, 7, 2, 7, 0x9680, 16},	/* PATTERN_SSO_XTALK_FREE_DQ5 */
247 	{0xf, 7, 2, 7, 0x9A80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ6 */
248 	{0xf, 7, 2, 7, 0x9E80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ7 */
249 	{0xf, 7, 2, 7, 0xA280, 16}	/* PATTERN_ISI_XTALK_FREE */
250 	/* Note: actual start_address is "<< 3" of defined address */
251 };
252 
253 struct pattern_info pattern_table_32[] = {
254 	/*
255 	 * num tx phases, tx burst, delay between, rx pattern,
256 	 * start_address, pattern_len
257 	 */
258 	{3, 3, 2, 3, 0x0080, 4},	/* PATTERN_PBS1 */
259 	{3, 3, 2, 3, 0x00c0, 4},	/* PATTERN_PBS2 */
260 	{3, 3, 2, 3, 0x0380, 4},	/* PATTERN_PBS3 */
261 	{3, 3, 2, 3, 0x0040, 4},	/* PATTERN_TEST */
262 	{3, 3, 2, 3, 0x0100, 4},	/* PATTERN_RL */
263 	{3, 3, 2, 3, 0x0000, 4},	/* PATTERN_RL2 */
264 	{0x1f, 0xf, 2, 0xf, 0x0140, 32},	/* PATTERN_STATIC_PBS */
265 	{0x1f, 0xf, 2, 0xf, 0x0190, 32},	/* PATTERN_KILLER_DQ0 */
266 	{0x1f, 0xf, 2, 0xf, 0x01d0, 32},	/* PATTERN_KILLER_DQ1 */
267 	{0x1f, 0xf, 2, 0xf, 0x0210, 32},	/* PATTERN_KILLER_DQ2 */
268 	{0x1f, 0xf, 2, 0xf, 0x0250, 32},	/* PATTERN_KILLER_DQ3 */
269 	{0x1f, 0xf, 2, 0xf, 0x0290, 32},	/* PATTERN_KILLER_DQ4 */
270 	{0x1f, 0xf, 2, 0xf, 0x02d0, 32},	/* PATTERN_KILLER_DQ5 */
271 	{0x1f, 0xf, 2, 0xf, 0x0310, 32},	/* PATTERN_KILLER_DQ6 */
272 	{0x1f, 0xf, 2, 0xf, 0x0350, 32},	/* PATTERN_KILLER_DQ7 */
273 	{0x1f, 0xf, 2, 0xf, 0x04c0, 32},	/* PATTERN_VREF */
274 	{0x1f, 0xf, 2, 0xf, 0x03c0, 32},	/* PATTERN_FULL_SSO_1T */
275 	{0x1f, 0xf, 2, 0xf, 0x0400, 32},	/* PATTERN_FULL_SSO_2T */
276 	{0x1f, 0xf, 2, 0xf, 0x0440, 32},	/* PATTERN_FULL_SSO_3T */
277 	{0x1f, 0xf, 2, 0xf, 0x0480, 32},	/* PATTERN_FULL_SSO_4T */
278 	{0x1f, 0xF, 2, 0xf, 0x6280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ0 */
279 	{0x1f, 0xF, 2, 0xf, 0x6680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
280 	{0x1f, 0xF, 2, 0xf, 0x6A80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ2 */
281 	{0x1f, 0xF, 2, 0xf, 0x6E80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ3 */
282 	{0x1f, 0xF, 2, 0xf, 0x7280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ4 */
283 	{0x1f, 0xF, 2, 0xf, 0x7680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ5 */
284 	{0x1f, 0xF, 2, 0xf, 0x7A80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ6 */
285 	{0x1f, 0xF, 2, 0xf, 0x7E80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ7 */
286 	{0x1f, 0xF, 2, 0xf, 0x8280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ0 */
287 	{0x1f, 0xF, 2, 0xf, 0x8680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ1 */
288 	{0x1f, 0xF, 2, 0xf, 0x8A80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ2 */
289 	{0x1f, 0xF, 2, 0xf, 0x8E80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ3 */
290 	{0x1f, 0xF, 2, 0xf, 0x9280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ4 */
291 	{0x1f, 0xF, 2, 0xf, 0x9680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ5 */
292 	{0x1f, 0xF, 2, 0xf, 0x9A80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ6 */
293 	{0x1f, 0xF, 2, 0xf, 0x9E80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ7 */
294 	{0x1f, 0xF, 2, 0xf, 0xA280, 32}		/* PATTERN_ISI_XTALK_FREE */
295 	/* Note: actual start_address is "<< 3" of defined address */
296 };
297 
298 u32 train_dev_num;
299 enum hws_ddr_cs traintrain_cs_type;
300 u32 train_pup_num;
301 enum hws_training_result train_result_type;
302 enum hws_control_element train_control_element;
303 enum hws_search_dir traine_search_dir;
304 enum hws_dir train_direction;
305 u32 train_if_select;
306 u32 train_init_value;
307 u32 train_number_iterations;
308 enum hws_pattern train_pattern;
309 enum hws_edge_compare train_edge_compare;
310 u32 train_cs_num;
311 u32 train_if_acess, train_if_id, train_pup_access;
312 u32 max_polling_for_done = 1000000;
313 
ddr3_tip_get_buf_ptr(u32 dev_num,enum hws_search_dir search,enum hws_training_result result_type,u32 interface_num)314 u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
315 			  enum hws_training_result result_type,
316 			  u32 interface_num)
317 {
318 	u32 *buf_ptr = NULL;
319 
320 	buf_ptr = &training_res
321 		[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * search +
322 		 interface_num * MAX_BUS_NUM * BUS_WIDTH_IN_BITS];
323 
324 	return buf_ptr;
325 }
326 
327 enum {
328 	PASS,
329 	FAIL
330 };
331 /*
332  * IP Training search
333  * Note: for one edge search only from fail to pass, else jitter can
334  * be be entered into solution.
335  */
ddr3_tip_ip_training(u32 dev_num,enum hws_access_type access_type,u32 interface_num,enum hws_access_type pup_access_type,u32 pup_num,enum hws_training_result result_type,enum hws_control_element control_element,enum hws_search_dir search_dir,enum hws_dir direction,u32 interface_mask,u32 init_value,u32 num_iter,enum hws_pattern pattern,enum hws_edge_compare edge_comp,enum hws_ddr_cs cs_type,u32 cs_num,enum hws_training_ip_stat * train_status)336 int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
337 			 u32 interface_num,
338 			 enum hws_access_type pup_access_type,
339 			 u32 pup_num, enum hws_training_result result_type,
340 			 enum hws_control_element control_element,
341 			 enum hws_search_dir search_dir, enum hws_dir direction,
342 			 u32 interface_mask, u32 init_value, u32 num_iter,
343 			 enum hws_pattern pattern,
344 			 enum hws_edge_compare edge_comp,
345 			 enum hws_ddr_cs cs_type, u32 cs_num,
346 			 enum hws_training_ip_stat *train_status)
347 {
348 	u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt,
349 		reg_data, pup_id;
350 	u32 tx_burst_size;
351 	u32 delay_between_burst;
352 	u32 rd_mode;
353 	u32 data;
354 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
355 	u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
356 	u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
357 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
358 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
359 
360 	if (pup_num >= octets_per_if_num) {
361 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
362 					 ("pup_num %d not valid\n", pup_num));
363 	}
364 	if (interface_num >= MAX_INTERFACE_NUM) {
365 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
366 					 ("if_id %d not valid\n",
367 					  interface_num));
368 	}
369 	if (train_status == NULL) {
370 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
371 					 ("error param 4\n"));
372 		return MV_BAD_PARAM;
373 	}
374 
375 	/* load pattern */
376 	if (cs_type == CS_SINGLE) {
377 		/* All CSs to CS0     */
378 		CHECK_STATUS(ddr3_tip_if_write
379 			     (dev_num, access_type, interface_num,
380 			      DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3));
381 		/* All CSs to CS0     */
382 		CHECK_STATUS(ddr3_tip_if_write
383 			     (dev_num, access_type, interface_num,
384 			      ODPG_DATA_CTRL_REG,
385 			      (0x3 | (effective_cs << 26)), 0xc000003));
386 	} else {
387 		CHECK_STATUS(ddr3_tip_if_write
388 			     (dev_num, access_type, interface_num,
389 			      DUAL_DUNIT_CFG_REG, 0, 1 << 3));
390 		/*  CS select */
391 		CHECK_STATUS(ddr3_tip_if_write
392 			     (dev_num, access_type, interface_num,
393 			      ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26,
394 			      0x3 | 3 << 26));
395 	}
396 
397 	/* load pattern to ODPG */
398 	ddr3_tip_load_pattern_to_odpg(dev_num, access_type, interface_num,
399 				      pattern,
400 				      pattern_table[pattern].start_addr);
401 	tx_burst_size =	(direction == OPER_WRITE) ?
402 		pattern_table[pattern].tx_burst_size : 0;
403 	delay_between_burst = (direction == OPER_WRITE) ? 2 : 0;
404 	rd_mode = (direction == OPER_WRITE) ? 1 : 0;
405 	CHECK_STATUS(ddr3_tip_configure_odpg
406 		     (dev_num, access_type, interface_num, direction,
407 		      pattern_table[pattern].num_of_phases_tx, tx_burst_size,
408 		      pattern_table[pattern].num_of_phases_rx,
409 		      delay_between_burst, rd_mode, effective_cs, STRESS_NONE,
410 		      DURATION_SINGLE));
411 	reg_data = (direction == OPER_READ) ? 0 : (0x3 << 30);
412 	reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa;
413 	CHECK_STATUS(ddr3_tip_if_write
414 		     (dev_num, access_type, interface_num,
415 		      ODPG_WR_RD_MODE_ENA_REG, reg_data,
416 		      MASK_ALL_BITS));
417 	reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6;
418 	reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ?
419 		(1 << 7) : 0;
420 
421 	/* change from Pass to Fail will lock the result */
422 	if (pup_access_type == ACCESS_TYPE_MULTICAST)
423 		reg_data |= 0xe << 14;
424 	else
425 		reg_data |= pup_num << 14;
426 
427 	if (edge_comp == EDGE_FP) {
428 		/* don't search for readl edge change, only the state */
429 		reg_data |= (0 << 20);
430 	} else if (edge_comp == EDGE_FPF) {
431 		reg_data |= (0 << 20);
432 	} else {
433 		reg_data |= (3 << 20);
434 	}
435 
436 	CHECK_STATUS(ddr3_tip_if_write
437 		     (dev_num, access_type, interface_num,
438 		      GENERAL_TRAINING_OPCODE_REG,
439 		      reg_data | (0x7 << 8) | (0x7 << 11),
440 		      (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) |
441 		       (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20))));
442 	reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8);
443 	CHECK_STATUS(ddr3_tip_if_write
444 		     (dev_num, access_type, interface_num, OPCODE_REG0_REG(1),
445 		      1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26),
446 		      0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26)));
447 
448 	/*
449 	 * Write2_dunit(0x10b4, Number_iteration , [15:0])
450 	 * Max number of iterations
451 	 */
452 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
453 				       OPCODE_REG1_REG(1), num_iter,
454 				       0xffff));
455 	if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
456 	    direction == OPER_READ) {
457 		/*
458 		 * Write2_dunit(0x10c0, 0x5f , [7:0])
459 		 * MC PBS Reg Address at DDR PHY
460 		 */
461 		reg_data = PBS_RX_BCAST_PHY_REG(effective_cs);
462 	} else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
463 		   direction == OPER_WRITE) {
464 		reg_data = PBS_TX_BCAST_PHY_REG(effective_cs);
465 	} else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
466 		   direction == OPER_WRITE) {
467 		/*
468 		 * LOOP         0x00000001 + 4*n:
469 		 * where n (0-3) represents M_CS number
470 		 */
471 		/*
472 		 * Write2_dunit(0x10c0, 0x1 , [7:0])
473 		 * ADLL WR Reg Address at DDR PHY
474 		 */
475 		reg_data = CTX_PHY_REG(effective_cs);
476 	} else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
477 		   direction == OPER_READ) {
478 		/* ADLL RD Reg Address at DDR PHY */
479 		reg_data = CRX_PHY_REG(effective_cs);
480 	} else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
481 		   direction == OPER_WRITE) {
482 		/* TBD not defined in 0.5.0 requirement  */
483 	} else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
484 		   direction == OPER_READ) {
485 		/* TBD not defined in 0.5.0 requirement */
486 	}
487 
488 	reg_data |= (0x6 << 28);
489 	CHECK_STATUS(ddr3_tip_if_write
490 		     (dev_num, access_type, interface_num, CAL_PHY_REG(1),
491 		      reg_data | (init_value << 8),
492 		      0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28)));
493 
494 	mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS;
495 	mask_pup_num_of_regs = octets_per_if_num;
496 
497 	if (result_type == RESULT_PER_BIT) {
498 		for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
499 		     index_cnt++) {
500 			CHECK_STATUS(ddr3_tip_if_write
501 				     (dev_num, access_type, interface_num,
502 				      mask_results_dq_reg_map[index_cnt], 0,
503 				      1 << 24));
504 		}
505 
506 		/* Mask disabled buses */
507 		for (pup_id = 0; pup_id < octets_per_if_num;
508 		     pup_id++) {
509 			if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
510 				continue;
511 
512 			for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) {
513 				CHECK_STATUS(ddr3_tip_if_write
514 					     (dev_num, access_type,
515 					      interface_num,
516 					      mask_results_dq_reg_map
517 					      [index_cnt], (1 << 24), 1 << 24));
518 			}
519 		}
520 
521 		for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
522 		     index_cnt++) {
523 			CHECK_STATUS(ddr3_tip_if_write
524 				     (dev_num, access_type, interface_num,
525 				      mask_results_pup_reg_map[index_cnt],
526 				      (1 << 24), 1 << 24));
527 		}
528 	} else if (result_type == RESULT_PER_BYTE) {
529 		/* write to adll */
530 		for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
531 		     index_cnt++) {
532 			CHECK_STATUS(ddr3_tip_if_write
533 				     (dev_num, access_type, interface_num,
534 				      mask_results_pup_reg_map[index_cnt], 0,
535 				      1 << 24));
536 		}
537 		for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
538 		     index_cnt++) {
539 			CHECK_STATUS(ddr3_tip_if_write
540 				     (dev_num, access_type, interface_num,
541 				      mask_results_dq_reg_map[index_cnt],
542 				      (1 << 24), (1 << 24)));
543 		}
544 	}
545 
546 	/* trigger training */
547 	mv_ddr_training_enable();
548 
549 	/* wa for 16-bit mode: wait for all rfu tests to finish or timeout */
550 	mdelay(1);
551 
552 	/* check for training done */
553 	if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) {
554 		train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT;
555 	} else { /* training done; check for pass */
556 		if (data == PASS)
557 			train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS;
558 		else
559 			train_status[0] = HWS_TRAINING_IP_STATUS_FAIL;
560 	}
561 
562 	ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
563 			  ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
564 
565 	return MV_OK;
566 }
567 
568 /*
569  * Load expected Pattern to ODPG
570  */
ddr3_tip_load_pattern_to_odpg(u32 dev_num,enum hws_access_type access_type,u32 if_id,enum hws_pattern pattern,u32 load_addr)571 int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
572 				  u32 if_id, enum hws_pattern pattern,
573 				  u32 load_addr)
574 {
575 	u32 pattern_length_cnt = 0;
576 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
577 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
578 
579 	for (pattern_length_cnt = 0;
580 	     pattern_length_cnt < pattern_table[pattern].pattern_len;
581 	     pattern_length_cnt++) {	/* FIXME: the ecc patch below is only for a7040 A0 */
582 		if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) {
583 			CHECK_STATUS(ddr3_tip_if_write
584 				     (dev_num, access_type, if_id,
585 				      ODPG_DATA_WR_DATA_LOW_REG,
586 				      pattern_table_get_word(dev_num, pattern,
587 							     (u8) (pattern_length_cnt)),
588 				      MASK_ALL_BITS));
589 			CHECK_STATUS(ddr3_tip_if_write
590 				     (dev_num, access_type, if_id,
591 				      ODPG_DATA_WR_DATA_HIGH_REG,
592 				      pattern_table_get_word(dev_num, pattern,
593 							     (u8) (pattern_length_cnt)),
594 				      MASK_ALL_BITS));
595 		} else {
596 			CHECK_STATUS(ddr3_tip_if_write
597 				     (dev_num, access_type, if_id,
598 					      ODPG_DATA_WR_DATA_LOW_REG,
599 				      pattern_table_get_word(dev_num, pattern,
600 							     (u8) (pattern_length_cnt * 2)),
601 				      MASK_ALL_BITS));
602 			CHECK_STATUS(ddr3_tip_if_write
603 				     (dev_num, access_type, if_id,
604 				      ODPG_DATA_WR_DATA_HIGH_REG,
605 				      pattern_table_get_word(dev_num, pattern,
606 							     (u8) (pattern_length_cnt * 2 + 1)),
607 				      MASK_ALL_BITS));
608 		}
609 		CHECK_STATUS(ddr3_tip_if_write
610 			     (dev_num, access_type, if_id,
611 			      ODPG_DATA_WR_ADDR_REG, pattern_length_cnt,
612 			      MASK_ALL_BITS));
613 	}
614 
615 	CHECK_STATUS(ddr3_tip_if_write
616 		     (dev_num, access_type, if_id,
617 		      ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS));
618 
619 	return MV_OK;
620 }
621 
622 /*
623  * Configure ODPG
624  */
ddr3_tip_configure_odpg(u32 dev_num,enum hws_access_type access_type,u32 if_id,enum hws_dir direction,u32 tx_phases,u32 tx_burst_size,u32 rx_phases,u32 delay_between_burst,u32 rd_mode,u32 cs_num,u32 addr_stress_jump,u32 single_pattern)625 int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
626 			    u32 if_id, enum hws_dir direction, u32 tx_phases,
627 			    u32 tx_burst_size, u32 rx_phases,
628 			    u32 delay_between_burst, u32 rd_mode, u32 cs_num,
629 			    u32 addr_stress_jump, u32 single_pattern)
630 {
631 	u32 data_value = 0;
632 	int ret;
633 
634 	data_value = ((single_pattern << 2) | (tx_phases << 5) |
635 		      (tx_burst_size << 11) | (delay_between_burst << 15) |
636 		      (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) |
637 		      (addr_stress_jump << 29));
638 	ret = ddr3_tip_if_write(dev_num, access_type, if_id,
639 				ODPG_DATA_CTRL_REG, data_value, 0xaffffffc);
640 	if (ret != MV_OK)
641 		return ret;
642 
643 	return MV_OK;
644 }
645 
ddr3_tip_process_result(u32 * ar_result,enum hws_edge e_edge,enum hws_edge_search e_edge_search,u32 * edge_result)646 int ddr3_tip_process_result(u32 *ar_result, enum hws_edge e_edge,
647 			    enum hws_edge_search e_edge_search,
648 			    u32 *edge_result)
649 {
650 	u32 i, res;
651 	int tap_val, max_val = -10000, min_val = 10000;
652 	int lock_success = 1;
653 
654 	for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
655 		res = GET_LOCK_RESULT(ar_result[i]);
656 		if (res == 0) {
657 			lock_success = 0;
658 			break;
659 		}
660 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
661 					 ("lock failed for bit %d\n", i));
662 	}
663 
664 	if (lock_success == 1) {
665 		for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
666 			tap_val = GET_TAP_RESULT(ar_result[i], e_edge);
667 			if (tap_val > max_val)
668 				max_val = tap_val;
669 			if (tap_val < min_val)
670 				min_val = tap_val;
671 			if (e_edge_search == TRAINING_EDGE_MAX)
672 				*edge_result = (u32) max_val;
673 			else
674 				*edge_result = (u32) min_val;
675 
676 			DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
677 						 ("i %d ar_result[i] 0x%x tap_val %d max_val %d min_val %d Edge_result %d\n",
678 						  i, ar_result[i], tap_val,
679 						  max_val, min_val,
680 						  *edge_result));
681 		}
682 	} else {
683 		return MV_FAIL;
684 	}
685 
686 	return MV_OK;
687 }
688 
689 /*
690  * Read training search result
691  */
ddr3_tip_read_training_result(u32 dev_num,u32 if_id,enum hws_access_type pup_access_type,u32 pup_num,u32 bit_num,enum hws_search_dir search,enum hws_dir direction,enum hws_training_result result_type,enum hws_training_load_op operation,u32 cs_num_type,u32 ** load_res,int is_read_from_db,u8 cons_tap,int is_check_result_validity)692 int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
693 				  enum hws_access_type pup_access_type,
694 				  u32 pup_num, u32 bit_num,
695 				  enum hws_search_dir search,
696 				  enum hws_dir direction,
697 				  enum hws_training_result result_type,
698 				  enum hws_training_load_op operation,
699 				  u32 cs_num_type, u32 **load_res,
700 				  int is_read_from_db, u8 cons_tap,
701 				  int is_check_result_validity)
702 {
703 	u32 reg_offset, pup_cnt, start_pup, end_pup, start_reg, end_reg;
704 	u32 *interface_train_res = NULL;
705 	u16 *reg_addr = NULL;
706 	u32 read_data[MAX_INTERFACE_NUM];
707 	u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
708 	u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
709 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
710 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
711 
712 	/*
713 	 * Agreed assumption: all CS mask contain same number of bits,
714 	 * i.e. in multi CS, the number of CS per memory is the same for
715 	 * all pups
716 	 */
717 	CHECK_STATUS(ddr3_tip_if_write
718 		     (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG,
719 		      (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3)));
720 	CHECK_STATUS(ddr3_tip_if_write
721 		     (dev_num, ACCESS_TYPE_UNICAST, if_id,
722 		      ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26)));
723 	DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
724 				 ("Read_from_d_b %d cs_type %d oper %d result_type %d direction %d search %d pup_num %d if_id %d pup_access_type %d\n",
725 				  is_read_from_db, cs_num_type, operation,
726 				  result_type, direction, search, pup_num,
727 				  if_id, pup_access_type));
728 
729 	if ((load_res == NULL) && (is_read_from_db == 1)) {
730 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
731 					 ("ddr3_tip_read_training_result load_res = NULL"));
732 		return MV_FAIL;
733 	}
734 	if (pup_num >= octets_per_if_num) {
735 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
736 					 ("pup_num %d not valid\n", pup_num));
737 	}
738 	if (if_id >= MAX_INTERFACE_NUM) {
739 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
740 					 ("if_id %d not valid\n", if_id));
741 	}
742 	if (result_type == RESULT_PER_BIT)
743 		reg_addr = mask_results_dq_reg_map;
744 	else
745 		reg_addr = mask_results_pup_reg_map;
746 	if (pup_access_type == ACCESS_TYPE_UNICAST) {
747 		start_pup = pup_num;
748 		end_pup = pup_num;
749 	} else {		/*pup_access_type == ACCESS_TYPE_MULTICAST) */
750 
751 		start_pup = 0;
752 		end_pup = octets_per_if_num - 1;
753 	}
754 
755 	for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) {
756 		VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt);
757 		DEBUG_TRAINING_IP_ENGINE(
758 			DEBUG_LEVEL_TRACE,
759 			("if_id %d start_pup %d end_pup %d pup_cnt %d\n",
760 			 if_id, start_pup, end_pup, pup_cnt));
761 		if (result_type == RESULT_PER_BIT) {
762 			if (bit_num == ALL_BITS_PER_PUP) {
763 				start_reg = pup_cnt * BUS_WIDTH_IN_BITS;
764 				end_reg = (pup_cnt + 1) * BUS_WIDTH_IN_BITS - 1;
765 			} else {
766 				start_reg =
767 					pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
768 				end_reg = pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
769 			}
770 		} else {
771 			start_reg = pup_cnt;
772 			end_reg = pup_cnt;
773 		}
774 
775 		interface_train_res =
776 			ddr3_tip_get_buf_ptr(dev_num, search, result_type,
777 					     if_id);
778 		DEBUG_TRAINING_IP_ENGINE(
779 			DEBUG_LEVEL_TRACE,
780 			("start_reg %d end_reg %d interface %p\n",
781 			 start_reg, end_reg, interface_train_res));
782 		if (interface_train_res == NULL) {
783 			DEBUG_TRAINING_IP_ENGINE(
784 				DEBUG_LEVEL_ERROR,
785 				("interface_train_res is NULL\n"));
786 			return MV_FAIL;
787 		}
788 
789 		for (reg_offset = start_reg; reg_offset <= end_reg;
790 		     reg_offset++) {
791 			if (operation == TRAINING_LOAD_OPERATION_UNLOAD) {
792 				if (is_read_from_db == 0) {
793 					CHECK_STATUS(ddr3_tip_if_read
794 						     (dev_num,
795 						      ACCESS_TYPE_UNICAST,
796 						      if_id,
797 						      reg_addr[reg_offset],
798 						      read_data,
799 						      MASK_ALL_BITS));
800 					if (is_check_result_validity == 1) {
801 						if ((read_data[if_id] &
802 						     TIP_ENG_LOCK) == 0) {
803 							interface_train_res
804 								[reg_offset] =
805 								TIP_ENG_LOCK +
806 								TIP_TX_DLL_RANGE_MAX;
807 						} else {
808 							interface_train_res
809 								[reg_offset] =
810 								read_data
811 								[if_id] +
812 								cons_tap;
813 						}
814 					} else {
815 						interface_train_res[reg_offset]
816 							= read_data[if_id] +
817 							cons_tap;
818 					}
819 					DEBUG_TRAINING_IP_ENGINE
820 						(DEBUG_LEVEL_TRACE,
821 						 ("reg_offset %d value 0x%x addr %p\n",
822 						  reg_offset,
823 						  interface_train_res
824 						  [reg_offset],
825 						  &interface_train_res
826 						  [reg_offset]));
827 				} else {
828 					*load_res =
829 						&interface_train_res[start_reg];
830 					DEBUG_TRAINING_IP_ENGINE
831 						(DEBUG_LEVEL_TRACE,
832 						 ("*load_res %p\n", *load_res));
833 				}
834 			} else {
835 				DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
836 							 ("not supported\n"));
837 			}
838 		}
839 	}
840 
841 	return MV_OK;
842 }
843 
844 /*
845  * Load all pattern to memory using ODPG
846  */
ddr3_tip_load_all_pattern_to_mem(u32 dev_num)847 int ddr3_tip_load_all_pattern_to_mem(u32 dev_num)
848 {
849 	u32 pattern = 0, if_id;
850 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
851 
852 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
853 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
854 		training_result[training_stage][if_id] = TEST_SUCCESS;
855 	}
856 
857 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
858 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
859 		/* enable single cs */
860 		CHECK_STATUS(ddr3_tip_if_write
861 			     (dev_num, ACCESS_TYPE_UNICAST, if_id,
862 			      DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
863 	}
864 
865 	for (pattern = 0; pattern < PATTERN_LAST; pattern++)
866 		ddr3_tip_load_pattern_to_mem(dev_num, pattern);
867 
868 	return MV_OK;
869 }
870 
871 /*
872  * Load specific pattern to memory using ODPG
873  */
ddr3_tip_load_pattern_to_mem(u32 dev_num,enum hws_pattern pattern)874 int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern)
875 {
876 	u32 reg_data, if_id;
877 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
878 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
879 
880 	/* load pattern to memory */
881 	/*
882 	 * Write Tx mode, CS0, phases, Tx burst size, delay between burst,
883 	 * rx pattern phases
884 	 */
885 	reg_data =
886 		0x1 | (pattern_table[pattern].num_of_phases_tx << 5) |
887 		(pattern_table[pattern].tx_burst_size << 11) |
888 		(pattern_table[pattern].delay_between_bursts << 15) |
889 		(pattern_table[pattern].num_of_phases_rx << 21) | (0x1 << 25) |
890 		(effective_cs << 26);
891 	CHECK_STATUS(ddr3_tip_if_write
892 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
893 		      ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS));
894 	/* ODPG Write enable from BIST */
895 	CHECK_STATUS(ddr3_tip_if_write
896 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
897 		      ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)),
898 		      0xc000003));
899 	/* disable error injection */
900 	CHECK_STATUS(ddr3_tip_if_write
901 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
902 		      ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1));
903 	/* load pattern to ODPG */
904 	ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
905 				      PARAM_NOT_CARE, pattern,
906 				      pattern_table[pattern].start_addr);
907 
908 	if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
909 		for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
910 			VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
911 
912 			CHECK_STATUS(ddr3_tip_if_write
913 				     (dev_num, ACCESS_TYPE_UNICAST, if_id,
914 				      SDRAM_ODT_CTRL_HIGH_REG,
915 				      0x3, 0xf));
916 		}
917 
918 		mv_ddr_odpg_enable();
919 	} else {
920 		CHECK_STATUS(ddr3_tip_if_write
921 			     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
922 			      ODPG_DATA_CTRL_REG, (u32)(0x1 << 31),
923 			      (u32)(0x1 << 31)));
924 	}
925 	mdelay(1);
926 
927 	if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK)
928 		return MV_FAIL;
929 
930 	/* Disable ODPG and stop write to memory */
931 	CHECK_STATUS(ddr3_tip_if_write
932 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
933 		      ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30)));
934 
935 	/* return to default */
936 	CHECK_STATUS(ddr3_tip_if_write
937 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
938 		      ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS));
939 
940 	if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
941 		/* Disable odt0 for CS0 training - need to adjust for multy CS */
942 		CHECK_STATUS(ddr3_tip_if_write
943 			     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
944 			      SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf));
945 	}
946 	/* temporary added */
947 	mdelay(1);
948 
949 	return MV_OK;
950 }
951 
952 /*
953  * Training search routine
954  */
ddr3_tip_ip_training_wrapper_int(u32 dev_num,enum hws_access_type access_type,u32 if_id,enum hws_access_type pup_access_type,u32 pup_num,u32 bit_num,enum hws_training_result result_type,enum hws_control_element control_element,enum hws_search_dir search_dir,enum hws_dir direction,u32 interface_mask,u32 init_value_l2h,u32 init_value_h2l,u32 num_iter,enum hws_pattern pattern,enum hws_edge_compare edge_comp,enum hws_ddr_cs train_cs_type,u32 cs_num,enum hws_training_ip_stat * train_status)955 int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
956 				     enum hws_access_type access_type,
957 				     u32 if_id,
958 				     enum hws_access_type pup_access_type,
959 				     u32 pup_num, u32 bit_num,
960 				     enum hws_training_result result_type,
961 				     enum hws_control_element control_element,
962 				     enum hws_search_dir search_dir,
963 				     enum hws_dir direction,
964 				     u32 interface_mask, u32 init_value_l2h,
965 				     u32 init_value_h2l, u32 num_iter,
966 				     enum hws_pattern pattern,
967 				     enum hws_edge_compare edge_comp,
968 				     enum hws_ddr_cs train_cs_type, u32 cs_num,
969 				     enum hws_training_ip_stat *train_status)
970 {
971 	u32 interface_num = 0, start_if, end_if, init_value_used;
972 	enum hws_search_dir search_dir_id, start_search, end_search;
973 	enum hws_edge_compare edge_comp_used;
974 	u8 cons_tap = 0;
975 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
976 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
977 
978 	if (train_status == NULL) {
979 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
980 					 ("train_status is NULL\n"));
981 		return MV_FAIL;
982 	}
983 
984 	if ((train_cs_type > CS_NON_SINGLE) ||
985 	    (edge_comp >= EDGE_PFP) ||
986 	    (pattern >= PATTERN_LAST) ||
987 	    (direction > OPER_WRITE_AND_READ) ||
988 	    (search_dir > HWS_HIGH2LOW) ||
989 	    (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) ||
990 	    (result_type > RESULT_PER_BYTE) ||
991 	    (pup_num >= octets_per_if_num) ||
992 	    (pup_access_type > ACCESS_TYPE_MULTICAST) ||
993 	    (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) {
994 		DEBUG_TRAINING_IP_ENGINE(
995 			DEBUG_LEVEL_ERROR,
996 			("wrong parameter train_cs_type %d edge_comp %d pattern %d direction %d search_dir %d control_element %d result_type %d pup_num %d pup_access_type %d if_id %d access_type %d\n",
997 			 train_cs_type, edge_comp, pattern, direction,
998 			 search_dir, control_element, result_type, pup_num,
999 			 pup_access_type, if_id, access_type));
1000 		return MV_FAIL;
1001 	}
1002 
1003 	if (edge_comp == EDGE_FPF) {
1004 		start_search = HWS_LOW2HIGH;
1005 		end_search = HWS_HIGH2LOW;
1006 		edge_comp_used = EDGE_FP;
1007 	} else {
1008 		start_search = search_dir;
1009 		end_search = search_dir;
1010 		edge_comp_used = edge_comp;
1011 	}
1012 
1013 	for (search_dir_id = start_search; search_dir_id <= end_search;
1014 	     search_dir_id++) {
1015 		init_value_used = (search_dir_id == HWS_LOW2HIGH) ?
1016 			init_value_l2h : init_value_h2l;
1017 		DEBUG_TRAINING_IP_ENGINE(
1018 			DEBUG_LEVEL_TRACE,
1019 			("dev_num %d, access_type %d, if_id %d, pup_access_type %d,pup_num %d, result_type %d, control_element %d search_dir_id %d, direction %d, interface_mask %d,init_value_used %d, num_iter %d, pattern %d, edge_comp_used %d, train_cs_type %d, cs_num %d\n",
1020 			 dev_num, access_type, if_id, pup_access_type, pup_num,
1021 			 result_type, control_element, search_dir_id,
1022 			 direction, interface_mask, init_value_used, num_iter,
1023 			 pattern, edge_comp_used, train_cs_type, cs_num));
1024 
1025 		ddr3_tip_ip_training(dev_num, access_type, if_id,
1026 				     pup_access_type, pup_num, result_type,
1027 				     control_element, search_dir_id, direction,
1028 				     interface_mask, init_value_used, num_iter,
1029 				     pattern, edge_comp_used, train_cs_type,
1030 				     cs_num, train_status);
1031 		if (access_type == ACCESS_TYPE_MULTICAST) {
1032 			start_if = 0;
1033 			end_if = MAX_INTERFACE_NUM - 1;
1034 		} else {
1035 			start_if = if_id;
1036 			end_if = if_id;
1037 		}
1038 
1039 		for (interface_num = start_if; interface_num <= end_if;
1040 		     interface_num++) {
1041 			VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num);
1042 			cs_num = 0;
1043 			CHECK_STATUS(ddr3_tip_read_training_result
1044 				     (dev_num, interface_num, pup_access_type,
1045 				      pup_num, bit_num, search_dir_id,
1046 				      direction, result_type,
1047 				      TRAINING_LOAD_OPERATION_UNLOAD,
1048 				      train_cs_type, NULL, 0, cons_tap,
1049 				      0));
1050 		}
1051 	}
1052 
1053 	return MV_OK;
1054 }
1055 /*
1056  * Training search & read result routine
1057  * This function implements the search algorithm
1058  * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l
1059  * this function handles rx and tx search cases
1060  * in case of rx it only triggers the search (l2h and h2l)
1061  * in case of tx there are 3 optional algorithm phases:
1062  * phase 1:
1063  * it first triggers the search and handles the results as following (phase 1):
1064  * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases:
1065  *  1.	BIT_LOW_UI	0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31
1066  *  2.	BIT_HIGH_UI	32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32
1067  *  3.	BIT_SPLIT_IN	VW_L <= 31 & VW_H >= 32
1068  *  4.	BIT_SPLIT_OUT*	VW_H < 32 &  VW_L > 32
1069  * note: the VW units is adll taps
1070  * phase 2:
1071  * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h
1072  * because only this case is not locked by the search engine in the first search trigger (phase 1).
1073  * phase 3:
1074  * each subphy is categorized according to its bits definition.
1075  * the sub-phy cases are as follows:
1076  *  1.BYTE_NOT_DEFINED			the byte has not yet been categorized
1077  *  2.BYTE_HOMOGENEOUS_LOW		0 =< VW =< 31
1078  *  3.BYTE_HOMOGENEOUS_HIGH		32 =< VW =< 63
1079  *  4.BYTE_HOMOGENEOUS_SPLIT_IN		VW_L <= 31 & VW_H >= 32
1080  *					or the center of all bits in the byte  =< 31
1081  *  5.BYTE_HOMOGENEOUS_SPLIT_OUT	VW_H < 32 &  VW_L > 32
1082  *  6.BYTE_SPLIT_OUT_MIX		at least one bits is in split out state and one bit is in other
1083  *					or the center of all bits in the byte => 32
1084  * after the two phases above a center valid window for each subphy is calculated accordingly:
1085  * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy.
1086  * now decisions are made in each subphy as following:
1087  * all subphys which are homogeneous remains as is
1088  * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32
1089  *	mark this subphy as homogeneous split in.
1090  * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following
1091  * all bits which are BIT_LOW_UI will be added with 64 adll,
1092  * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs
1093  */
ddr3_tip_ip_training_wrapper(u32 dev_num,enum hws_access_type access_type,u32 if_id,enum hws_access_type pup_access_type,u32 pup_num,enum hws_training_result result_type,enum hws_control_element control_element,enum hws_search_dir search_dir,enum hws_dir direction,u32 interface_mask,u32 init_value_l2h,u32 init_value_h2l,u32 num_iter,enum hws_pattern pattern,enum hws_edge_compare edge_comp,enum hws_ddr_cs train_cs_type,u32 cs_num,enum hws_training_ip_stat * train_status)1094 int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type,
1095 	u32 if_id,
1096 	enum hws_access_type pup_access_type,
1097 	u32 pup_num,
1098 	enum hws_training_result result_type,
1099 	enum hws_control_element control_element,
1100 	enum hws_search_dir search_dir,
1101 	enum hws_dir direction, u32 interface_mask,
1102 	u32 init_value_l2h, u32 init_value_h2l,
1103 	u32 num_iter, enum hws_pattern pattern,
1104 	enum hws_edge_compare edge_comp,
1105 	enum hws_ddr_cs train_cs_type, u32 cs_num,
1106 	enum hws_training_ip_stat *train_status)
1107 {
1108 	u8 e1, e2;
1109 	u32 bit_id, start_if, end_if, bit_end = 0;
1110 	u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 };
1111 	u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
1112 	u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0;
1113 	u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0};
1114 	u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
1115 	u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
1116 	u8 center_subphy_adll_window[MAX_BUS_NUM];
1117 	u8 min_center_subphy_adll[MAX_BUS_NUM];
1118 	u8 max_center_subphy_adll[MAX_BUS_NUM];
1119 	u32 *l2h_if_train_res = NULL;
1120 	u32 *h2l_if_train_res = NULL;
1121 	enum hws_search_dir search_dir_id;
1122 	int status;
1123 	u32 bit_lock_result;
1124 
1125 	u8 sybphy_id;
1126 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
1127 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1128 
1129 	if (pup_num >= octets_per_if_num) {
1130 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1131 			("pup_num %d not valid\n", pup_num));
1132 	}
1133 
1134 	if (if_id >= MAX_INTERFACE_NUM) {
1135 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1136 			("if_id %d not valid\n", if_id));
1137 	}
1138 
1139 	status = ddr3_tip_ip_training_wrapper_int
1140 		(dev_num, access_type, if_id, pup_access_type, pup_num,
1141 		ALL_BITS_PER_PUP, result_type, control_element,
1142 		search_dir, direction, interface_mask, init_value_l2h,
1143 		init_value_h2l, num_iter, pattern, edge_comp,
1144 		train_cs_type, cs_num, train_status);
1145 
1146 	if (MV_OK != status)
1147 		return status;
1148 
1149 	if (access_type == ACCESS_TYPE_MULTICAST) {
1150 		start_if = 0;
1151 		end_if = MAX_INTERFACE_NUM - 1;
1152 	} else {
1153 		start_if = if_id;
1154 		end_if = if_id;
1155 	}
1156 
1157 	for (if_id = start_if; if_id <= end_if; if_id++) {
1158 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
1159 		/* zero the database */
1160 		bit_bit_mask_active = 0;	/* clean the flag for level2 search */
1161 		memset(bit_state, 0, sizeof(bit_state));
1162 		/* phase 1 */
1163 		for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
1164 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
1165 			if (result_type == RESULT_PER_BIT)
1166 				bit_end = BUS_WIDTH_IN_BITS;
1167 			else
1168 				bit_end = 0;
1169 
1170 			/* zero the data base */
1171 			bit_bit_mask[sybphy_id] = 0;
1172 			byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED;
1173 			for (bit_id = 0; bit_id < bit_end; bit_id++) {
1174 				h2l_adll_value[sybphy_id][bit_id] = 64;
1175 				l2h_adll_value[sybphy_id][bit_id] = 0;
1176 				for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW;
1177 					search_dir_id++) {
1178 					status = ddr3_tip_read_training_result
1179 						(dev_num, if_id,
1180 							ACCESS_TYPE_UNICAST, sybphy_id, bit_id,
1181 							search_dir_id, direction, result_type,
1182 							TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
1183 							&result[search_dir_id], 1, 0, 0);
1184 
1185 					if (MV_OK != status)
1186 						return status;
1187 				}
1188 
1189 				e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1);
1190 				e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1);
1191 				DEBUG_TRAINING_IP_ENGINE
1192 					(DEBUG_LEVEL_INFO,
1193 					 ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n",
1194 					 if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1,
1195 					 result[HWS_HIGH2LOW][0], e2));
1196 				bit_lock_result =
1197 					(GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) &&
1198 						GET_LOCK_RESULT(result[HWS_HIGH2LOW][0]));
1199 
1200 				if (bit_lock_result) {
1201 					/* in case of read operation set the byte status as homogeneous low */
1202 					if (direction == OPER_READ) {
1203 						byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW;
1204 					} else if ((e2 - e1) > 32) { /* oper_write */
1205 						/* split out */
1206 						bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
1207 							BIT_SPLIT_OUT;
1208 						byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT;
1209 						/* mark problem bits */
1210 						bit_bit_mask[sybphy_id] |= (1 << bit_id);
1211 						bit_bit_mask_active = 1;
1212 						DEBUG_TRAINING_IP_ENGINE
1213 							(DEBUG_LEVEL_TRACE,
1214 							 ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n",
1215 							 if_id, sybphy_id, bit_id));
1216 					} else {
1217 						/* low ui */
1218 						if (e1 <= 31 && e2 <= 31) {
1219 							bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
1220 								BIT_LOW_UI;
1221 							byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW;
1222 							l2h_adll_value[sybphy_id][bit_id] = e1;
1223 							h2l_adll_value[sybphy_id][bit_id] = e2;
1224 							DEBUG_TRAINING_IP_ENGINE
1225 								(DEBUG_LEVEL_TRACE,
1226 								 ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n",
1227 								 if_id, sybphy_id, bit_id));
1228 						}
1229 							/* high ui */
1230 						if (e1 >= 32 && e2 >= 32) {
1231 							bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
1232 								BIT_HIGH_UI;
1233 							byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH;
1234 							l2h_adll_value[sybphy_id][bit_id] = e1;
1235 							h2l_adll_value[sybphy_id][bit_id] = e2;
1236 							DEBUG_TRAINING_IP_ENGINE
1237 								(DEBUG_LEVEL_TRACE,
1238 								 ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n",
1239 								 if_id, sybphy_id, bit_id));
1240 						}
1241 						/* split in */
1242 						if (e1 <= 31 && e2 >= 32) {
1243 							bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
1244 								BIT_SPLIT_IN;
1245 							byte_status[if_id][sybphy_id] |=
1246 								BYTE_HOMOGENEOUS_SPLIT_IN;
1247 							l2h_adll_value[sybphy_id][bit_id] = e1;
1248 							h2l_adll_value[sybphy_id][bit_id] = e2;
1249 							DEBUG_TRAINING_IP_ENGINE
1250 								(DEBUG_LEVEL_TRACE,
1251 								 ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n",
1252 								 if_id, sybphy_id, bit_id));
1253 						}
1254 					}
1255 				} else {
1256 					DEBUG_TRAINING_IP_ENGINE
1257 						(DEBUG_LEVEL_INFO,
1258 						 ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)"
1259 						 "h2l 0x%x (e2 0x%x): bit cannot be categorized\n",
1260 						 if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1,
1261 						 result[HWS_HIGH2LOW][0], e2));
1262 					/* mark the byte as not defined */
1263 					byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED;
1264 					break; /* continue to next pup - no reason to analyze this byte */
1265 				}
1266 			} /* for all bits */
1267 		} /* for all PUPs */
1268 
1269 		/* phase 2 will occur only in write operation */
1270 		if (bit_bit_mask_active != 0) {
1271 			l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id);
1272 			h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id);
1273 			/* search from middle to end */
1274 			ddr3_tip_ip_training
1275 				(dev_num, ACCESS_TYPE_UNICAST,
1276 				 if_id, ACCESS_TYPE_MULTICAST,
1277 				 PARAM_NOT_CARE, result_type,
1278 				 control_element, HWS_LOW2HIGH,
1279 				 direction, interface_mask,
1280 				 num_iter / 2, num_iter / 2,
1281 				 pattern, EDGE_FP, train_cs_type,
1282 				 cs_num, train_status);
1283 
1284 			for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
1285 				VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
1286 				if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) {
1287 					if (bit_bit_mask[sybphy_id] == 0)
1288 						continue; /* this byte bits have no split out state */
1289 
1290 					for (bit_id = 0; bit_id < bit_end; bit_id++) {
1291 						if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0)
1292 							continue; /* this bit is non split goto next bit */
1293 
1294 						/* enter the result to the data base */
1295 						status = ddr3_tip_read_training_result
1296 							(dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id,
1297 							 bit_id, HWS_LOW2HIGH, direction, result_type,
1298 							 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
1299 							 &l2h_if_train_res, 0, 0, 1);
1300 
1301 						if (MV_OK != status)
1302 							return status;
1303 
1304 						l2h_adll_value[sybphy_id][bit_id] =
1305 							l2h_if_train_res[sybphy_id *
1306 							BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK;
1307 					}
1308 				}
1309 			}
1310 			/* Search from middle to start */
1311 			ddr3_tip_ip_training
1312 				(dev_num, ACCESS_TYPE_UNICAST,
1313 				 if_id, ACCESS_TYPE_MULTICAST,
1314 				 PARAM_NOT_CARE, result_type,
1315 				 control_element, HWS_HIGH2LOW,
1316 				 direction, interface_mask,
1317 				 num_iter / 2, num_iter / 2,
1318 				 pattern, EDGE_FP, train_cs_type,
1319 				 cs_num, train_status);
1320 
1321 			for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
1322 				VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
1323 				if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) {
1324 					if (bit_bit_mask[sybphy_id] == 0)
1325 						continue;
1326 
1327 					for (bit_id = 0; bit_id < bit_end; bit_id++) {
1328 						if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0)
1329 							continue;
1330 
1331 						status = ddr3_tip_read_training_result
1332 							(dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id,
1333 							 bit_id, HWS_HIGH2LOW, direction, result_type,
1334 							 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
1335 							 &h2l_if_train_res, 0, cons_tap, 1);
1336 
1337 						if (MV_OK != status)
1338 							return status;
1339 
1340 						h2l_adll_value[sybphy_id][bit_id] =
1341 							h2l_if_train_res[sybphy_id *
1342 							BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK;
1343 					}
1344 				}
1345 			}
1346 		} /* end if bit_bit_mask_active */
1347 		/*
1348 			* phase 3 will occur only in write operation
1349 			* find the maximum and the minimum center of each subphy
1350 			*/
1351 		for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
1352 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
1353 
1354 			if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) {
1355 				/* clear the arrays and parameters */
1356 				center_subphy_adll_window[sybphy_id] = 0;
1357 				max_center_subphy_adll[sybphy_id] = 0;
1358 				min_center_subphy_adll[sybphy_id] = 64;
1359 				/* find the max and min center adll value in the current subphy */
1360 				for (bit_id = 0; bit_id < bit_end; bit_id++) {
1361 					/* debug print all the bit edges after alignment */
1362 					DEBUG_TRAINING_IP_ENGINE
1363 						(DEBUG_LEVEL_TRACE,
1364 						 ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n",
1365 						 if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id],
1366 						 h2l_adll_value[sybphy_id][bit_id]));
1367 
1368 					if (((l2h_adll_value[sybphy_id][bit_id] +
1369 					      h2l_adll_value[sybphy_id][bit_id]) / 2) >
1370 					      max_center_subphy_adll[sybphy_id])
1371 						max_center_subphy_adll[sybphy_id] =
1372 						(l2h_adll_value[sybphy_id][bit_id] +
1373 						 h2l_adll_value[sybphy_id][bit_id]) / 2;
1374 					if (((l2h_adll_value[sybphy_id][bit_id] +
1375 					      h2l_adll_value[sybphy_id][bit_id]) / 2) <
1376 					      min_center_subphy_adll[sybphy_id])
1377 						min_center_subphy_adll[sybphy_id] =
1378 						(l2h_adll_value[sybphy_id][bit_id] +
1379 						 h2l_adll_value[sybphy_id][bit_id]) / 2;
1380 				}
1381 
1382 				/* calculate the center of the current subphy */
1383 				center_subphy_adll_window[sybphy_id] =
1384 					max_center_subphy_adll[sybphy_id] -
1385 					min_center_subphy_adll[sybphy_id];
1386 				DEBUG_TRAINING_IP_ENGINE
1387 					(DEBUG_LEVEL_TRACE,
1388 					 ("if_id %d sybphy_id %d min center %d max center %d center %d\n",
1389 					 if_id, sybphy_id, min_center_subphy_adll[sybphy_id],
1390 					 max_center_subphy_adll[sybphy_id],
1391 					 center_subphy_adll_window[sybphy_id]));
1392 			}
1393 		}
1394 		/*
1395 			* check byte state and fix bits state if needed
1396 			* in case the level 1 and 2 above subphy results are
1397 			* homogeneous continue to the next subphy
1398 			*/
1399 		for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
1400 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
1401 			if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) ||
1402 			    (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) ||
1403 			    (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) ||
1404 			    (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) ||
1405 			    (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED))
1406 			continue;
1407 
1408 			/*
1409 			 * in case all of the bits in the current subphy are
1410 			 * less than 32 which will find alignment in the subphy bits
1411 			 * mark this subphy as homogeneous split in
1412 			*/
1413 			if (center_subphy_adll_window[sybphy_id] <= 31)
1414 				byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN;
1415 
1416 			/*
1417 				* in case the current byte is split_out and the center is bigger than 31
1418 				* the byte can be aligned. in this case add 64 to the the low ui bits aligning it
1419 				* to the other ui bits
1420 				*/
1421 			if (center_subphy_adll_window[sybphy_id] >= 32) {
1422 				byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX;
1423 
1424 				DEBUG_TRAINING_IP_ENGINE
1425 					(DEBUG_LEVEL_TRACE,
1426 					 ("if_id %d sybphy_id %d byte state 0x%x\n",
1427 					 if_id, sybphy_id, byte_status[if_id][sybphy_id]));
1428 				for (bit_id = 0; bit_id < bit_end; bit_id++) {
1429 					if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) {
1430 						l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64;
1431 						h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64;
1432 					}
1433 					DEBUG_TRAINING_IP_ENGINE
1434 						(DEBUG_LEVEL_TRACE,
1435 						 ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n",
1436 						 if_id, sybphy_id, bit_id));
1437 				}
1438 			}
1439 		}
1440 	} /* for all interfaces */
1441 
1442 	return MV_OK;
1443 }
1444 
mv_ddr_tip_sub_phy_byte_status_get(u32 if_id,u32 subphy_id)1445 u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id)
1446 {
1447 	return byte_status[if_id][subphy_id];
1448 }
1449 
mv_ddr_tip_sub_phy_byte_status_set(u32 if_id,u32 subphy_id,u8 byte_status_data)1450 void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data)
1451 {
1452 	byte_status[if_id][subphy_id] = byte_status_data;
1453 }
1454 
1455 /*
1456  * Load phy values
1457  */
ddr3_tip_load_phy_values(int b_load)1458 int ddr3_tip_load_phy_values(int b_load)
1459 {
1460 	u32 bus_cnt = 0, if_id, dev_num = 0;
1461 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
1462 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1463 
1464 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
1465 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
1466 		for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
1467 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
1468 			if (b_load == 1) {
1469 				CHECK_STATUS(ddr3_tip_bus_read
1470 					     (dev_num, if_id,
1471 					      ACCESS_TYPE_UNICAST, bus_cnt,
1472 					      DDR_PHY_DATA,
1473 					      CTX_PHY_REG(effective_cs),
1474 					      &phy_reg_bk[if_id][bus_cnt]
1475 					      [0]));
1476 				CHECK_STATUS(ddr3_tip_bus_read
1477 					     (dev_num, if_id,
1478 					      ACCESS_TYPE_UNICAST, bus_cnt,
1479 					      DDR_PHY_DATA,
1480 					      RL_PHY_REG(effective_cs),
1481 					      &phy_reg_bk[if_id][bus_cnt]
1482 					      [1]));
1483 				CHECK_STATUS(ddr3_tip_bus_read
1484 					     (dev_num, if_id,
1485 					      ACCESS_TYPE_UNICAST, bus_cnt,
1486 					      DDR_PHY_DATA,
1487 					      CRX_PHY_REG(effective_cs),
1488 					      &phy_reg_bk[if_id][bus_cnt]
1489 					      [2]));
1490 			} else {
1491 				CHECK_STATUS(ddr3_tip_bus_write
1492 					     (dev_num, ACCESS_TYPE_UNICAST,
1493 					      if_id, ACCESS_TYPE_UNICAST,
1494 					      bus_cnt, DDR_PHY_DATA,
1495 					      CTX_PHY_REG(effective_cs),
1496 					      phy_reg_bk[if_id][bus_cnt]
1497 					      [0]));
1498 				CHECK_STATUS(ddr3_tip_bus_write
1499 					     (dev_num, ACCESS_TYPE_UNICAST,
1500 					      if_id, ACCESS_TYPE_UNICAST,
1501 					      bus_cnt, DDR_PHY_DATA,
1502 					      RL_PHY_REG(effective_cs),
1503 					      phy_reg_bk[if_id][bus_cnt]
1504 					      [1]));
1505 				CHECK_STATUS(ddr3_tip_bus_write
1506 					     (dev_num, ACCESS_TYPE_UNICAST,
1507 					      if_id, ACCESS_TYPE_UNICAST,
1508 					      bus_cnt, DDR_PHY_DATA,
1509 					      CRX_PHY_REG(effective_cs),
1510 					      phy_reg_bk[if_id][bus_cnt]
1511 					      [2]));
1512 			}
1513 		}
1514 	}
1515 
1516 	return MV_OK;
1517 }
1518 
ddr3_tip_training_ip_test(u32 dev_num,enum hws_training_result result_type,enum hws_search_dir search_dir,enum hws_dir direction,enum hws_edge_compare edge,u32 init_val1,u32 init_val2,u32 num_of_iterations,u32 start_pattern,u32 end_pattern)1519 int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
1520 			      enum hws_search_dir search_dir,
1521 			      enum hws_dir direction,
1522 			      enum hws_edge_compare edge,
1523 			      u32 init_val1, u32 init_val2,
1524 			      u32 num_of_iterations,
1525 			      u32 start_pattern, u32 end_pattern)
1526 {
1527 	u32 pattern, if_id, pup_id;
1528 	enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
1529 	u32 *res = NULL;
1530 	u32 search_state = 0;
1531 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
1532 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1533 
1534 	ddr3_tip_load_phy_values(1);
1535 
1536 	for (pattern = start_pattern; pattern <= end_pattern; pattern++) {
1537 		for (search_state = 0; search_state < HWS_SEARCH_DIR_LIMIT;
1538 		     search_state++) {
1539 			ddr3_tip_ip_training_wrapper(dev_num,
1540 						     ACCESS_TYPE_MULTICAST, 0,
1541 						     ACCESS_TYPE_MULTICAST, 0,
1542 						     result_type,
1543 						     HWS_CONTROL_ELEMENT_ADLL,
1544 						     search_dir, direction,
1545 						     0xfff, init_val1,
1546 						     init_val2,
1547 						     num_of_iterations, pattern,
1548 						     edge, CS_SINGLE,
1549 						     PARAM_NOT_CARE,
1550 						     train_status);
1551 
1552 			for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
1553 			     if_id++) {
1554 				VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
1555 				for (pup_id = 0; pup_id <
1556 					     octets_per_if_num;
1557 				     pup_id++) {
1558 					VALIDATE_BUS_ACTIVE(tm->bus_act_mask,
1559 							pup_id);
1560 					CHECK_STATUS
1561 						(ddr3_tip_read_training_result
1562 						 (dev_num, if_id,
1563 						  ACCESS_TYPE_UNICAST, pup_id,
1564 						  ALL_BITS_PER_PUP,
1565 						  search_state,
1566 						  direction, result_type,
1567 						  TRAINING_LOAD_OPERATION_UNLOAD,
1568 						  CS_SINGLE, &res, 1, 0,
1569 						  0));
1570 					if (result_type == RESULT_PER_BYTE) {
1571 						DEBUG_TRAINING_IP_ENGINE
1572 							(DEBUG_LEVEL_INFO,
1573 							 ("search_state %d if_id %d pup_id %d 0x%x\n",
1574 							  search_state, if_id,
1575 							  pup_id, res[0]));
1576 					} else {
1577 						DEBUG_TRAINING_IP_ENGINE
1578 							(DEBUG_LEVEL_INFO,
1579 							 ("search_state %d if_id %d pup_id %d 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
1580 							  search_state, if_id,
1581 							  pup_id, res[0],
1582 							  res[1], res[2],
1583 							  res[3], res[4],
1584 							  res[5], res[6],
1585 							  res[7]));
1586 					}
1587 				}
1588 			}	/* interface */
1589 		}		/* search */
1590 	}			/* pattern */
1591 
1592 	ddr3_tip_load_phy_values(0);
1593 
1594 	return MV_OK;
1595 }
1596 
mv_ddr_pattern_start_addr_set(struct pattern_info * pattern_tbl,enum hws_pattern pattern,u32 addr)1597 int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr)
1598 {
1599 	pattern_tbl[pattern].start_addr = addr;
1600 
1601 	return 0;
1602 }
1603 
ddr3_tip_get_pattern_table()1604 struct pattern_info *ddr3_tip_get_pattern_table()
1605 {
1606 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1607 
1608 	if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask))
1609 		return pattern_table_64;
1610 	else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0)
1611 		return pattern_table_32;
1612 	else
1613 		return pattern_table_16;
1614 }
1615 
ddr3_tip_get_mask_results_dq_reg()1616 u16 *ddr3_tip_get_mask_results_dq_reg()
1617 {
1618 #if MAX_BUS_NUM == 5
1619 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1620 
1621 	if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1622 		return mask_results_dq_reg_map_pup3_ecc;
1623 	else
1624 #endif
1625 		return mask_results_dq_reg_map;
1626 }
1627 
ddr3_tip_get_mask_results_pup_reg_map()1628 u16 *ddr3_tip_get_mask_results_pup_reg_map()
1629 {
1630 #if MAX_BUS_NUM == 5
1631 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1632 
1633 	if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1634 		return mask_results_pup_reg_map_pup3_ecc;
1635 	else
1636 #endif
1637 		return mask_results_pup_reg_map;
1638 }
1639 
1640 /* load expected dm pattern to odpg */
1641 #define LOW_NIBBLE_BYTE_MASK	0xf
1642 #define HIGH_NIBBLE_BYTE_MASK	0xf0
mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type,enum hws_pattern pattern,enum dm_direction dm_dir)1643 int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern,
1644 				   enum dm_direction dm_dir)
1645 {
1646 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
1647 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1648 	u32 pattern_len = 0;
1649 	u32 data_low, data_high;
1650 	u8 dm_data;
1651 
1652 	for (pattern_len = 0;
1653 	     pattern_len < pattern_table[pattern].pattern_len;
1654 	     pattern_len++) {
1655 		if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) {
1656 			data_low = pattern_table_get_word(0, pattern, (u8)pattern_len);
1657 			data_high = data_low;
1658 		} else {
1659 			data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2));
1660 			data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1));
1661 		}
1662 
1663 		/* odpg mbus dm definition is opposite to ddr4 protocol */
1664 		if (dm_dir == DM_DIR_INVERSE)
1665 			dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK));
1666 		else
1667 			dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK);
1668 
1669 		ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS);
1670 		ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS);
1671 		ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG,
1672 				  pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS),
1673 				  MASK_ALL_BITS);
1674 	}
1675 
1676 	return MV_OK;
1677 }
1678