1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright (C) Marvell International Ltd. and its affiliates
4  */
5 
6 #include "ddr_ml_wrapper.h"
7 
8 #include "ddr3_training_ip_flow.h"
9 #include "mv_ddr_topology.h"
10 #include "mv_ddr_training_db.h"
11 #include "ddr3_training_ip_db.h"
12 
13 /* Device attributes structures */
14 enum mv_ddr_dev_attribute ddr_dev_attributes[MV_ATTR_LAST];
15 int ddr_dev_attr_init_done = 0;
16 
17 static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index);
18 static inline u32 pattern_table_get_sso_word(u8 sso, u8 index);
19 static inline u32 pattern_table_get_vref_word(u8 index);
20 static inline u32 pattern_table_get_vref_word16(u8 index);
21 static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index);
22 static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index);
23 static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index);
24 static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index);
25 static inline u32 pattern_table_get_isi_word(u8 index);
26 static inline u32 pattern_table_get_isi_word16(u8 index);
27 
28 /* List of allowed frequency listed in order of enum mv_ddr_freq */
29 static unsigned int freq_val[MV_DDR_FREQ_LAST] = {
30 	0,			/*MV_DDR_FREQ_LOW_FREQ */
31 	400,			/*MV_DDR_FREQ_400, */
32 	533,			/*MV_DDR_FREQ_533, */
33 	666,			/*MV_DDR_FREQ_667, */
34 	800,			/*MV_DDR_FREQ_800, */
35 	933,			/*MV_DDR_FREQ_933, */
36 	1066,			/*MV_DDR_FREQ_1066, */
37 	311,			/*MV_DDR_FREQ_311, */
38 	333,			/*MV_DDR_FREQ_333, */
39 	467,			/*MV_DDR_FREQ_467, */
40 	850,			/*MV_DDR_FREQ_850, */
41 	600,			/*MV_DDR_FREQ_600 */
42 	300,			/*MV_DDR_FREQ_300 */
43 	900,			/*MV_DDR_FREQ_900 */
44 	360,			/*MV_DDR_FREQ_360 */
45 	1000			/*MV_DDR_FREQ_1000 */
46 };
47 
48 unsigned int *mv_ddr_freq_tbl_get(void)
49 {
50 	return &freq_val[0];
51 }
52 
53 u32 mv_ddr_freq_get(enum mv_ddr_freq freq)
54 {
55 	return freq_val[freq];
56 }
57 
58 /* cas latency values per frequency for each speed bin index */
59 static struct mv_ddr_cl_val_per_freq cl_table[] = {
60 	/*
61 	 * 400M   667M     933M   311M     467M  600M    360
62 	 * 100M    533M    800M    1066M   333M    850M      900
63 	 * 1000 (the order is 100, 400, 533 etc.)
64 	 */
65 	/* DDR3-800D */
66 	{ {6, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
67 	/* DDR3-800E */
68 	{ {6, 6, 0, 0, 0, 0, 0, 6, 6, 0, 0, 0, 6, 0, 6, 0} },
69 	/* DDR3-1066E */
70 	{ {6, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 0, 5, 0, 5, 0} },
71 	/* DDR3-1066F */
72 	{ {6, 6, 7, 0, 0, 0, 0, 6, 6, 7, 0, 0, 6, 0, 6, 0} },
73 	/* DDR3-1066G */
74 	{ {6, 6, 8, 0, 0, 0, 0, 6, 6, 8, 0, 0, 6, 0, 6, 0} },
75 	/* DDR3-1333F* */
76 	{ {6, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
77 	/* DDR3-1333G */
78 	{ {6, 5, 7, 8, 0, 0, 0, 5, 5, 7, 0, 8, 5, 0, 5, 0} },
79 	/* DDR3-1333H */
80 	{ {6, 6, 8, 9, 0, 0, 0, 6, 6, 8, 0, 9, 6, 0, 6, 0} },
81 	/* DDR3-1333J* */
82 	{ {6, 6, 8, 10, 0, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6,  0}
83 	 /* DDR3-1600G* */},
84 	{ {6, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
85 	/* DDR3-1600H */
86 	{ {6, 5, 6, 8, 9, 0, 0, 5, 5, 6, 0, 8, 5, 0, 5, 0} },
87 	/* DDR3-1600J */
88 	{ {6, 5, 7, 9, 10, 0, 0, 5, 5, 7, 0, 9, 5, 0, 5, 0} },
89 	/* DDR3-1600K */
90 	{ {6, 6, 8, 10, 11, 0, 0, 6, 6, 8, 0, 10, 6, 0, 6, 0 } },
91 	/* DDR3-1866J* */
92 	{ {6, 5, 6, 8, 9, 11, 0, 5, 5, 6, 11, 8, 5, 0, 5, 0} },
93 	/* DDR3-1866K */
94 	{ {6, 5, 7, 8, 10, 11, 0, 5, 5, 7, 11, 8, 5, 11, 5, 11} },
95 	/* DDR3-1866L */
96 	{ {6, 6, 7, 9, 11, 12, 0, 6, 6, 7, 12, 9, 6, 12, 6, 12} },
97 	/* DDR3-1866M* */
98 	{ {6, 6, 8, 10, 11, 13, 0, 6, 6, 8, 13, 10, 6, 13, 6, 13} },
99 	/* DDR3-2133K* */
100 	{ {6, 5, 6, 7, 9, 10, 11, 5, 5, 6, 10, 7, 5, 11, 5, 11} },
101 	/* DDR3-2133L */
102 	{ {6, 5, 6, 8, 9, 11, 12, 5, 5, 6, 11, 8, 5, 12, 5, 12} },
103 	/* DDR3-2133M */
104 	{ {6, 5, 7, 9, 10, 12, 13, 5, 5, 7, 12, 9, 5, 13, 5, 13} },
105 	/* DDR3-2133N* */
106 	{ {6, 6, 7, 9, 11, 13, 14, 6, 6, 7, 13, 9, 6, 14,  6, 14} },
107 	/* DDR3-1333H-ext */
108 	{ {6, 6, 7, 9, 0, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
109 	/* DDR3-1600K-ext */
110 	{ {6, 6, 7, 9, 11, 0, 0, 6, 6, 7, 0, 9, 6, 0, 6, 0} },
111 	/* DDR3-1866M-ext */
112 	{ {6, 6, 7, 9, 11, 13, 0, 6, 6, 7, 13, 9, 6, 13, 6, 13} },
113 };
114 
115 u32 mv_ddr_cl_val_get(u32 index, u32 freq)
116 {
117 	return cl_table[index].cl_val[freq];
118 }
119 
120 /* cas write latency values per frequency for each speed bin index */
121 static struct mv_ddr_cl_val_per_freq cwl_table[] = {
122 	/*
123 	 * 400M   667M     933M   311M     467M  600M    360
124 	 * 100M    533M    800M    1066M   333M    850M      900
125 	 * (the order is 100, 400, 533 etc.)
126 	 */
127 	/* DDR3-800D  */
128 	{ {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
129 	/* DDR3-800E  */
130 	{ {5, 5, 0, 0, 0, 0, 0, 5, 5, 0, 0, 0, 5, 0, 5, 0} },
131 	/* DDR3-1066E  */
132 	{ {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
133 	/* DDR3-1066F  */
134 	{ {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
135 	/* DDR3-1066G  */
136 	{ {5, 5, 6, 0, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
137 	/* DDR3-1333F*  */
138 	{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
139 	/* DDR3-1333G  */
140 	{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
141 	/* DDR3-1333H  */
142 	{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
143 	/* DDR3-1333J*  */
144 	{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
145 	/* DDR3-1600G*  */
146 	{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
147 	/* DDR3-1600H  */
148 	{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
149 	/* DDR3-1600J  */
150 	{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
151 	/* DDR3-1600K  */
152 	{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
153 	/* DDR3-1866J*  */
154 	{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
155 	/* DDR3-1866K  */
156 	{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 0, 5, 0} },
157 	/* DDR3-1866L  */
158 	{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
159 	/* DDR3-1866M*   */
160 	{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
161 	/* DDR3-2133K*  */
162 	{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
163 	/* DDR3-2133L  */
164 	{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
165 	/* DDR3-2133M  */
166 	{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
167 	/* DDR3-2133N*  */
168 	{ {5, 5, 6, 7, 8, 9, 10, 5, 5, 6, 9, 7, 5, 9, 5, 10} },
169 	/* DDR3-1333H-ext  */
170 	{ {5, 5, 6, 7, 0, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
171 	/* DDR3-1600K-ext  */
172 	{ {5, 5, 6, 7, 8, 0, 0, 5, 5, 6, 0, 7, 5, 0, 5, 0} },
173 	/* DDR3-1866M-ext  */
174 	{ {5, 5, 6, 7, 8, 9, 0, 5, 5, 6, 9, 7, 5, 9, 5, 9} },
175 };
176 
177 u32 mv_ddr_cwl_val_get(u32 index, u32 freq)
178 {
179 	return cwl_table[index].cl_val[freq];
180 }
181 
182 u8 twr_mask_table[] = {
183 	10,
184 	10,
185 	10,
186 	10,
187 	10,
188 	1,			/* 5 */
189 	2,			/* 6 */
190 	3,			/* 7 */
191 	4,			/* 8 */
192 	10,
193 	5,			/* 10 */
194 	10,
195 	6,			/* 12 */
196 	10,
197 	7,			/* 14 */
198 	10,
199 	0			/* 16 */
200 };
201 
202 u8 cl_mask_table[] = {
203 	0,
204 	0,
205 	0,
206 	0,
207 	0,
208 	0x2,
209 	0x4,
210 	0x6,
211 	0x8,
212 	0xa,
213 	0xc,
214 	0xe,
215 	0x1,
216 	0x3,
217 	0x5,
218 	0x5
219 };
220 
221 u8 cwl_mask_table[] = {
222 	0,
223 	0,
224 	0,
225 	0,
226 	0,
227 	0,
228 	0x1,
229 	0x2,
230 	0x3,
231 	0x4,
232 	0x5,
233 	0x6,
234 	0x7,
235 	0x8,
236 	0x9,
237 	0x9
238 };
239 
240 /* RFC values (in ns) */
241 static unsigned int rfc_table[] = {
242 	90,	/* 512M */
243 	110,	/* 1G */
244 	160,	/* 2G */
245 	260,	/* 4G */
246 	350,	/* 8G */
247 	0,	/* TODO: placeholder for 16-Mbit dev width */
248 	0,	/* TODO: placeholder for 32-Mbit dev width */
249 	0,	/* TODO: placeholder for 12-Mbit dev width */
250 	0	/* TODO: placeholder for 24-Mbit dev width */
251 };
252 
253 u32 mv_ddr_rfc_get(u32 mem)
254 {
255 	return rfc_table[mem];
256 }
257 
258 u32 speed_bin_table_t_rc[] = {
259 	50000,
260 	52500,
261 	48750,
262 	50625,
263 	52500,
264 	46500,
265 	48000,
266 	49500,
267 	51000,
268 	45000,
269 	46250,
270 	47500,
271 	48750,
272 	44700,
273 	45770,
274 	46840,
275 	47910,
276 	43285,
277 	44220,
278 	45155,
279 	46090
280 };
281 
282 u32 speed_bin_table_t_rcd_t_rp[] = {
283 	12500,
284 	15000,
285 	11250,
286 	13125,
287 	15000,
288 	10500,
289 	12000,
290 	13500,
291 	15000,
292 	10000,
293 	11250,
294 	12500,
295 	13750,
296 	10700,
297 	11770,
298 	12840,
299 	13910,
300 	10285,
301 	11220,
302 	12155,
303 	13090,
304 };
305 
306 enum {
307 	PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR = 0,
308 	PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM
309 };
310 
311 static u8 pattern_killer_pattern_table_map[KILLER_PATTERN_LENGTH * 2][2] = {
312 	/*Aggressor / Victim */
313 	{1, 0},
314 	{0, 0},
315 	{1, 0},
316 	{1, 1},
317 	{0, 1},
318 	{0, 1},
319 	{1, 0},
320 	{0, 1},
321 	{1, 0},
322 	{0, 1},
323 	{1, 0},
324 	{1, 0},
325 	{0, 1},
326 	{1, 0},
327 	{0, 1},
328 	{0, 0},
329 	{1, 1},
330 	{0, 0},
331 	{1, 1},
332 	{0, 0},
333 	{1, 1},
334 	{0, 0},
335 	{1, 1},
336 	{1, 0},
337 	{0, 0},
338 	{1, 1},
339 	{0, 0},
340 	{1, 1},
341 	{0, 0},
342 	{0, 0},
343 	{0, 0},
344 	{0, 1},
345 	{0, 1},
346 	{1, 1},
347 	{0, 0},
348 	{0, 0},
349 	{1, 1},
350 	{1, 1},
351 	{0, 0},
352 	{1, 1},
353 	{0, 0},
354 	{1, 1},
355 	{1, 1},
356 	{0, 0},
357 	{0, 0},
358 	{1, 1},
359 	{0, 0},
360 	{1, 1},
361 	{0, 1},
362 	{0, 0},
363 	{0, 1},
364 	{0, 1},
365 	{0, 0},
366 	{1, 1},
367 	{1, 1},
368 	{1, 0},
369 	{1, 0},
370 	{1, 1},
371 	{1, 1},
372 	{1, 1},
373 	{1, 1},
374 	{1, 1},
375 	{1, 1},
376 	{1, 1}
377 };
378 
379 static u8 pattern_vref_pattern_table_map[] = {
380 	/* 1 means 0xffffffff, 0 is 0x0 */
381 	0xb8,
382 	0x52,
383 	0x55,
384 	0x8a,
385 	0x33,
386 	0xa6,
387 	0x6d,
388 	0xfe
389 };
390 
391 static struct mv_ddr_page_element page_tbl[] = {
392 	/* 8-bit, 16-bit page size */
393 	{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 512M */
394 	{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 1G */
395 	{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 2G */
396 	{MV_DDR_PAGE_SIZE_1K, MV_DDR_PAGE_SIZE_2K}, /* 4G */
397 	{MV_DDR_PAGE_SIZE_2K, MV_DDR_PAGE_SIZE_2K}, /* 8G */
398 	{0, 0}, /* TODO: placeholder for 16-Mbit die capacity */
399 	{0, 0}, /* TODO: placeholder for 32-Mbit die capacity */
400 	{0, 0}, /* TODO: placeholder for 12-Mbit die capacity */
401 	{0, 0}  /* TODO: placeholder for 24-Mbit die capacity */
402 };
403 
404 u32 mv_ddr_page_size_get(enum mv_ddr_dev_width bus_width, enum mv_ddr_die_capacity mem_size)
405 {
406 	if (bus_width == MV_DDR_DEV_WIDTH_8BIT)
407 		return page_tbl[mem_size].page_size_8bit;
408 	else
409 		return page_tbl[mem_size].page_size_16bit;
410 }
411 
412 /* Return speed Bin value for selected index and t* element */
413 unsigned int mv_ddr_speed_bin_timing_get(enum mv_ddr_speed_bin index, enum mv_ddr_speed_bin_timing element)
414 {
415 	u32 result = 0;
416 
417 	switch (element) {
418 	case SPEED_BIN_TRCD:
419 	case SPEED_BIN_TRP:
420 		result = speed_bin_table_t_rcd_t_rp[index];
421 		break;
422 	case SPEED_BIN_TRAS:
423 		if (index < SPEED_BIN_DDR_1066G)
424 			result = 37500;
425 		else if (index < SPEED_BIN_DDR_1333J)
426 			result = 36000;
427 		else if (index < SPEED_BIN_DDR_1600K)
428 			result = 35000;
429 		else if (index < SPEED_BIN_DDR_1866M)
430 			result = 34000;
431 		else
432 			result = 33000;
433 		break;
434 	case SPEED_BIN_TRC:
435 		result = speed_bin_table_t_rc[index];
436 		break;
437 	case SPEED_BIN_TRRD1K:
438 		if (index <= SPEED_BIN_DDR_800E)
439 			result = 10000;
440 		else if (index <= SPEED_BIN_DDR_1066G)
441 			result = 7500;
442 		else if (index <= SPEED_BIN_DDR_1600K)
443 			result = 6000;
444 		else
445 			result = 5000;
446 		break;
447 	case SPEED_BIN_TRRD2K:
448 		if (index <= SPEED_BIN_DDR_1066G)
449 			result = 10000;
450 		else if (index <= SPEED_BIN_DDR_1600K)
451 			result = 7500;
452 		else
453 			result = 6000;
454 		break;
455 	case SPEED_BIN_TPD:
456 		if (index < SPEED_BIN_DDR_800E)
457 			result = 7500;
458 		else if (index < SPEED_BIN_DDR_1333J)
459 			result = 5625;
460 		else
461 			result = 5000;
462 		break;
463 	case SPEED_BIN_TFAW1K:
464 		if (index <= SPEED_BIN_DDR_800E)
465 			result = 40000;
466 		else if (index <= SPEED_BIN_DDR_1066G)
467 			result = 37500;
468 		else if (index <= SPEED_BIN_DDR_1600K)
469 			result = 30000;
470 		else if (index <= SPEED_BIN_DDR_1866M)
471 			result = 27000;
472 		else
473 			result = 25000;
474 		break;
475 	case SPEED_BIN_TFAW2K:
476 		if (index <= SPEED_BIN_DDR_1066G)
477 			result = 50000;
478 		else if (index <= SPEED_BIN_DDR_1333J)
479 			result = 45000;
480 		else if (index <= SPEED_BIN_DDR_1600K)
481 			result = 40000;
482 		else
483 			result = 35000;
484 		break;
485 	case SPEED_BIN_TWTR:
486 		result = 7500;
487 		break;
488 	case SPEED_BIN_TRTP:
489 		result = 7500;
490 		break;
491 	case SPEED_BIN_TWR:
492 		result = 15000;
493 		break;
494 	case SPEED_BIN_TMOD:
495 		result = 15000;
496 		break;
497 	case SPEED_BIN_TXPDLL:
498 		result = 24000;
499 		break;
500 	case SPEED_BIN_TXSDLL:
501 		result = 512;
502 		break;
503 	default:
504 		break;
505 	}
506 
507 	return result;
508 }
509 
510 static inline u32 pattern_table_get_killer_word(u8 dqs, u8 index)
511 {
512 	u8 i, byte = 0;
513 	u8 role;
514 
515 	for (i = 0; i < 8; i++) {
516 		role = (i == dqs) ?
517 			(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
518 			(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
519 		byte |= pattern_killer_pattern_table_map[index][role] << i;
520 	}
521 
522 	return byte | (byte << 8) | (byte << 16) | (byte << 24);
523 }
524 
525 static inline u32 pattern_table_get_killer_word16(u8 dqs, u8 index)
526 {
527 	u8 i, byte0 = 0, byte1 = 0;
528 	u8 role;
529 
530 	for (i = 0; i < 8; i++) {
531 		role = (i == dqs) ?
532 			(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_AGGRESSOR) :
533 			(PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM);
534 		byte0 |= pattern_killer_pattern_table_map[index * 2][role] << i;
535 		byte1 |= pattern_killer_pattern_table_map[index * 2 + 1][role] << i;
536 	}
537 
538 	return byte0 | (byte0 << 8) | (byte1 << 16) | (byte1 << 24);
539 }
540 
541 static inline u32 pattern_table_get_sso_word(u8 sso, u8 index)
542 {
543 	u8 step = sso + 1;
544 
545 	if (0 == ((index / step) & 1))
546 		return 0x0;
547 	else
548 		return 0xffffffff;
549 }
550 
551 static inline u32 pattern_table_get_sso_full_xtalk_word(u8 bit, u8 index)
552 {
553 	u8 byte = (1 << bit);
554 
555 	if ((index & 1) == 1)
556 		byte = ~byte;
557 
558 	return byte | (byte << 8) | (byte << 16) | (byte << 24);
559 
560 }
561 
562 static inline u32 pattern_table_get_sso_xtalk_free_word(u8 bit, u8 index)
563 {
564 	u8 byte = (1 << bit);
565 
566 	if ((index & 1) == 1)
567 		byte = 0;
568 
569 	return byte | (byte << 8) | (byte << 16) | (byte << 24);
570 }
571 
572 static inline u32 pattern_table_get_isi_word(u8 index)
573 {
574 	u8 i0 = index % 32;
575 	u8 i1 = index % 8;
576 	u32 word;
577 
578 	if (i0 > 15)
579 		word = ((i1 == 5) | (i1 == 7)) ? 0xffffffff : 0x0;
580 	else
581 		word = (i1 == 6) ? 0xffffffff : 0x0;
582 
583 	word = ((i0 % 16) > 7) ? ~word : word;
584 
585 	return word;
586 }
587 
588 static inline u32 pattern_table_get_sso_full_xtalk_word16(u8 bit, u8 index)
589 {
590 	u8 byte = (1 << bit);
591 
592 	if ((index & 1) == 1)
593 		byte = ~byte;
594 
595 	return byte | (byte << 8) | ((~byte) << 16) | ((~byte) << 24);
596 }
597 
598 static inline u32 pattern_table_get_sso_xtalk_free_word16(u8 bit, u8 index)
599 {
600 	u8 byte = (1 << bit);
601 
602 	if ((index & 1) == 0)
603 		return (byte << 16) | (byte << 24);
604 	else
605 		return byte | (byte << 8);
606 }
607 
608 static inline u32 pattern_table_get_isi_word16(u8 index)
609 {
610 	u8 i0 = index % 16;
611 	u8 i1 = index % 4;
612 	u32 word;
613 
614 	if (i0 > 7)
615 		word = (i1 > 1) ? 0x0000ffff : 0x0;
616 	else
617 		word = (i1 == 3) ? 0xffff0000 : 0x0;
618 
619 	word = ((i0 % 8) > 3) ? ~word : word;
620 
621 	return word;
622 }
623 
624 static inline u32 pattern_table_get_vref_word(u8 index)
625 {
626 	if (0 == ((pattern_vref_pattern_table_map[index / 8] >>
627 		   (index % 8)) & 1))
628 		return 0x0;
629 	else
630 		return 0xffffffff;
631 }
632 
633 static inline u32 pattern_table_get_vref_word16(u8 index)
634 {
635 	if (0 == pattern_killer_pattern_table_map
636 	    [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
637 	    0 == pattern_killer_pattern_table_map
638 	    [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
639 		return 0x00000000;
640 	else if (1 == pattern_killer_pattern_table_map
641 		 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
642 		 0 == pattern_killer_pattern_table_map
643 		 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
644 		return 0xffff0000;
645 	else if (0 == pattern_killer_pattern_table_map
646 		 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2] &&
647 		 1 == pattern_killer_pattern_table_map
648 		 [PATTERN_KILLER_PATTERN_TABLE_MAP_ROLE_VICTIM][index * 2 + 1])
649 		return 0x0000ffff;
650 	else
651 		return 0xffffffff;
652 }
653 
654 static inline u32 pattern_table_get_static_pbs_word(u8 index)
655 {
656 	u16 temp;
657 
658 	temp = ((0x00ff << (index / 3)) & 0xff00) >> 8;
659 
660 	return temp | (temp << 8) | (temp << 16) | (temp << 24);
661 }
662 
663 u32 pattern_table_get_word(u32 dev_num, enum hws_pattern type, u8 index)
664 {
665 	u32 pattern = 0;
666 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
667 
668 	if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0) {
669 		/* 32/64-bit patterns */
670 		switch (type) {
671 		case PATTERN_PBS1:
672 		case PATTERN_PBS2:
673 			if (index == 0 || index == 2 || index == 5 ||
674 			    index == 7)
675 				pattern = PATTERN_55;
676 			else
677 				pattern = PATTERN_AA;
678 			break;
679 		case PATTERN_PBS3:
680 			if (0 == (index & 1))
681 				pattern = PATTERN_55;
682 			else
683 				pattern = PATTERN_AA;
684 			break;
685 		case PATTERN_RL:
686 			if (index < 6)
687 				pattern = PATTERN_00;
688 			else
689 				pattern = PATTERN_80;
690 			break;
691 		case PATTERN_STATIC_PBS:
692 			pattern = pattern_table_get_static_pbs_word(index);
693 			break;
694 		case PATTERN_KILLER_DQ0:
695 		case PATTERN_KILLER_DQ1:
696 		case PATTERN_KILLER_DQ2:
697 		case PATTERN_KILLER_DQ3:
698 		case PATTERN_KILLER_DQ4:
699 		case PATTERN_KILLER_DQ5:
700 		case PATTERN_KILLER_DQ6:
701 		case PATTERN_KILLER_DQ7:
702 			pattern = pattern_table_get_killer_word(
703 				(u8)(type - PATTERN_KILLER_DQ0), index);
704 			break;
705 		case PATTERN_RL2:
706 			if (index < 6)
707 				pattern = PATTERN_00;
708 			else
709 				pattern = PATTERN_01;
710 			break;
711 		case PATTERN_TEST:
712 			if (index > 1 && index < 6)
713 				pattern = PATTERN_00;
714 			else
715 				pattern = PATTERN_FF;
716 			break;
717 		case PATTERN_FULL_SSO0:
718 		case PATTERN_FULL_SSO1:
719 		case PATTERN_FULL_SSO2:
720 		case PATTERN_FULL_SSO3:
721 			pattern = pattern_table_get_sso_word(
722 				(u8)(type - PATTERN_FULL_SSO0), index);
723 			break;
724 		case PATTERN_VREF:
725 			pattern = pattern_table_get_vref_word(index);
726 			break;
727 		case PATTERN_SSO_FULL_XTALK_DQ0:
728 		case PATTERN_SSO_FULL_XTALK_DQ1:
729 		case PATTERN_SSO_FULL_XTALK_DQ2:
730 		case PATTERN_SSO_FULL_XTALK_DQ3:
731 		case PATTERN_SSO_FULL_XTALK_DQ4:
732 		case PATTERN_SSO_FULL_XTALK_DQ5:
733 		case PATTERN_SSO_FULL_XTALK_DQ6:
734 		case PATTERN_SSO_FULL_XTALK_DQ7:
735 			pattern = pattern_table_get_sso_full_xtalk_word(
736 				(u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index);
737 			break;
738 		case PATTERN_SSO_XTALK_FREE_DQ0:
739 		case PATTERN_SSO_XTALK_FREE_DQ1:
740 		case PATTERN_SSO_XTALK_FREE_DQ2:
741 		case PATTERN_SSO_XTALK_FREE_DQ3:
742 		case PATTERN_SSO_XTALK_FREE_DQ4:
743 		case PATTERN_SSO_XTALK_FREE_DQ5:
744 		case PATTERN_SSO_XTALK_FREE_DQ6:
745 		case PATTERN_SSO_XTALK_FREE_DQ7:
746 			pattern = pattern_table_get_sso_xtalk_free_word(
747 				(u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index);
748 			break;
749 		case PATTERN_ISI_XTALK_FREE:
750 			pattern = pattern_table_get_isi_word(index);
751 			break;
752 		default:
753 			printf("error: %s: unsupported pattern type [%d] found\n",
754 			       __func__, (int)type);
755 			pattern = 0;
756 			break;
757 		}
758 	} else {
759 		/* 16bit patterns */
760 		switch (type) {
761 		case PATTERN_PBS1:
762 		case PATTERN_PBS2:
763 		case PATTERN_PBS3:
764 			pattern = PATTERN_55AA;
765 			break;
766 		case PATTERN_RL:
767 			if (index < 3)
768 				pattern = PATTERN_00;
769 			else
770 				pattern = PATTERN_80;
771 			break;
772 		case PATTERN_STATIC_PBS:
773 			pattern = PATTERN_00FF;
774 			break;
775 		case PATTERN_KILLER_DQ0:
776 		case PATTERN_KILLER_DQ1:
777 		case PATTERN_KILLER_DQ2:
778 		case PATTERN_KILLER_DQ3:
779 		case PATTERN_KILLER_DQ4:
780 		case PATTERN_KILLER_DQ5:
781 		case PATTERN_KILLER_DQ6:
782 		case PATTERN_KILLER_DQ7:
783 			pattern = pattern_table_get_killer_word16(
784 				(u8)(type - PATTERN_KILLER_DQ0), index);
785 			break;
786 		case PATTERN_RL2:
787 			if (index < 3)
788 				pattern = PATTERN_00;
789 			else
790 				pattern = PATTERN_01;
791 			break;
792 		case PATTERN_TEST:
793 			if ((index == 0) || (index == 3))
794 				pattern = 0x00000000;
795 			else
796 				pattern = 0xFFFFFFFF;
797 			break;
798 		case PATTERN_FULL_SSO0:
799 			pattern = 0x0000ffff;
800 			break;
801 		case PATTERN_FULL_SSO1:
802 		case PATTERN_FULL_SSO2:
803 		case PATTERN_FULL_SSO3:
804 			pattern = pattern_table_get_sso_word(
805 				(u8)(type - PATTERN_FULL_SSO1), index);
806 			break;
807 		case PATTERN_VREF:
808 			pattern = pattern_table_get_vref_word16(index);
809 			break;
810 		case PATTERN_SSO_FULL_XTALK_DQ0:
811 		case PATTERN_SSO_FULL_XTALK_DQ1:
812 		case PATTERN_SSO_FULL_XTALK_DQ2:
813 		case PATTERN_SSO_FULL_XTALK_DQ3:
814 		case PATTERN_SSO_FULL_XTALK_DQ4:
815 		case PATTERN_SSO_FULL_XTALK_DQ5:
816 		case PATTERN_SSO_FULL_XTALK_DQ6:
817 		case PATTERN_SSO_FULL_XTALK_DQ7:
818 			pattern = pattern_table_get_sso_full_xtalk_word16(
819 				(u8)(type - PATTERN_SSO_FULL_XTALK_DQ0), index);
820 			break;
821 		case PATTERN_SSO_XTALK_FREE_DQ0:
822 		case PATTERN_SSO_XTALK_FREE_DQ1:
823 		case PATTERN_SSO_XTALK_FREE_DQ2:
824 		case PATTERN_SSO_XTALK_FREE_DQ3:
825 		case PATTERN_SSO_XTALK_FREE_DQ4:
826 		case PATTERN_SSO_XTALK_FREE_DQ5:
827 		case PATTERN_SSO_XTALK_FREE_DQ6:
828 		case PATTERN_SSO_XTALK_FREE_DQ7:
829 			pattern = pattern_table_get_sso_xtalk_free_word16(
830 				(u8)(type - PATTERN_SSO_XTALK_FREE_DQ0), index);
831 			break;
832 		case PATTERN_ISI_XTALK_FREE:
833 			pattern = pattern_table_get_isi_word16(index);
834 			break;
835 		default:
836 			printf("error: %s: unsupported pattern type [%d] found\n",
837 			       __func__, (int)type);
838 			pattern = 0;
839 			break;
840 		}
841 	}
842 
843 	return pattern;
844 }
845 
846 /* Device attribute functions */
847 void ddr3_tip_dev_attr_init(u32 dev_num)
848 {
849 	u32 attr_id;
850 
851 	for (attr_id = 0; attr_id < MV_ATTR_LAST; attr_id++)
852 		ddr_dev_attributes[attr_id] = 0xFF;
853 
854 	ddr_dev_attr_init_done = 1;
855 }
856 
857 u32 ddr3_tip_dev_attr_get(u32 dev_num, enum mv_ddr_dev_attribute attr_id)
858 {
859 	if (ddr_dev_attr_init_done == 0)
860 		ddr3_tip_dev_attr_init(dev_num);
861 
862 	return ddr_dev_attributes[attr_id];
863 }
864 
865 void ddr3_tip_dev_attr_set(u32 dev_num, enum mv_ddr_dev_attribute attr_id, u32 value)
866 {
867 	if (ddr_dev_attr_init_done == 0)
868 		ddr3_tip_dev_attr_init(dev_num);
869 
870 	ddr_dev_attributes[attr_id] = value;
871 }
872