183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0
2f1df9364SStefan Roese /*
3f1df9364SStefan Roese  * Copyright (C) Marvell International Ltd. and its affiliates
4f1df9364SStefan Roese  */
5f1df9364SStefan Roese 
6f1df9364SStefan Roese #include "ddr3_init.h"
7*ebb1a593SChris Packham #include "mv_ddr_regs.h"
8*ebb1a593SChris Packham #include "ddr_training_ip_db.h"
9f1df9364SStefan Roese 
10f1df9364SStefan Roese #define PATTERN_1	0x55555555
11f1df9364SStefan Roese #define PATTERN_2	0xaaaaaaaa
12f1df9364SStefan Roese 
13f1df9364SStefan Roese #define VALIDATE_TRAINING_LIMIT(e1, e2)			\
14f1df9364SStefan Roese 	((((e2) - (e1) + 1) > 33) && ((e1) < 67))
15f1df9364SStefan Roese 
16f1df9364SStefan Roese u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
17f1df9364SStefan Roese 
18f1df9364SStefan Roese u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS *
19f1df9364SStefan Roese 		 HWS_SEARCH_DIR_LIMIT];
202b4ffbf6SChris Packham u8 byte_status[MAX_INTERFACE_NUM][MAX_BUS_NUM];	/* holds the bit status in the byte in wrapper function*/
21f1df9364SStefan Roese 
22f1df9364SStefan Roese u16 mask_results_dq_reg_map[] = {
23f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
24f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
25f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
26f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
27f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
28f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
29f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
30f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
31f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
32f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
33f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
34f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
35f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
36f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
37f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
38f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG,
39f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
40f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
41f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
42f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
432b4ffbf6SChris Packham #if MAX_BUS_NUM == 9
442b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_5_BIT_0_REG, RESULT_CONTROL_PUP_5_BIT_1_REG,
452b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_5_BIT_2_REG, RESULT_CONTROL_PUP_5_BIT_3_REG,
462b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_5_BIT_4_REG, RESULT_CONTROL_PUP_5_BIT_5_REG,
472b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_5_BIT_6_REG, RESULT_CONTROL_PUP_5_BIT_7_REG,
482b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_6_BIT_0_REG, RESULT_CONTROL_PUP_6_BIT_1_REG,
492b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_6_BIT_2_REG, RESULT_CONTROL_PUP_6_BIT_3_REG,
502b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_6_BIT_4_REG, RESULT_CONTROL_PUP_6_BIT_5_REG,
512b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_6_BIT_6_REG, RESULT_CONTROL_PUP_6_BIT_7_REG,
522b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_7_BIT_0_REG, RESULT_CONTROL_PUP_7_BIT_1_REG,
532b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_7_BIT_2_REG, RESULT_CONTROL_PUP_7_BIT_3_REG,
542b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_7_BIT_4_REG, RESULT_CONTROL_PUP_7_BIT_5_REG,
552b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_7_BIT_6_REG, RESULT_CONTROL_PUP_7_BIT_7_REG,
562b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_8_BIT_0_REG, RESULT_CONTROL_PUP_8_BIT_1_REG,
572b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_8_BIT_2_REG, RESULT_CONTROL_PUP_8_BIT_3_REG,
582b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_8_BIT_4_REG, RESULT_CONTROL_PUP_8_BIT_5_REG,
592b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_8_BIT_6_REG, RESULT_CONTROL_PUP_8_BIT_7_REG,
602b4ffbf6SChris Packham #endif
612b4ffbf6SChris Packham 	0xffff
62f1df9364SStefan Roese };
63f1df9364SStefan Roese 
64f1df9364SStefan Roese u16 mask_results_pup_reg_map[] = {
65f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
66f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG,
672b4ffbf6SChris Packham 	RESULT_CONTROL_BYTE_PUP_4_REG,
682b4ffbf6SChris Packham #if MAX_BUS_NUM == 9
692b4ffbf6SChris Packham 	RESULT_CONTROL_BYTE_PUP_5_REG, RESULT_CONTROL_BYTE_PUP_6_REG,
702b4ffbf6SChris Packham 	RESULT_CONTROL_BYTE_PUP_7_REG, RESULT_CONTROL_BYTE_PUP_8_REG,
712b4ffbf6SChris Packham #endif
722b4ffbf6SChris Packham 	0xffff
73f1df9364SStefan Roese };
74f1df9364SStefan Roese 
752b4ffbf6SChris Packham #if MAX_BUS_NUM == 5
76f1df9364SStefan Roese u16 mask_results_dq_reg_map_pup3_ecc[] = {
77f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
78f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
79f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
80f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
81f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
82f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
83f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
84f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
85f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
86f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
87f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
88f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
89f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
90f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
91f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
92f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
932b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
942b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
952b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
962b4ffbf6SChris Packham 	RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG
97f1df9364SStefan Roese };
982b4ffbf6SChris Packham #endif
99f1df9364SStefan Roese 
1002b4ffbf6SChris Packham #if MAX_BUS_NUM == 5
101f1df9364SStefan Roese u16 mask_results_pup_reg_map_pup3_ecc[] = {
102f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
103f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG,
104f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_4_REG
105f1df9364SStefan Roese };
1062b4ffbf6SChris Packham #endif
1072b4ffbf6SChris Packham 
1082b4ffbf6SChris Packham struct pattern_info pattern_table_64[] = {
1092b4ffbf6SChris Packham 	/*
1102b4ffbf6SChris Packham 	 * num_of_phases_tx, tx_burst_size;
1112b4ffbf6SChris Packham 	 * delay_between_bursts, num_of_phases_rx,
1122b4ffbf6SChris Packham 	 * start_addr, pattern_len
1132b4ffbf6SChris Packham 	 */
1142b4ffbf6SChris Packham 	{0x7, 0x7, 2, 0x7, 0x00000, 8},		/* PATTERN_PBS1 */
1152b4ffbf6SChris Packham 	{0x7, 0x7, 2, 0x7, 0x00080, 8},		/* PATTERN_PBS2 */
1162b4ffbf6SChris Packham 	{0x7, 0x7, 2, 0x7, 0x00100, 8},		/* PATTERN_PBS3 */
1172b4ffbf6SChris Packham 	{0x7, 0x7, 2, 0x7, 0x00030, 8},		/* PATTERN_TEST */
1182b4ffbf6SChris Packham 	{0x7, 0x7, 2, 0x7, 0x00100, 8},		/* PATTERN_RL */
1192b4ffbf6SChris Packham 	{0x7, 0x7, 2, 0x7, 0x00100, 8},		/* PATTERN_RL2 */
1202b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x00680, 32},	/* PATTERN_STATIC_PBS */
1212b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x00a80, 32},	/* PATTERN_KILLER_DQ0 */
1222b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x01280, 32},	/* PATTERN_KILLER_DQ1 */
1232b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x01a80, 32},	/* PATTERN_KILLER_DQ2 */
1242b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x02280, 32},	/* PATTERN_KILLER_DQ3 */
1252b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x02a80, 32},	/* PATTERN_KILLER_DQ4 */
1262b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x03280, 32},	/* PATTERN_KILLER_DQ5 */
1272b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x03a80, 32},	/* PATTERN_KILLER_DQ6 */
1282b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x04280, 32},	/* PATTERN_KILLER_DQ7 */
1292b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x00e80, 32},	/* PATTERN_KILLER_DQ0_64 */
1302b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x01680, 32},	/* PATTERN_KILLER_DQ1_64 */
1312b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x01e80, 32},	/* PATTERN_KILLER_DQ2_64 */
1322b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x02680, 32},	/* PATTERN_KILLER_DQ3_64 */
1332b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x02e80, 32},	/* PATTERN_KILLER_DQ4_64 */
1342b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x03680, 32},	/* PATTERN_KILLER_DQ5_64 */
1352b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x03e80, 32},	/* PATTERN_KILLER_DQ6_64 */
1362b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x04680, 32},	/* PATTERN_KILLER_DQ7_64 */
1372b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x04a80, 32},	/* PATTERN_KILLER_DQ0_INV */
1382b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x05280, 32},	/* PATTERN_KILLER_DQ1_INV */
1392b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x05a80, 32},	/* PATTERN_KILLER_DQ2_INV */
1402b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x06280, 32},	/* PATTERN_KILLER_DQ3_INV */
1412b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x06a80, 32},	/* PATTERN_KILLER_DQ4_INV */
1422b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x07280, 32},	/* PATTERN_KILLER_DQ5_INV */
1432b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x07a80, 32},	/* PATTERN_KILLER_DQ6_INV */
1442b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x08280, 32},	/* PATTERN_KILLER_DQ7_INV */
1452b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x04e80, 32},	/* PATTERN_KILLER_DQ0_INV_64 */
1462b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x05680, 32},	/* PATTERN_KILLER_DQ1_INV_64 */
1472b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x05e80, 32},	/* PATTERN_KILLER_DQ2_INV_64 */
1482b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x06680, 32},	/* PATTERN_KILLER_DQ3_INV_64 */
1492b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x06e80, 32},	/* PATTERN_KILLER_DQ4_INV_64 */
1502b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x07680, 32},	/* PATTERN_KILLER_DQ5_INV_64 */
1512b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x07e80, 32},	/* PATTERN_KILLER_DQ6_INV_64 */
1522b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x08680, 32},	/* PATTERN_KILLER_DQ7_INV_64 */
1532b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x08a80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ0 */
1542b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x09280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
1552b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x09a80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ2 */
1562b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0a280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ3 */
1572b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0aa80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ4 */
1582b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0b280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ5 */
1592b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0ba80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ6 */
1602b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0c280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ7 */
1612b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x08e80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ0_64 */
1622b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x09680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ1_64 */
1632b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x09e80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ2_64 */
1642b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0a680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ3_64 */
1652b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0ae80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ4_64 */
1662b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0b680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ5_64 */
1672b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0be80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ6_64 */
1682b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0c680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ7_64 */
1692b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0ca80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ0 */
1702b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0d280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ1 */
1712b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0da80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ2 */
1722b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0e280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ3 */
1732b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0ea80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ4 */
1742b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0f280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ5 */
1752b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0fa80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ6 */
1762b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x10280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ7 */
1772b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0ce80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ0_64 */
1782b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0d680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ1_64 */
1792b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0de80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ2_64 */
1802b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0e680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ3_64 */
1812b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0ee80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ4_64 */
1822b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0f680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ5_64 */
1832b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x0fe80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ6_64 */
1842b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x10680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ7_64 */
1852b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x10a80, 32},	/* PATTERN_ISI_XTALK_FREE */
1862b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x10e80, 32},	/* PATTERN_ISI_XTALK_FREE_64 */
1872b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x11280, 32},	/* PATTERN_VREF */
1882b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x11680, 32},	/* PATTERN_VREF_64 */
1892b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x11a80, 32},	/* PATTERN_VREF_INV */
1902b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x11e80, 32},	/* PATTERN_FULL_SSO_0T */
1912b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x12280, 32},	/* PATTERN_FULL_SSO_1T */
1922b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x12680, 32},	/* PATTERN_FULL_SSO_2T */
1932b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x12a80, 32},	/* PATTERN_FULL_SSO_3T */
1942b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x12e80, 32},	/* PATTERN_RESONANCE_1T */
1952b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x13280, 32},	/* PATTERN_RESONANCE_2T */
1962b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x13680, 32},	/* PATTERN_RESONANCE_3T */
1972b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x13a80, 32},	/* PATTERN_RESONANCE_4T */
1982b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x13e80, 32},	/* PATTERN_RESONANCE_5T */
1992b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x14280, 32},	/* PATTERN_RESONANCE_6T */
2002b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x14680, 32},	/* PATTERN_RESONANCE_7T */
2012b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x14a80, 32},	/* PATTERN_RESONANCE_8T */
2022b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x14e80, 32},	/* PATTERN_RESONANCE_9T */
2032b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x15280, 32},	/* PATTERN_ZERO */
2042b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x15680, 32}	/* PATTERN_ONE */
2052b4ffbf6SChris Packham 	/* Note: actual start_address is "<< 3" of defined address */
2062b4ffbf6SChris Packham };
207f1df9364SStefan Roese 
208f1df9364SStefan Roese struct pattern_info pattern_table_16[] = {
209f1df9364SStefan Roese 	/*
210f1df9364SStefan Roese 	 * num tx phases, tx burst, delay between, rx pattern,
211f1df9364SStefan Roese 	 * start_address, pattern_len
212f1df9364SStefan Roese 	 */
213f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0080, 2},	/* PATTERN_PBS1 */
214f1df9364SStefan Roese 	{1, 1, 2, 1, 0x00c0, 2},	/* PATTERN_PBS2 */
2152b4ffbf6SChris Packham 	{1, 1, 2, 1, 0x0380, 2},	/* PATTERN_PBS3 */
2162b4ffbf6SChris Packham 	{1, 1, 2, 1, 0x0040, 2},	/* PATTERN_TEST */
217f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0100, 2},	/* PATTERN_RL */
2182b4ffbf6SChris Packham 	{1, 1, 2, 1, 0x0000, 2},	/* PATTERN_RL2 */
219f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0140, 16},	/* PATTERN_STATIC_PBS */
220f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0190, 16},	/* PATTERN_KILLER_DQ0 */
221f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x01d0, 16},	/* PATTERN_KILLER_DQ1 */
222f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0210, 16},	/* PATTERN_KILLER_DQ2 */
223f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0250, 16},	/* PATTERN_KILLER_DQ3 */
224f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0290, 16},	/* PATTERN_KILLER_DQ4 */
225f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x02d0, 16},	/* PATTERN_KILLER_DQ5 */
226f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0310, 16},	/* PATTERN_KILLER_DQ6 */
227f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0350, 16},	/* PATTERN_KILLER_DQ7 */
2282b4ffbf6SChris Packham 	{0xf, 0x7, 2, 0x7, 0x04c0, 16},	/* PATTERN_VREF */
229f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x03c0, 16},	/* PATTERN_FULL_SSO_1T */
230f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0400, 16},	/* PATTERN_FULL_SSO_2T */
231f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0440, 16},	/* PATTERN_FULL_SSO_3T */
232f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0480, 16},	/* PATTERN_FULL_SSO_4T */
2332b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x6280, 16},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
2342b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x6680, 16},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
2352b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x6A80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ2 */
2362b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x6E80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ3 */
2372b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x7280, 16},	/* PATTERN_SSO_FULL_XTALK_DQ4 */
2382b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x7680, 16},	/* PATTERN_SSO_FULL_XTALK_DQ5 */
2392b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x7A80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ6 */
2402b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x7E80, 16},	/* PATTERN_SSO_FULL_XTALK_DQ7 */
2412b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x8280, 16},	/* PATTERN_SSO_XTALK_FREE_DQ0 */
2422b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x8680, 16},	/* PATTERN_SSO_XTALK_FREE_DQ1 */
2432b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x8A80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ2 */
2442b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x8E80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ3 */
2452b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x9280, 16},	/* PATTERN_SSO_XTALK_FREE_DQ4 */
2462b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x9680, 16},	/* PATTERN_SSO_XTALK_FREE_DQ5 */
2472b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x9A80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ6 */
2482b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0x9E80, 16},	/* PATTERN_SSO_XTALK_FREE_DQ7 */
2492b4ffbf6SChris Packham 	{0xf, 7, 2, 7, 0xA280, 16}	/* PATTERN_ISI_XTALK_FREE */
2502b4ffbf6SChris Packham 	/* Note: actual start_address is "<< 3" of defined address */
251f1df9364SStefan Roese };
252f1df9364SStefan Roese 
253f1df9364SStefan Roese struct pattern_info pattern_table_32[] = {
254f1df9364SStefan Roese 	/*
255f1df9364SStefan Roese 	 * num tx phases, tx burst, delay between, rx pattern,
256f1df9364SStefan Roese 	 * start_address, pattern_len
257f1df9364SStefan Roese 	 */
258f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0080, 4},	/* PATTERN_PBS1 */
259f1df9364SStefan Roese 	{3, 3, 2, 3, 0x00c0, 4},	/* PATTERN_PBS2 */
2602b4ffbf6SChris Packham 	{3, 3, 2, 3, 0x0380, 4},	/* PATTERN_PBS3 */
2612b4ffbf6SChris Packham 	{3, 3, 2, 3, 0x0040, 4},	/* PATTERN_TEST */
262f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0100, 4},	/* PATTERN_RL */
2632b4ffbf6SChris Packham 	{3, 3, 2, 3, 0x0000, 4},	/* PATTERN_RL2 */
264f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0140, 32},	/* PATTERN_STATIC_PBS */
265f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0190, 32},	/* PATTERN_KILLER_DQ0 */
266f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x01d0, 32},	/* PATTERN_KILLER_DQ1 */
267f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0210, 32},	/* PATTERN_KILLER_DQ2 */
268f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0250, 32},	/* PATTERN_KILLER_DQ3 */
269f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0290, 32},	/* PATTERN_KILLER_DQ4 */
270f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x02d0, 32},	/* PATTERN_KILLER_DQ5 */
271f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0310, 32},	/* PATTERN_KILLER_DQ6 */
272f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0350, 32},	/* PATTERN_KILLER_DQ7 */
2732b4ffbf6SChris Packham 	{0x1f, 0xf, 2, 0xf, 0x04c0, 32},	/* PATTERN_VREF */
274f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x03c0, 32},	/* PATTERN_FULL_SSO_1T */
275f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0400, 32},	/* PATTERN_FULL_SSO_2T */
276f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0440, 32},	/* PATTERN_FULL_SSO_3T */
277f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0480, 32},	/* PATTERN_FULL_SSO_4T */
2782b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x6280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ0 */
2792b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x6680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ1 */
2802b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x6A80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ2 */
2812b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x6E80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ3 */
2822b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x7280, 32},	/* PATTERN_SSO_FULL_XTALK_DQ4 */
2832b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x7680, 32},	/* PATTERN_SSO_FULL_XTALK_DQ5 */
2842b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x7A80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ6 */
2852b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x7E80, 32},	/* PATTERN_SSO_FULL_XTALK_DQ7 */
2862b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x8280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ0 */
2872b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x8680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ1 */
2882b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x8A80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ2 */
2892b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x8E80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ3 */
2902b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x9280, 32},	/* PATTERN_SSO_XTALK_FREE_DQ4 */
2912b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x9680, 32},	/* PATTERN_SSO_XTALK_FREE_DQ5 */
2922b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x9A80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ6 */
2932b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0x9E80, 32},	/* PATTERN_SSO_XTALK_FREE_DQ7 */
2942b4ffbf6SChris Packham 	{0x1f, 0xF, 2, 0xf, 0xA280, 32}		/* PATTERN_ISI_XTALK_FREE */
2952b4ffbf6SChris Packham 	/* Note: actual start_address is "<< 3" of defined address */
296f1df9364SStefan Roese };
297f1df9364SStefan Roese 
298f1df9364SStefan Roese u32 train_dev_num;
299f1df9364SStefan Roese enum hws_ddr_cs traintrain_cs_type;
300f1df9364SStefan Roese u32 train_pup_num;
301f1df9364SStefan Roese enum hws_training_result train_result_type;
302f1df9364SStefan Roese enum hws_control_element train_control_element;
303f1df9364SStefan Roese enum hws_search_dir traine_search_dir;
304f1df9364SStefan Roese enum hws_dir train_direction;
305f1df9364SStefan Roese u32 train_if_select;
306f1df9364SStefan Roese u32 train_init_value;
307f1df9364SStefan Roese u32 train_number_iterations;
308f1df9364SStefan Roese enum hws_pattern train_pattern;
309f1df9364SStefan Roese enum hws_edge_compare train_edge_compare;
310f1df9364SStefan Roese u32 train_cs_num;
311f1df9364SStefan Roese u32 train_if_acess, train_if_id, train_pup_access;
312f1df9364SStefan Roese u32 max_polling_for_done = 1000000;
313f1df9364SStefan Roese 
ddr3_tip_get_buf_ptr(u32 dev_num,enum hws_search_dir search,enum hws_training_result result_type,u32 interface_num)314f1df9364SStefan Roese u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
315f1df9364SStefan Roese 			  enum hws_training_result result_type,
316f1df9364SStefan Roese 			  u32 interface_num)
317f1df9364SStefan Roese {
318f1df9364SStefan Roese 	u32 *buf_ptr = NULL;
319f1df9364SStefan Roese 
320f1df9364SStefan Roese 	buf_ptr = &training_res
321f1df9364SStefan Roese 		[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * search +
322f1df9364SStefan Roese 		 interface_num * MAX_BUS_NUM * BUS_WIDTH_IN_BITS];
323f1df9364SStefan Roese 
324f1df9364SStefan Roese 	return buf_ptr;
325f1df9364SStefan Roese }
326f1df9364SStefan Roese 
3272b4ffbf6SChris Packham enum {
3282b4ffbf6SChris Packham 	PASS,
3292b4ffbf6SChris Packham 	FAIL
3302b4ffbf6SChris Packham };
331f1df9364SStefan Roese /*
332f1df9364SStefan Roese  * IP Training search
333f1df9364SStefan Roese  * Note: for one edge search only from fail to pass, else jitter can
334f1df9364SStefan Roese  * be be entered into solution.
335f1df9364SStefan Roese  */
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)336f1df9364SStefan Roese int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
337f1df9364SStefan Roese 			 u32 interface_num,
338f1df9364SStefan Roese 			 enum hws_access_type pup_access_type,
339f1df9364SStefan Roese 			 u32 pup_num, enum hws_training_result result_type,
340f1df9364SStefan Roese 			 enum hws_control_element control_element,
341f1df9364SStefan Roese 			 enum hws_search_dir search_dir, enum hws_dir direction,
342f1df9364SStefan Roese 			 u32 interface_mask, u32 init_value, u32 num_iter,
343f1df9364SStefan Roese 			 enum hws_pattern pattern,
344f1df9364SStefan Roese 			 enum hws_edge_compare edge_comp,
345f1df9364SStefan Roese 			 enum hws_ddr_cs cs_type, u32 cs_num,
346f1df9364SStefan Roese 			 enum hws_training_ip_stat *train_status)
347f1df9364SStefan Roese {
3482b4ffbf6SChris Packham 	u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt,
349f1df9364SStefan Roese 		reg_data, pup_id;
350f1df9364SStefan Roese 	u32 tx_burst_size;
351f1df9364SStefan Roese 	u32 delay_between_burst;
352f1df9364SStefan Roese 	u32 rd_mode;
3532b4ffbf6SChris Packham 	u32 data;
354f1df9364SStefan Roese 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
355f1df9364SStefan Roese 	u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
356f1df9364SStefan Roese 	u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
3572b4ffbf6SChris Packham 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
3582b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
359f1df9364SStefan Roese 
3602b4ffbf6SChris Packham 	if (pup_num >= octets_per_if_num) {
361f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
362f1df9364SStefan Roese 					 ("pup_num %d not valid\n", pup_num));
363f1df9364SStefan Roese 	}
364f1df9364SStefan Roese 	if (interface_num >= MAX_INTERFACE_NUM) {
365f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
366f1df9364SStefan Roese 					 ("if_id %d not valid\n",
367f1df9364SStefan Roese 					  interface_num));
368f1df9364SStefan Roese 	}
369f1df9364SStefan Roese 	if (train_status == NULL) {
370f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
371f1df9364SStefan Roese 					 ("error param 4\n"));
372f1df9364SStefan Roese 		return MV_BAD_PARAM;
373f1df9364SStefan Roese 	}
374f1df9364SStefan Roese 
375f1df9364SStefan Roese 	/* load pattern */
376f1df9364SStefan Roese 	if (cs_type == CS_SINGLE) {
377f1df9364SStefan Roese 		/* All CSs to CS0     */
378f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
379f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
3802b4ffbf6SChris Packham 			      DUAL_DUNIT_CFG_REG, 1 << 3, 1 << 3));
381f1df9364SStefan Roese 		/* All CSs to CS0     */
382f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
383f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
3842b4ffbf6SChris Packham 			      ODPG_DATA_CTRL_REG,
385f1df9364SStefan Roese 			      (0x3 | (effective_cs << 26)), 0xc000003));
386f1df9364SStefan Roese 	} else {
387f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
388f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
3892b4ffbf6SChris Packham 			      DUAL_DUNIT_CFG_REG, 0, 1 << 3));
390f1df9364SStefan Roese 		/*  CS select */
391f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
392f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
3932b4ffbf6SChris Packham 			      ODPG_DATA_CTRL_REG, 0x3 | cs_num << 26,
394f1df9364SStefan Roese 			      0x3 | 3 << 26));
395f1df9364SStefan Roese 	}
396f1df9364SStefan Roese 
397f1df9364SStefan Roese 	/* load pattern to ODPG */
398f1df9364SStefan Roese 	ddr3_tip_load_pattern_to_odpg(dev_num, access_type, interface_num,
399f1df9364SStefan Roese 				      pattern,
400f1df9364SStefan Roese 				      pattern_table[pattern].start_addr);
401f1df9364SStefan Roese 	tx_burst_size =	(direction == OPER_WRITE) ?
402f1df9364SStefan Roese 		pattern_table[pattern].tx_burst_size : 0;
403f1df9364SStefan Roese 	delay_between_burst = (direction == OPER_WRITE) ? 2 : 0;
404f1df9364SStefan Roese 	rd_mode = (direction == OPER_WRITE) ? 1 : 0;
405f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_configure_odpg
406f1df9364SStefan Roese 		     (dev_num, access_type, interface_num, direction,
407f1df9364SStefan Roese 		      pattern_table[pattern].num_of_phases_tx, tx_burst_size,
408f1df9364SStefan Roese 		      pattern_table[pattern].num_of_phases_rx,
409f1df9364SStefan Roese 		      delay_between_burst, rd_mode, effective_cs, STRESS_NONE,
410f1df9364SStefan Roese 		      DURATION_SINGLE));
411f1df9364SStefan Roese 	reg_data = (direction == OPER_READ) ? 0 : (0x3 << 30);
412f1df9364SStefan Roese 	reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa;
413f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
414f1df9364SStefan Roese 		     (dev_num, access_type, interface_num,
4152b4ffbf6SChris Packham 		      ODPG_WR_RD_MODE_ENA_REG, reg_data,
416f1df9364SStefan Roese 		      MASK_ALL_BITS));
417f1df9364SStefan Roese 	reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6;
418f1df9364SStefan Roese 	reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ?
419f1df9364SStefan Roese 		(1 << 7) : 0;
420f1df9364SStefan Roese 
421f1df9364SStefan Roese 	/* change from Pass to Fail will lock the result */
422f1df9364SStefan Roese 	if (pup_access_type == ACCESS_TYPE_MULTICAST)
423f1df9364SStefan Roese 		reg_data |= 0xe << 14;
424f1df9364SStefan Roese 	else
425f1df9364SStefan Roese 		reg_data |= pup_num << 14;
426f1df9364SStefan Roese 
427f1df9364SStefan Roese 	if (edge_comp == EDGE_FP) {
428f1df9364SStefan Roese 		/* don't search for readl edge change, only the state */
429f1df9364SStefan Roese 		reg_data |= (0 << 20);
430f1df9364SStefan Roese 	} else if (edge_comp == EDGE_FPF) {
431f1df9364SStefan Roese 		reg_data |= (0 << 20);
432f1df9364SStefan Roese 	} else {
433f1df9364SStefan Roese 		reg_data |= (3 << 20);
434f1df9364SStefan Roese 	}
435f1df9364SStefan Roese 
436f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
437f1df9364SStefan Roese 		     (dev_num, access_type, interface_num,
4382b4ffbf6SChris Packham 		      GENERAL_TRAINING_OPCODE_REG,
439f1df9364SStefan Roese 		      reg_data | (0x7 << 8) | (0x7 << 11),
440f1df9364SStefan Roese 		      (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) |
441f1df9364SStefan Roese 		       (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20))));
442f1df9364SStefan Roese 	reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8);
443f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
4442b4ffbf6SChris Packham 		     (dev_num, access_type, interface_num, OPCODE_REG0_REG(1),
445f1df9364SStefan Roese 		      1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26),
446f1df9364SStefan Roese 		      0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26)));
447f1df9364SStefan Roese 
448f1df9364SStefan Roese 	/*
449f1df9364SStefan Roese 	 * Write2_dunit(0x10b4, Number_iteration , [15:0])
450f1df9364SStefan Roese 	 * Max number of iterations
451f1df9364SStefan Roese 	 */
452f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
4532b4ffbf6SChris Packham 				       OPCODE_REG1_REG(1), num_iter,
454f1df9364SStefan Roese 				       0xffff));
455f1df9364SStefan Roese 	if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
456f1df9364SStefan Roese 	    direction == OPER_READ) {
457f1df9364SStefan Roese 		/*
458f1df9364SStefan Roese 		 * Write2_dunit(0x10c0, 0x5f , [7:0])
459f1df9364SStefan Roese 		 * MC PBS Reg Address at DDR PHY
460f1df9364SStefan Roese 		 */
4612b4ffbf6SChris Packham 		reg_data = PBS_RX_BCAST_PHY_REG(effective_cs);
462f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
463f1df9364SStefan Roese 		   direction == OPER_WRITE) {
4642b4ffbf6SChris Packham 		reg_data = PBS_TX_BCAST_PHY_REG(effective_cs);
465f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
466f1df9364SStefan Roese 		   direction == OPER_WRITE) {
467f1df9364SStefan Roese 		/*
468f1df9364SStefan Roese 		 * LOOP         0x00000001 + 4*n:
469f1df9364SStefan Roese 		 * where n (0-3) represents M_CS number
470f1df9364SStefan Roese 		 */
471f1df9364SStefan Roese 		/*
472f1df9364SStefan Roese 		 * Write2_dunit(0x10c0, 0x1 , [7:0])
473f1df9364SStefan Roese 		 * ADLL WR Reg Address at DDR PHY
474f1df9364SStefan Roese 		 */
4752b4ffbf6SChris Packham 		reg_data = CTX_PHY_REG(effective_cs);
476f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
477f1df9364SStefan Roese 		   direction == OPER_READ) {
478f1df9364SStefan Roese 		/* ADLL RD Reg Address at DDR PHY */
4792b4ffbf6SChris Packham 		reg_data = CRX_PHY_REG(effective_cs);
480f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
481f1df9364SStefan Roese 		   direction == OPER_WRITE) {
482f1df9364SStefan Roese 		/* TBD not defined in 0.5.0 requirement  */
483f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
484f1df9364SStefan Roese 		   direction == OPER_READ) {
485f1df9364SStefan Roese 		/* TBD not defined in 0.5.0 requirement */
486f1df9364SStefan Roese 	}
487f1df9364SStefan Roese 
488f1df9364SStefan Roese 	reg_data |= (0x6 << 28);
489f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
4902b4ffbf6SChris Packham 		     (dev_num, access_type, interface_num, CAL_PHY_REG(1),
491f1df9364SStefan Roese 		      reg_data | (init_value << 8),
492f1df9364SStefan Roese 		      0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28)));
493f1df9364SStefan Roese 
4942b4ffbf6SChris Packham 	mask_dq_num_of_regs = octets_per_if_num * BUS_WIDTH_IN_BITS;
4952b4ffbf6SChris Packham 	mask_pup_num_of_regs = octets_per_if_num;
496f1df9364SStefan Roese 
497f1df9364SStefan Roese 	if (result_type == RESULT_PER_BIT) {
498f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
499f1df9364SStefan Roese 		     index_cnt++) {
500f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
501f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
502f1df9364SStefan Roese 				      mask_results_dq_reg_map[index_cnt], 0,
503f1df9364SStefan Roese 				      1 << 24));
504f1df9364SStefan Roese 		}
505f1df9364SStefan Roese 
506f1df9364SStefan Roese 		/* Mask disabled buses */
5072b4ffbf6SChris Packham 		for (pup_id = 0; pup_id < octets_per_if_num;
508f1df9364SStefan Roese 		     pup_id++) {
5092b4ffbf6SChris Packham 			if (IS_BUS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
510f1df9364SStefan Roese 				continue;
511f1df9364SStefan Roese 
5122b4ffbf6SChris Packham 			for (index_cnt = (pup_id * 8); index_cnt < (pup_id + 1) * 8; index_cnt++) {
513f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_if_write
514f1df9364SStefan Roese 					     (dev_num, access_type,
515f1df9364SStefan Roese 					      interface_num,
516f1df9364SStefan Roese 					      mask_results_dq_reg_map
517f1df9364SStefan Roese 					      [index_cnt], (1 << 24), 1 << 24));
518f1df9364SStefan Roese 			}
519f1df9364SStefan Roese 		}
520f1df9364SStefan Roese 
521f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
522f1df9364SStefan Roese 		     index_cnt++) {
523f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
524f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
525f1df9364SStefan Roese 				      mask_results_pup_reg_map[index_cnt],
526f1df9364SStefan Roese 				      (1 << 24), 1 << 24));
527f1df9364SStefan Roese 		}
528f1df9364SStefan Roese 	} else if (result_type == RESULT_PER_BYTE) {
529f1df9364SStefan Roese 		/* write to adll */
530f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
531f1df9364SStefan Roese 		     index_cnt++) {
532f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
533f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
534f1df9364SStefan Roese 				      mask_results_pup_reg_map[index_cnt], 0,
535f1df9364SStefan Roese 				      1 << 24));
536f1df9364SStefan Roese 		}
537f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
538f1df9364SStefan Roese 		     index_cnt++) {
539f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
540f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
541f1df9364SStefan Roese 				      mask_results_dq_reg_map[index_cnt],
542f1df9364SStefan Roese 				      (1 << 24), (1 << 24)));
543f1df9364SStefan Roese 		}
544f1df9364SStefan Roese 	}
545f1df9364SStefan Roese 
5462b4ffbf6SChris Packham 	/* trigger training */
5472b4ffbf6SChris Packham 	mv_ddr_training_enable();
5482b4ffbf6SChris Packham 
5492b4ffbf6SChris Packham 	/* wa for 16-bit mode: wait for all rfu tests to finish or timeout */
550f1df9364SStefan Roese 	mdelay(1);
551f1df9364SStefan Roese 
5522b4ffbf6SChris Packham 	/* check for training done */
5532b4ffbf6SChris Packham 	if (mv_ddr_is_training_done(MAX_POLLING_ITERATIONS, &data) != MV_OK) {
5542b4ffbf6SChris Packham 		train_status[0] = HWS_TRAINING_IP_STATUS_TIMEOUT;
5552b4ffbf6SChris Packham 	} else { /* training done; check for pass */
5562b4ffbf6SChris Packham 		if (data == PASS)
5572b4ffbf6SChris Packham 			train_status[0] = HWS_TRAINING_IP_STATUS_SUCCESS;
5582b4ffbf6SChris Packham 		else
5592b4ffbf6SChris Packham 			train_status[0] = HWS_TRAINING_IP_STATUS_FAIL;
560f1df9364SStefan Roese 	}
561f1df9364SStefan Roese 
5622b4ffbf6SChris Packham 	ddr3_tip_if_write(0, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
5632b4ffbf6SChris Packham 			  ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS);
564f1df9364SStefan Roese 
565f1df9364SStefan Roese 	return MV_OK;
566f1df9364SStefan Roese }
567f1df9364SStefan Roese 
568f1df9364SStefan Roese /*
569f1df9364SStefan Roese  * Load expected Pattern to ODPG
570f1df9364SStefan Roese  */
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)571f1df9364SStefan Roese int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
572f1df9364SStefan Roese 				  u32 if_id, enum hws_pattern pattern,
573f1df9364SStefan Roese 				  u32 load_addr)
574f1df9364SStefan Roese {
575f1df9364SStefan Roese 	u32 pattern_length_cnt = 0;
576f1df9364SStefan Roese 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
5772b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
578f1df9364SStefan Roese 
579f1df9364SStefan Roese 	for (pattern_length_cnt = 0;
580f1df9364SStefan Roese 	     pattern_length_cnt < pattern_table[pattern].pattern_len;
5812b4ffbf6SChris Packham 	     pattern_length_cnt++) {	/* FIXME: the ecc patch below is only for a7040 A0 */
5822b4ffbf6SChris Packham 		if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)/* || tm->bus_act_mask == MV_DDR_32BIT_ECC_PUP8_BUS_MASK*/) {
583f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
584f1df9364SStefan Roese 				     (dev_num, access_type, if_id,
5852b4ffbf6SChris Packham 				      ODPG_DATA_WR_DATA_LOW_REG,
586f1df9364SStefan Roese 				      pattern_table_get_word(dev_num, pattern,
5872b4ffbf6SChris Packham 							     (u8) (pattern_length_cnt)),
588f1df9364SStefan Roese 				      MASK_ALL_BITS));
589f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
590f1df9364SStefan Roese 				     (dev_num, access_type, if_id,
5912b4ffbf6SChris Packham 				      ODPG_DATA_WR_DATA_HIGH_REG,
5922b4ffbf6SChris Packham 				      pattern_table_get_word(dev_num, pattern,
5932b4ffbf6SChris Packham 							     (u8) (pattern_length_cnt)),
5942b4ffbf6SChris Packham 				      MASK_ALL_BITS));
5952b4ffbf6SChris Packham 		} else {
5962b4ffbf6SChris Packham 			CHECK_STATUS(ddr3_tip_if_write
5972b4ffbf6SChris Packham 				     (dev_num, access_type, if_id,
5982b4ffbf6SChris Packham 					      ODPG_DATA_WR_DATA_LOW_REG,
5992b4ffbf6SChris Packham 				      pattern_table_get_word(dev_num, pattern,
6002b4ffbf6SChris Packham 							     (u8) (pattern_length_cnt * 2)),
6012b4ffbf6SChris Packham 				      MASK_ALL_BITS));
6022b4ffbf6SChris Packham 			CHECK_STATUS(ddr3_tip_if_write
6032b4ffbf6SChris Packham 				     (dev_num, access_type, if_id,
6042b4ffbf6SChris Packham 				      ODPG_DATA_WR_DATA_HIGH_REG,
6052b4ffbf6SChris Packham 				      pattern_table_get_word(dev_num, pattern,
6062b4ffbf6SChris Packham 							     (u8) (pattern_length_cnt * 2 + 1)),
6072b4ffbf6SChris Packham 				      MASK_ALL_BITS));
6082b4ffbf6SChris Packham 		}
6092b4ffbf6SChris Packham 		CHECK_STATUS(ddr3_tip_if_write
6102b4ffbf6SChris Packham 			     (dev_num, access_type, if_id,
6112b4ffbf6SChris Packham 			      ODPG_DATA_WR_ADDR_REG, pattern_length_cnt,
612f1df9364SStefan Roese 			      MASK_ALL_BITS));
613f1df9364SStefan Roese 	}
614f1df9364SStefan Roese 
615f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
616f1df9364SStefan Roese 		     (dev_num, access_type, if_id,
6172b4ffbf6SChris Packham 		      ODPG_DATA_BUFFER_OFFS_REG, load_addr, MASK_ALL_BITS));
618f1df9364SStefan Roese 
619f1df9364SStefan Roese 	return MV_OK;
620f1df9364SStefan Roese }
621f1df9364SStefan Roese 
622f1df9364SStefan Roese /*
623f1df9364SStefan Roese  * Configure ODPG
624f1df9364SStefan Roese  */
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)625f1df9364SStefan Roese int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
626f1df9364SStefan Roese 			    u32 if_id, enum hws_dir direction, u32 tx_phases,
627f1df9364SStefan Roese 			    u32 tx_burst_size, u32 rx_phases,
628f1df9364SStefan Roese 			    u32 delay_between_burst, u32 rd_mode, u32 cs_num,
629f1df9364SStefan Roese 			    u32 addr_stress_jump, u32 single_pattern)
630f1df9364SStefan Roese {
631f1df9364SStefan Roese 	u32 data_value = 0;
632f1df9364SStefan Roese 	int ret;
633f1df9364SStefan Roese 
634f1df9364SStefan Roese 	data_value = ((single_pattern << 2) | (tx_phases << 5) |
635f1df9364SStefan Roese 		      (tx_burst_size << 11) | (delay_between_burst << 15) |
636f1df9364SStefan Roese 		      (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) |
637f1df9364SStefan Roese 		      (addr_stress_jump << 29));
638f1df9364SStefan Roese 	ret = ddr3_tip_if_write(dev_num, access_type, if_id,
6392b4ffbf6SChris Packham 				ODPG_DATA_CTRL_REG, data_value, 0xaffffffc);
640f1df9364SStefan Roese 	if (ret != MV_OK)
641f1df9364SStefan Roese 		return ret;
642f1df9364SStefan Roese 
643f1df9364SStefan Roese 	return MV_OK;
644f1df9364SStefan Roese }
645f1df9364SStefan Roese 
ddr3_tip_process_result(u32 * ar_result,enum hws_edge e_edge,enum hws_edge_search e_edge_search,u32 * edge_result)646f1df9364SStefan Roese int ddr3_tip_process_result(u32 *ar_result, enum hws_edge e_edge,
647f1df9364SStefan Roese 			    enum hws_edge_search e_edge_search,
648f1df9364SStefan Roese 			    u32 *edge_result)
649f1df9364SStefan Roese {
650f1df9364SStefan Roese 	u32 i, res;
651f1df9364SStefan Roese 	int tap_val, max_val = -10000, min_val = 10000;
652f1df9364SStefan Roese 	int lock_success = 1;
653f1df9364SStefan Roese 
654f1df9364SStefan Roese 	for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
655f1df9364SStefan Roese 		res = GET_LOCK_RESULT(ar_result[i]);
656f1df9364SStefan Roese 		if (res == 0) {
657f1df9364SStefan Roese 			lock_success = 0;
658f1df9364SStefan Roese 			break;
659f1df9364SStefan Roese 		}
660f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
661f1df9364SStefan Roese 					 ("lock failed for bit %d\n", i));
662f1df9364SStefan Roese 	}
663f1df9364SStefan Roese 
664f1df9364SStefan Roese 	if (lock_success == 1) {
665f1df9364SStefan Roese 		for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
666f1df9364SStefan Roese 			tap_val = GET_TAP_RESULT(ar_result[i], e_edge);
667f1df9364SStefan Roese 			if (tap_val > max_val)
668f1df9364SStefan Roese 				max_val = tap_val;
669f1df9364SStefan Roese 			if (tap_val < min_val)
670f1df9364SStefan Roese 				min_val = tap_val;
671f1df9364SStefan Roese 			if (e_edge_search == TRAINING_EDGE_MAX)
672f1df9364SStefan Roese 				*edge_result = (u32) max_val;
673f1df9364SStefan Roese 			else
674f1df9364SStefan Roese 				*edge_result = (u32) min_val;
675f1df9364SStefan Roese 
676f1df9364SStefan Roese 			DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
677f1df9364SStefan Roese 						 ("i %d ar_result[i] 0x%x tap_val %d max_val %d min_val %d Edge_result %d\n",
678f1df9364SStefan Roese 						  i, ar_result[i], tap_val,
679f1df9364SStefan Roese 						  max_val, min_val,
680f1df9364SStefan Roese 						  *edge_result));
681f1df9364SStefan Roese 		}
682f1df9364SStefan Roese 	} else {
683f1df9364SStefan Roese 		return MV_FAIL;
684f1df9364SStefan Roese 	}
685f1df9364SStefan Roese 
686f1df9364SStefan Roese 	return MV_OK;
687f1df9364SStefan Roese }
688f1df9364SStefan Roese 
689f1df9364SStefan Roese /*
690f1df9364SStefan Roese  * Read training search result
691f1df9364SStefan Roese  */
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)692f1df9364SStefan Roese int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
693f1df9364SStefan Roese 				  enum hws_access_type pup_access_type,
694f1df9364SStefan Roese 				  u32 pup_num, u32 bit_num,
695f1df9364SStefan Roese 				  enum hws_search_dir search,
696f1df9364SStefan Roese 				  enum hws_dir direction,
697f1df9364SStefan Roese 				  enum hws_training_result result_type,
698f1df9364SStefan Roese 				  enum hws_training_load_op operation,
699f1df9364SStefan Roese 				  u32 cs_num_type, u32 **load_res,
700f1df9364SStefan Roese 				  int is_read_from_db, u8 cons_tap,
701f1df9364SStefan Roese 				  int is_check_result_validity)
702f1df9364SStefan Roese {
703f1df9364SStefan Roese 	u32 reg_offset, pup_cnt, start_pup, end_pup, start_reg, end_reg;
704f1df9364SStefan Roese 	u32 *interface_train_res = NULL;
705f1df9364SStefan Roese 	u16 *reg_addr = NULL;
706f1df9364SStefan Roese 	u32 read_data[MAX_INTERFACE_NUM];
707f1df9364SStefan Roese 	u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
708f1df9364SStefan Roese 	u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
7092b4ffbf6SChris Packham 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
7102b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
711f1df9364SStefan Roese 
712f1df9364SStefan Roese 	/*
713f1df9364SStefan Roese 	 * Agreed assumption: all CS mask contain same number of bits,
714f1df9364SStefan Roese 	 * i.e. in multi CS, the number of CS per memory is the same for
715f1df9364SStefan Roese 	 * all pups
716f1df9364SStefan Roese 	 */
717f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
7182b4ffbf6SChris Packham 		     (dev_num, ACCESS_TYPE_UNICAST, if_id, DUAL_DUNIT_CFG_REG,
719f1df9364SStefan Roese 		      (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3)));
720f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
721f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_UNICAST, if_id,
7222b4ffbf6SChris Packham 		      ODPG_DATA_CTRL_REG, (cs_num_type << 26), (3 << 26)));
723f1df9364SStefan Roese 	DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
724f1df9364SStefan Roese 				 ("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",
725f1df9364SStefan Roese 				  is_read_from_db, cs_num_type, operation,
726f1df9364SStefan Roese 				  result_type, direction, search, pup_num,
727f1df9364SStefan Roese 				  if_id, pup_access_type));
728f1df9364SStefan Roese 
729f1df9364SStefan Roese 	if ((load_res == NULL) && (is_read_from_db == 1)) {
730f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
731f1df9364SStefan Roese 					 ("ddr3_tip_read_training_result load_res = NULL"));
732f1df9364SStefan Roese 		return MV_FAIL;
733f1df9364SStefan Roese 	}
7342b4ffbf6SChris Packham 	if (pup_num >= octets_per_if_num) {
735f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
736f1df9364SStefan Roese 					 ("pup_num %d not valid\n", pup_num));
737f1df9364SStefan Roese 	}
738f1df9364SStefan Roese 	if (if_id >= MAX_INTERFACE_NUM) {
739f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
740f1df9364SStefan Roese 					 ("if_id %d not valid\n", if_id));
741f1df9364SStefan Roese 	}
742f1df9364SStefan Roese 	if (result_type == RESULT_PER_BIT)
743f1df9364SStefan Roese 		reg_addr = mask_results_dq_reg_map;
744f1df9364SStefan Roese 	else
745f1df9364SStefan Roese 		reg_addr = mask_results_pup_reg_map;
746f1df9364SStefan Roese 	if (pup_access_type == ACCESS_TYPE_UNICAST) {
747f1df9364SStefan Roese 		start_pup = pup_num;
748f1df9364SStefan Roese 		end_pup = pup_num;
749f1df9364SStefan Roese 	} else {		/*pup_access_type == ACCESS_TYPE_MULTICAST) */
750f1df9364SStefan Roese 
751f1df9364SStefan Roese 		start_pup = 0;
7522b4ffbf6SChris Packham 		end_pup = octets_per_if_num - 1;
753f1df9364SStefan Roese 	}
754f1df9364SStefan Roese 
755f1df9364SStefan Roese 	for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) {
7562b4ffbf6SChris Packham 		VALIDATE_BUS_ACTIVE(tm->bus_act_mask, pup_cnt);
757f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
758f1df9364SStefan Roese 			DEBUG_LEVEL_TRACE,
759f1df9364SStefan Roese 			("if_id %d start_pup %d end_pup %d pup_cnt %d\n",
760f1df9364SStefan Roese 			 if_id, start_pup, end_pup, pup_cnt));
761f1df9364SStefan Roese 		if (result_type == RESULT_PER_BIT) {
762f1df9364SStefan Roese 			if (bit_num == ALL_BITS_PER_PUP) {
763f1df9364SStefan Roese 				start_reg = pup_cnt * BUS_WIDTH_IN_BITS;
764f1df9364SStefan Roese 				end_reg = (pup_cnt + 1) * BUS_WIDTH_IN_BITS - 1;
765f1df9364SStefan Roese 			} else {
766f1df9364SStefan Roese 				start_reg =
767f1df9364SStefan Roese 					pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
768f1df9364SStefan Roese 				end_reg = pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
769f1df9364SStefan Roese 			}
770f1df9364SStefan Roese 		} else {
771f1df9364SStefan Roese 			start_reg = pup_cnt;
772f1df9364SStefan Roese 			end_reg = pup_cnt;
773f1df9364SStefan Roese 		}
774f1df9364SStefan Roese 
775f1df9364SStefan Roese 		interface_train_res =
776f1df9364SStefan Roese 			ddr3_tip_get_buf_ptr(dev_num, search, result_type,
777f1df9364SStefan Roese 					     if_id);
778f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
779f1df9364SStefan Roese 			DEBUG_LEVEL_TRACE,
780f1df9364SStefan Roese 			("start_reg %d end_reg %d interface %p\n",
781f1df9364SStefan Roese 			 start_reg, end_reg, interface_train_res));
782f1df9364SStefan Roese 		if (interface_train_res == NULL) {
783f1df9364SStefan Roese 			DEBUG_TRAINING_IP_ENGINE(
784f1df9364SStefan Roese 				DEBUG_LEVEL_ERROR,
785f1df9364SStefan Roese 				("interface_train_res is NULL\n"));
786f1df9364SStefan Roese 			return MV_FAIL;
787f1df9364SStefan Roese 		}
788f1df9364SStefan Roese 
789f1df9364SStefan Roese 		for (reg_offset = start_reg; reg_offset <= end_reg;
790f1df9364SStefan Roese 		     reg_offset++) {
791f1df9364SStefan Roese 			if (operation == TRAINING_LOAD_OPERATION_UNLOAD) {
792f1df9364SStefan Roese 				if (is_read_from_db == 0) {
793f1df9364SStefan Roese 					CHECK_STATUS(ddr3_tip_if_read
794f1df9364SStefan Roese 						     (dev_num,
795f1df9364SStefan Roese 						      ACCESS_TYPE_UNICAST,
796f1df9364SStefan Roese 						      if_id,
797f1df9364SStefan Roese 						      reg_addr[reg_offset],
798f1df9364SStefan Roese 						      read_data,
799f1df9364SStefan Roese 						      MASK_ALL_BITS));
800f1df9364SStefan Roese 					if (is_check_result_validity == 1) {
801f1df9364SStefan Roese 						if ((read_data[if_id] &
8022b4ffbf6SChris Packham 						     TIP_ENG_LOCK) == 0) {
803f1df9364SStefan Roese 							interface_train_res
804f1df9364SStefan Roese 								[reg_offset] =
8052b4ffbf6SChris Packham 								TIP_ENG_LOCK +
8062b4ffbf6SChris Packham 								TIP_TX_DLL_RANGE_MAX;
807f1df9364SStefan Roese 						} else {
808f1df9364SStefan Roese 							interface_train_res
809f1df9364SStefan Roese 								[reg_offset] =
810f1df9364SStefan Roese 								read_data
811f1df9364SStefan Roese 								[if_id] +
812f1df9364SStefan Roese 								cons_tap;
813f1df9364SStefan Roese 						}
814f1df9364SStefan Roese 					} else {
815f1df9364SStefan Roese 						interface_train_res[reg_offset]
816f1df9364SStefan Roese 							= read_data[if_id] +
817f1df9364SStefan Roese 							cons_tap;
818f1df9364SStefan Roese 					}
819f1df9364SStefan Roese 					DEBUG_TRAINING_IP_ENGINE
820f1df9364SStefan Roese 						(DEBUG_LEVEL_TRACE,
821f1df9364SStefan Roese 						 ("reg_offset %d value 0x%x addr %p\n",
822f1df9364SStefan Roese 						  reg_offset,
823f1df9364SStefan Roese 						  interface_train_res
824f1df9364SStefan Roese 						  [reg_offset],
825f1df9364SStefan Roese 						  &interface_train_res
826f1df9364SStefan Roese 						  [reg_offset]));
827f1df9364SStefan Roese 				} else {
828f1df9364SStefan Roese 					*load_res =
829f1df9364SStefan Roese 						&interface_train_res[start_reg];
830f1df9364SStefan Roese 					DEBUG_TRAINING_IP_ENGINE
831f1df9364SStefan Roese 						(DEBUG_LEVEL_TRACE,
832f1df9364SStefan Roese 						 ("*load_res %p\n", *load_res));
833f1df9364SStefan Roese 				}
834f1df9364SStefan Roese 			} else {
835f1df9364SStefan Roese 				DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
836f1df9364SStefan Roese 							 ("not supported\n"));
837f1df9364SStefan Roese 			}
838f1df9364SStefan Roese 		}
839f1df9364SStefan Roese 	}
840f1df9364SStefan Roese 
841f1df9364SStefan Roese 	return MV_OK;
842f1df9364SStefan Roese }
843f1df9364SStefan Roese 
844f1df9364SStefan Roese /*
845f1df9364SStefan Roese  * Load all pattern to memory using ODPG
846f1df9364SStefan Roese  */
ddr3_tip_load_all_pattern_to_mem(u32 dev_num)847f1df9364SStefan Roese int ddr3_tip_load_all_pattern_to_mem(u32 dev_num)
848f1df9364SStefan Roese {
849f1df9364SStefan Roese 	u32 pattern = 0, if_id;
8502b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
851f1df9364SStefan Roese 
852f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
8532b4ffbf6SChris Packham 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
854f1df9364SStefan Roese 		training_result[training_stage][if_id] = TEST_SUCCESS;
855f1df9364SStefan Roese 	}
856f1df9364SStefan Roese 
857f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
8582b4ffbf6SChris Packham 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
859f1df9364SStefan Roese 		/* enable single cs */
860f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
861f1df9364SStefan Roese 			     (dev_num, ACCESS_TYPE_UNICAST, if_id,
8622b4ffbf6SChris Packham 			      DUAL_DUNIT_CFG_REG, (1 << 3), (1 << 3)));
863f1df9364SStefan Roese 	}
864f1df9364SStefan Roese 
8652b4ffbf6SChris Packham 	for (pattern = 0; pattern < PATTERN_LAST; pattern++)
866f1df9364SStefan Roese 		ddr3_tip_load_pattern_to_mem(dev_num, pattern);
867f1df9364SStefan Roese 
868f1df9364SStefan Roese 	return MV_OK;
869f1df9364SStefan Roese }
870f1df9364SStefan Roese 
871f1df9364SStefan Roese /*
872f1df9364SStefan Roese  * Load specific pattern to memory using ODPG
873f1df9364SStefan Roese  */
ddr3_tip_load_pattern_to_mem(u32 dev_num,enum hws_pattern pattern)874f1df9364SStefan Roese int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern)
875f1df9364SStefan Roese {
876f1df9364SStefan Roese 	u32 reg_data, if_id;
877f1df9364SStefan Roese 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
8782b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
879f1df9364SStefan Roese 
880f1df9364SStefan Roese 	/* load pattern to memory */
881f1df9364SStefan Roese 	/*
882f1df9364SStefan Roese 	 * Write Tx mode, CS0, phases, Tx burst size, delay between burst,
883f1df9364SStefan Roese 	 * rx pattern phases
884f1df9364SStefan Roese 	 */
885f1df9364SStefan Roese 	reg_data =
886f1df9364SStefan Roese 		0x1 | (pattern_table[pattern].num_of_phases_tx << 5) |
887f1df9364SStefan Roese 		(pattern_table[pattern].tx_burst_size << 11) |
888f1df9364SStefan Roese 		(pattern_table[pattern].delay_between_bursts << 15) |
889f1df9364SStefan Roese 		(pattern_table[pattern].num_of_phases_rx << 21) | (0x1 << 25) |
890f1df9364SStefan Roese 		(effective_cs << 26);
891f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
892f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
8932b4ffbf6SChris Packham 		      ODPG_DATA_CTRL_REG, reg_data, MASK_ALL_BITS));
894f1df9364SStefan Roese 	/* ODPG Write enable from BIST */
895f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
896f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
8972b4ffbf6SChris Packham 		      ODPG_DATA_CTRL_REG, (0x1 | (effective_cs << 26)),
898f1df9364SStefan Roese 		      0xc000003));
899f1df9364SStefan Roese 	/* disable error injection */
900f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
901f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
9022b4ffbf6SChris Packham 		      ODPG_DATA_WR_DATA_ERR_REG, 0, 0x1));
903f1df9364SStefan Roese 	/* load pattern to ODPG */
904f1df9364SStefan Roese 	ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
905f1df9364SStefan Roese 				      PARAM_NOT_CARE, pattern,
906f1df9364SStefan Roese 				      pattern_table[pattern].start_addr);
907f1df9364SStefan Roese 
9082b4ffbf6SChris Packham 	if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
909f1df9364SStefan Roese 		for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
9102b4ffbf6SChris Packham 			VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
911f1df9364SStefan Roese 
912f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
9132b4ffbf6SChris Packham 				     (dev_num, ACCESS_TYPE_UNICAST, if_id,
9142b4ffbf6SChris Packham 				      SDRAM_ODT_CTRL_HIGH_REG,
915f1df9364SStefan Roese 				      0x3, 0xf));
916f1df9364SStefan Roese 		}
917f1df9364SStefan Roese 
9182b4ffbf6SChris Packham 		mv_ddr_odpg_enable();
9192b4ffbf6SChris Packham 	} else {
920f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
921f1df9364SStefan Roese 			     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
9222b4ffbf6SChris Packham 			      ODPG_DATA_CTRL_REG, (u32)(0x1 << 31),
9232b4ffbf6SChris Packham 			      (u32)(0x1 << 31)));
9242b4ffbf6SChris Packham 	}
925f1df9364SStefan Roese 	mdelay(1);
926f1df9364SStefan Roese 
9272b4ffbf6SChris Packham 	if (mv_ddr_is_odpg_done(MAX_POLLING_ITERATIONS) != MV_OK)
9282b4ffbf6SChris Packham 		return MV_FAIL;
929f1df9364SStefan Roese 
930f1df9364SStefan Roese 	/* Disable ODPG and stop write to memory */
931f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
932f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
9332b4ffbf6SChris Packham 		      ODPG_DATA_CTRL_REG, (0x1 << 30), (u32) (0x3 << 30)));
934f1df9364SStefan Roese 
935f1df9364SStefan Roese 	/* return to default */
936f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
937f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
9382b4ffbf6SChris Packham 		      ODPG_DATA_CTRL_REG, 0, MASK_ALL_BITS));
939f1df9364SStefan Roese 
9402b4ffbf6SChris Packham 	if (ddr3_tip_dev_attr_get(dev_num, MV_ATTR_TIP_REV) >= MV_TIP_REV_3) {
941f1df9364SStefan Roese 		/* Disable odt0 for CS0 training - need to adjust for multy CS */
942f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
9432b4ffbf6SChris Packham 			     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
9442b4ffbf6SChris Packham 			      SDRAM_ODT_CTRL_HIGH_REG, 0x0, 0xf));
9452b4ffbf6SChris Packham 	}
946f1df9364SStefan Roese 	/* temporary added */
947f1df9364SStefan Roese 	mdelay(1);
948f1df9364SStefan Roese 
949f1df9364SStefan Roese 	return MV_OK;
950f1df9364SStefan Roese }
951f1df9364SStefan Roese 
952f1df9364SStefan Roese /*
953f1df9364SStefan Roese  * Training search routine
954f1df9364SStefan Roese  */
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)955f1df9364SStefan Roese int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
956f1df9364SStefan Roese 				     enum hws_access_type access_type,
957f1df9364SStefan Roese 				     u32 if_id,
958f1df9364SStefan Roese 				     enum hws_access_type pup_access_type,
959f1df9364SStefan Roese 				     u32 pup_num, u32 bit_num,
960f1df9364SStefan Roese 				     enum hws_training_result result_type,
961f1df9364SStefan Roese 				     enum hws_control_element control_element,
962f1df9364SStefan Roese 				     enum hws_search_dir search_dir,
963f1df9364SStefan Roese 				     enum hws_dir direction,
964f1df9364SStefan Roese 				     u32 interface_mask, u32 init_value_l2h,
965f1df9364SStefan Roese 				     u32 init_value_h2l, u32 num_iter,
966f1df9364SStefan Roese 				     enum hws_pattern pattern,
967f1df9364SStefan Roese 				     enum hws_edge_compare edge_comp,
968f1df9364SStefan Roese 				     enum hws_ddr_cs train_cs_type, u32 cs_num,
969f1df9364SStefan Roese 				     enum hws_training_ip_stat *train_status)
970f1df9364SStefan Roese {
971f1df9364SStefan Roese 	u32 interface_num = 0, start_if, end_if, init_value_used;
972f1df9364SStefan Roese 	enum hws_search_dir search_dir_id, start_search, end_search;
973f1df9364SStefan Roese 	enum hws_edge_compare edge_comp_used;
9742b4ffbf6SChris Packham 	u8 cons_tap = 0;
9752b4ffbf6SChris Packham 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
9762b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
977f1df9364SStefan Roese 
978f1df9364SStefan Roese 	if (train_status == NULL) {
979f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
980f1df9364SStefan Roese 					 ("train_status is NULL\n"));
981f1df9364SStefan Roese 		return MV_FAIL;
982f1df9364SStefan Roese 	}
983f1df9364SStefan Roese 
984f1df9364SStefan Roese 	if ((train_cs_type > CS_NON_SINGLE) ||
985f1df9364SStefan Roese 	    (edge_comp >= EDGE_PFP) ||
9862b4ffbf6SChris Packham 	    (pattern >= PATTERN_LAST) ||
987f1df9364SStefan Roese 	    (direction > OPER_WRITE_AND_READ) ||
988f1df9364SStefan Roese 	    (search_dir > HWS_HIGH2LOW) ||
989f1df9364SStefan Roese 	    (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) ||
990f1df9364SStefan Roese 	    (result_type > RESULT_PER_BYTE) ||
9912b4ffbf6SChris Packham 	    (pup_num >= octets_per_if_num) ||
992f1df9364SStefan Roese 	    (pup_access_type > ACCESS_TYPE_MULTICAST) ||
993f1df9364SStefan Roese 	    (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) {
994f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
995f1df9364SStefan Roese 			DEBUG_LEVEL_ERROR,
996f1df9364SStefan Roese 			("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",
997f1df9364SStefan Roese 			 train_cs_type, edge_comp, pattern, direction,
998f1df9364SStefan Roese 			 search_dir, control_element, result_type, pup_num,
999f1df9364SStefan Roese 			 pup_access_type, if_id, access_type));
1000f1df9364SStefan Roese 		return MV_FAIL;
1001f1df9364SStefan Roese 	}
1002f1df9364SStefan Roese 
1003f1df9364SStefan Roese 	if (edge_comp == EDGE_FPF) {
1004f1df9364SStefan Roese 		start_search = HWS_LOW2HIGH;
1005f1df9364SStefan Roese 		end_search = HWS_HIGH2LOW;
1006f1df9364SStefan Roese 		edge_comp_used = EDGE_FP;
1007f1df9364SStefan Roese 	} else {
1008f1df9364SStefan Roese 		start_search = search_dir;
1009f1df9364SStefan Roese 		end_search = search_dir;
1010f1df9364SStefan Roese 		edge_comp_used = edge_comp;
1011f1df9364SStefan Roese 	}
1012f1df9364SStefan Roese 
1013f1df9364SStefan Roese 	for (search_dir_id = start_search; search_dir_id <= end_search;
1014f1df9364SStefan Roese 	     search_dir_id++) {
1015f1df9364SStefan Roese 		init_value_used = (search_dir_id == HWS_LOW2HIGH) ?
1016f1df9364SStefan Roese 			init_value_l2h : init_value_h2l;
1017f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
1018f1df9364SStefan Roese 			DEBUG_LEVEL_TRACE,
1019f1df9364SStefan Roese 			("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",
1020f1df9364SStefan Roese 			 dev_num, access_type, if_id, pup_access_type, pup_num,
1021f1df9364SStefan Roese 			 result_type, control_element, search_dir_id,
1022f1df9364SStefan Roese 			 direction, interface_mask, init_value_used, num_iter,
1023f1df9364SStefan Roese 			 pattern, edge_comp_used, train_cs_type, cs_num));
1024f1df9364SStefan Roese 
1025f1df9364SStefan Roese 		ddr3_tip_ip_training(dev_num, access_type, if_id,
1026f1df9364SStefan Roese 				     pup_access_type, pup_num, result_type,
1027f1df9364SStefan Roese 				     control_element, search_dir_id, direction,
1028f1df9364SStefan Roese 				     interface_mask, init_value_used, num_iter,
1029f1df9364SStefan Roese 				     pattern, edge_comp_used, train_cs_type,
1030f1df9364SStefan Roese 				     cs_num, train_status);
1031f1df9364SStefan Roese 		if (access_type == ACCESS_TYPE_MULTICAST) {
1032f1df9364SStefan Roese 			start_if = 0;
1033f1df9364SStefan Roese 			end_if = MAX_INTERFACE_NUM - 1;
1034f1df9364SStefan Roese 		} else {
1035f1df9364SStefan Roese 			start_if = if_id;
1036f1df9364SStefan Roese 			end_if = if_id;
1037f1df9364SStefan Roese 		}
1038f1df9364SStefan Roese 
1039f1df9364SStefan Roese 		for (interface_num = start_if; interface_num <= end_if;
1040f1df9364SStefan Roese 		     interface_num++) {
10412b4ffbf6SChris Packham 			VALIDATE_IF_ACTIVE(tm->if_act_mask, interface_num);
1042f1df9364SStefan Roese 			cs_num = 0;
1043f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_read_training_result
1044f1df9364SStefan Roese 				     (dev_num, interface_num, pup_access_type,
1045f1df9364SStefan Roese 				      pup_num, bit_num, search_dir_id,
1046f1df9364SStefan Roese 				      direction, result_type,
1047f1df9364SStefan Roese 				      TRAINING_LOAD_OPERATION_UNLOAD,
1048f1df9364SStefan Roese 				      train_cs_type, NULL, 0, cons_tap,
1049f1df9364SStefan Roese 				      0));
1050f1df9364SStefan Roese 		}
1051f1df9364SStefan Roese 	}
1052f1df9364SStefan Roese 
1053f1df9364SStefan Roese 	return MV_OK;
1054f1df9364SStefan Roese }
1055f1df9364SStefan Roese /*
1056f1df9364SStefan Roese  * Training search & read result routine
10572b4ffbf6SChris Packham  * This function implements the search algorithm
10582b4ffbf6SChris Packham  * first it calls the function ddr3_tip_ip_training_wrapper_int which triggers the search from l2h and h2l
10592b4ffbf6SChris Packham  * this function handles rx and tx search cases
10602b4ffbf6SChris Packham  * in case of rx it only triggers the search (l2h and h2l)
10612b4ffbf6SChris Packham  * in case of tx there are 3 optional algorithm phases:
10622b4ffbf6SChris Packham  * phase 1:
10632b4ffbf6SChris Packham  * it first triggers the search and handles the results as following (phase 1):
10642b4ffbf6SChris Packham  * each bit, which defined by the search two edges (e1 or VW_L and e2 or VW_H), match on of cases:
10652b4ffbf6SChris Packham  *  1.	BIT_LOW_UI	0 =< VW =< 31 in case of jitter use: VW_L <= 31, VW_H <= 31
10662b4ffbf6SChris Packham  *  2.	BIT_HIGH_UI	32 =< VW =< 63 in case of jitter use: VW_L >= 32, VW_H >= 32
10672b4ffbf6SChris Packham  *  3.	BIT_SPLIT_IN	VW_L <= 31 & VW_H >= 32
10682b4ffbf6SChris Packham  *  4.	BIT_SPLIT_OUT*	VW_H < 32 &  VW_L > 32
10692b4ffbf6SChris Packham  * note: the VW units is adll taps
10702b4ffbf6SChris Packham  * phase 2:
10712b4ffbf6SChris Packham  * only bit case BIT_SPLIT_OUT requires another search (phase 2) from the middle range in two directions h2l and l2h
10722b4ffbf6SChris Packham  * because only this case is not locked by the search engine in the first search trigger (phase 1).
10732b4ffbf6SChris Packham  * phase 3:
10742b4ffbf6SChris Packham  * each subphy is categorized according to its bits definition.
10752b4ffbf6SChris Packham  * the sub-phy cases are as follows:
10762b4ffbf6SChris Packham  *  1.BYTE_NOT_DEFINED			the byte has not yet been categorized
10772b4ffbf6SChris Packham  *  2.BYTE_HOMOGENEOUS_LOW		0 =< VW =< 31
10782b4ffbf6SChris Packham  *  3.BYTE_HOMOGENEOUS_HIGH		32 =< VW =< 63
10792b4ffbf6SChris Packham  *  4.BYTE_HOMOGENEOUS_SPLIT_IN		VW_L <= 31 & VW_H >= 32
10802b4ffbf6SChris Packham  *					or the center of all bits in the byte  =< 31
10812b4ffbf6SChris Packham  *  5.BYTE_HOMOGENEOUS_SPLIT_OUT	VW_H < 32 &  VW_L > 32
10822b4ffbf6SChris Packham  *  6.BYTE_SPLIT_OUT_MIX		at least one bits is in split out state and one bit is in other
10832b4ffbf6SChris Packham  *					or the center of all bits in the byte => 32
10842b4ffbf6SChris Packham  * after the two phases above a center valid window for each subphy is calculated accordingly:
10852b4ffbf6SChris Packham  * center valid window = maximum center of all bits in the subphy - minimum center of all bits in the subphy.
10862b4ffbf6SChris Packham  * now decisions are made in each subphy as following:
10872b4ffbf6SChris Packham  * all subphys which are homogeneous remains as is
10882b4ffbf6SChris Packham  * all subphys which are homogeneous low | homogeneous high and the subphy center valid window is less than 32
10892b4ffbf6SChris Packham  *	mark this subphy as homogeneous split in.
10902b4ffbf6SChris Packham  * now the bits in the bytes which are BYTE_SPLIT_OUT_MIX needed to be reorganized and handles as following
10912b4ffbf6SChris Packham  * all bits which are BIT_LOW_UI will be added with 64 adll,
10922b4ffbf6SChris Packham  * this will hopefully ensures that all the bits in the sub phy can be sampled by the dqs
1093f1df9364SStefan Roese  */
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)1094f1df9364SStefan Roese int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type,
1095f1df9364SStefan Roese 	u32 if_id,
1096f1df9364SStefan Roese 	enum hws_access_type pup_access_type,
1097f1df9364SStefan Roese 	u32 pup_num,
1098f1df9364SStefan Roese 	enum hws_training_result result_type,
1099f1df9364SStefan Roese 	enum hws_control_element control_element,
1100f1df9364SStefan Roese 	enum hws_search_dir search_dir,
1101f1df9364SStefan Roese 	enum hws_dir direction, u32 interface_mask,
1102f1df9364SStefan Roese 	u32 init_value_l2h, u32 init_value_h2l,
1103f1df9364SStefan Roese 	u32 num_iter, enum hws_pattern pattern,
1104f1df9364SStefan Roese 	enum hws_edge_compare edge_comp,
1105f1df9364SStefan Roese 	enum hws_ddr_cs train_cs_type, u32 cs_num,
1106f1df9364SStefan Roese 	enum hws_training_ip_stat *train_status)
1107f1df9364SStefan Roese {
1108f1df9364SStefan Roese 	u8 e1, e2;
11092b4ffbf6SChris Packham 	u32 bit_id, start_if, end_if, bit_end = 0;
1110f1df9364SStefan Roese 	u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 };
1111f1df9364SStefan Roese 	u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
1112f1df9364SStefan Roese 	u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0;
11132b4ffbf6SChris Packham 	u8 bit_state[MAX_BUS_NUM * BUS_WIDTH_IN_BITS] = {0};
11142b4ffbf6SChris Packham 	u8 h2l_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
11152b4ffbf6SChris Packham 	u8 l2h_adll_value[MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
11162b4ffbf6SChris Packham 	u8 center_subphy_adll_window[MAX_BUS_NUM];
11172b4ffbf6SChris Packham 	u8 min_center_subphy_adll[MAX_BUS_NUM];
11182b4ffbf6SChris Packham 	u8 max_center_subphy_adll[MAX_BUS_NUM];
11192b4ffbf6SChris Packham 	u32 *l2h_if_train_res = NULL;
11202b4ffbf6SChris Packham 	u32 *h2l_if_train_res = NULL;
11212b4ffbf6SChris Packham 	enum hws_search_dir search_dir_id;
11222b4ffbf6SChris Packham 	int status;
11232b4ffbf6SChris Packham 	u32 bit_lock_result;
1124f1df9364SStefan Roese 
11252b4ffbf6SChris Packham 	u8 sybphy_id;
11262b4ffbf6SChris Packham 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
11272b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
11282b4ffbf6SChris Packham 
11292b4ffbf6SChris Packham 	if (pup_num >= octets_per_if_num) {
1130f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1131f1df9364SStefan Roese 			("pup_num %d not valid\n", pup_num));
1132f1df9364SStefan Roese 	}
1133f1df9364SStefan Roese 
1134f1df9364SStefan Roese 	if (if_id >= MAX_INTERFACE_NUM) {
1135f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1136f1df9364SStefan Roese 			("if_id %d not valid\n", if_id));
1137f1df9364SStefan Roese 	}
1138f1df9364SStefan Roese 
11392b4ffbf6SChris Packham 	status = ddr3_tip_ip_training_wrapper_int
1140f1df9364SStefan Roese 		(dev_num, access_type, if_id, pup_access_type, pup_num,
1141f1df9364SStefan Roese 		ALL_BITS_PER_PUP, result_type, control_element,
1142f1df9364SStefan Roese 		search_dir, direction, interface_mask, init_value_l2h,
1143f1df9364SStefan Roese 		init_value_h2l, num_iter, pattern, edge_comp,
11442b4ffbf6SChris Packham 		train_cs_type, cs_num, train_status);
11452b4ffbf6SChris Packham 
11462b4ffbf6SChris Packham 	if (MV_OK != status)
11472b4ffbf6SChris Packham 		return status;
1148f1df9364SStefan Roese 
1149f1df9364SStefan Roese 	if (access_type == ACCESS_TYPE_MULTICAST) {
1150f1df9364SStefan Roese 		start_if = 0;
1151f1df9364SStefan Roese 		end_if = MAX_INTERFACE_NUM - 1;
1152f1df9364SStefan Roese 	} else {
1153f1df9364SStefan Roese 		start_if = if_id;
1154f1df9364SStefan Roese 		end_if = if_id;
1155f1df9364SStefan Roese 	}
1156f1df9364SStefan Roese 
11572b4ffbf6SChris Packham 	for (if_id = start_if; if_id <= end_if; if_id++) {
11582b4ffbf6SChris Packham 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
11592b4ffbf6SChris Packham 		/* zero the database */
11602b4ffbf6SChris Packham 		bit_bit_mask_active = 0;	/* clean the flag for level2 search */
11612b4ffbf6SChris Packham 		memset(bit_state, 0, sizeof(bit_state));
11622b4ffbf6SChris Packham 		/* phase 1 */
11632b4ffbf6SChris Packham 		for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
11642b4ffbf6SChris Packham 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
1165f1df9364SStefan Roese 			if (result_type == RESULT_PER_BIT)
11662b4ffbf6SChris Packham 				bit_end = BUS_WIDTH_IN_BITS;
1167f1df9364SStefan Roese 			else
1168f1df9364SStefan Roese 				bit_end = 0;
1169f1df9364SStefan Roese 
11702b4ffbf6SChris Packham 			/* zero the data base */
11712b4ffbf6SChris Packham 			bit_bit_mask[sybphy_id] = 0;
11722b4ffbf6SChris Packham 			byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED;
11732b4ffbf6SChris Packham 			for (bit_id = 0; bit_id < bit_end; bit_id++) {
11742b4ffbf6SChris Packham 				h2l_adll_value[sybphy_id][bit_id] = 64;
11752b4ffbf6SChris Packham 				l2h_adll_value[sybphy_id][bit_id] = 0;
11762b4ffbf6SChris Packham 				for (search_dir_id = HWS_LOW2HIGH; search_dir_id <= HWS_HIGH2LOW;
1177f1df9364SStefan Roese 					search_dir_id++) {
11782b4ffbf6SChris Packham 					status = ddr3_tip_read_training_result
11792b4ffbf6SChris Packham 						(dev_num, if_id,
11802b4ffbf6SChris Packham 							ACCESS_TYPE_UNICAST, sybphy_id, bit_id,
11812b4ffbf6SChris Packham 							search_dir_id, direction, result_type,
11822b4ffbf6SChris Packham 							TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
11832b4ffbf6SChris Packham 							&result[search_dir_id], 1, 0, 0);
11842b4ffbf6SChris Packham 
11852b4ffbf6SChris Packham 					if (MV_OK != status)
11862b4ffbf6SChris Packham 						return status;
1187f1df9364SStefan Roese 				}
11882b4ffbf6SChris Packham 
11892b4ffbf6SChris Packham 				e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0], EDGE_1);
11902b4ffbf6SChris Packham 				e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0], EDGE_1);
11912b4ffbf6SChris Packham 				DEBUG_TRAINING_IP_ENGINE
11922b4ffbf6SChris Packham 					(DEBUG_LEVEL_INFO,
11932b4ffbf6SChris Packham 					 ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n",
11942b4ffbf6SChris Packham 					 if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1,
1195f1df9364SStefan Roese 					 result[HWS_HIGH2LOW][0], e2));
11962b4ffbf6SChris Packham 				bit_lock_result =
11972b4ffbf6SChris Packham 					(GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) &&
11982b4ffbf6SChris Packham 						GET_LOCK_RESULT(result[HWS_HIGH2LOW][0]));
11992b4ffbf6SChris Packham 
12002b4ffbf6SChris Packham 				if (bit_lock_result) {
12012b4ffbf6SChris Packham 					/* in case of read operation set the byte status as homogeneous low */
12022b4ffbf6SChris Packham 					if (direction == OPER_READ) {
12032b4ffbf6SChris Packham 						byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW;
12042b4ffbf6SChris Packham 					} else if ((e2 - e1) > 32) { /* oper_write */
12052b4ffbf6SChris Packham 						/* split out */
12062b4ffbf6SChris Packham 						bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
12072b4ffbf6SChris Packham 							BIT_SPLIT_OUT;
12082b4ffbf6SChris Packham 						byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_SPLIT_OUT;
12092b4ffbf6SChris Packham 						/* mark problem bits */
12102b4ffbf6SChris Packham 						bit_bit_mask[sybphy_id] |= (1 << bit_id);
1211f1df9364SStefan Roese 						bit_bit_mask_active = 1;
12122b4ffbf6SChris Packham 						DEBUG_TRAINING_IP_ENGINE
12132b4ffbf6SChris Packham 							(DEBUG_LEVEL_TRACE,
12142b4ffbf6SChris Packham 							 ("if_id %d sybphy_id %d bit %d BIT_SPLIT_OUT\n",
12152b4ffbf6SChris Packham 							 if_id, sybphy_id, bit_id));
12162b4ffbf6SChris Packham 					} else {
12172b4ffbf6SChris Packham 						/* low ui */
12182b4ffbf6SChris Packham 						if (e1 <= 31 && e2 <= 31) {
12192b4ffbf6SChris Packham 							bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
12202b4ffbf6SChris Packham 								BIT_LOW_UI;
12212b4ffbf6SChris Packham 							byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_LOW;
12222b4ffbf6SChris Packham 							l2h_adll_value[sybphy_id][bit_id] = e1;
12232b4ffbf6SChris Packham 							h2l_adll_value[sybphy_id][bit_id] = e2;
12242b4ffbf6SChris Packham 							DEBUG_TRAINING_IP_ENGINE
12252b4ffbf6SChris Packham 								(DEBUG_LEVEL_TRACE,
12262b4ffbf6SChris Packham 								 ("if_id %d sybphy_id %d bit %d BIT_LOW_UI\n",
12272b4ffbf6SChris Packham 								 if_id, sybphy_id, bit_id));
1228f1df9364SStefan Roese 						}
12292b4ffbf6SChris Packham 							/* high ui */
12302b4ffbf6SChris Packham 						if (e1 >= 32 && e2 >= 32) {
12312b4ffbf6SChris Packham 							bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
12322b4ffbf6SChris Packham 								BIT_HIGH_UI;
12332b4ffbf6SChris Packham 							byte_status[if_id][sybphy_id] |= BYTE_HOMOGENEOUS_HIGH;
12342b4ffbf6SChris Packham 							l2h_adll_value[sybphy_id][bit_id] = e1;
12352b4ffbf6SChris Packham 							h2l_adll_value[sybphy_id][bit_id] = e2;
12362b4ffbf6SChris Packham 							DEBUG_TRAINING_IP_ENGINE
12372b4ffbf6SChris Packham 								(DEBUG_LEVEL_TRACE,
12382b4ffbf6SChris Packham 								 ("if_id %d sybphy_id %d bit %d BIT_HIGH_UI\n",
12392b4ffbf6SChris Packham 								 if_id, sybphy_id, bit_id));
12402b4ffbf6SChris Packham 						}
12412b4ffbf6SChris Packham 						/* split in */
12422b4ffbf6SChris Packham 						if (e1 <= 31 && e2 >= 32) {
12432b4ffbf6SChris Packham 							bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] =
12442b4ffbf6SChris Packham 								BIT_SPLIT_IN;
12452b4ffbf6SChris Packham 							byte_status[if_id][sybphy_id] |=
12462b4ffbf6SChris Packham 								BYTE_HOMOGENEOUS_SPLIT_IN;
12472b4ffbf6SChris Packham 							l2h_adll_value[sybphy_id][bit_id] = e1;
12482b4ffbf6SChris Packham 							h2l_adll_value[sybphy_id][bit_id] = e2;
12492b4ffbf6SChris Packham 							DEBUG_TRAINING_IP_ENGINE
12502b4ffbf6SChris Packham 								(DEBUG_LEVEL_TRACE,
12512b4ffbf6SChris Packham 								 ("if_id %d sybphy_id %d bit %d BIT_SPLIT_IN\n",
12522b4ffbf6SChris Packham 								 if_id, sybphy_id, bit_id));
12532b4ffbf6SChris Packham 						}
12542b4ffbf6SChris Packham 					}
12552b4ffbf6SChris Packham 				} else {
12562b4ffbf6SChris Packham 					DEBUG_TRAINING_IP_ENGINE
12572b4ffbf6SChris Packham 						(DEBUG_LEVEL_INFO,
12582b4ffbf6SChris Packham 						 ("if_id %d sybphy_id %d bit %d l2h 0x%x (e1 0x%x)"
12592b4ffbf6SChris Packham 						 "h2l 0x%x (e2 0x%x): bit cannot be categorized\n",
12602b4ffbf6SChris Packham 						 if_id, sybphy_id, bit_id, result[HWS_LOW2HIGH][0], e1,
12612b4ffbf6SChris Packham 						 result[HWS_HIGH2LOW][0], e2));
12622b4ffbf6SChris Packham 					/* mark the byte as not defined */
12632b4ffbf6SChris Packham 					byte_status[if_id][sybphy_id] = BYTE_NOT_DEFINED;
12642b4ffbf6SChris Packham 					break; /* continue to next pup - no reason to analyze this byte */
12652b4ffbf6SChris Packham 				}
12662b4ffbf6SChris Packham 			} /* for all bits */
12672b4ffbf6SChris Packham 		} /* for all PUPs */
1268f1df9364SStefan Roese 
12692b4ffbf6SChris Packham 		/* phase 2 will occur only in write operation */
1270f1df9364SStefan Roese 		if (bit_bit_mask_active != 0) {
12712b4ffbf6SChris Packham 			l2h_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH, result_type, if_id);
12722b4ffbf6SChris Packham 			h2l_if_train_res = ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW, result_type, if_id);
12732b4ffbf6SChris Packham 			/* search from middle to end */
12742b4ffbf6SChris Packham 			ddr3_tip_ip_training
12752b4ffbf6SChris Packham 				(dev_num, ACCESS_TYPE_UNICAST,
12762b4ffbf6SChris Packham 				 if_id, ACCESS_TYPE_MULTICAST,
1277f1df9364SStefan Roese 				 PARAM_NOT_CARE, result_type,
1278f1df9364SStefan Roese 				 control_element, HWS_LOW2HIGH,
1279f1df9364SStefan Roese 				 direction, interface_mask,
1280f1df9364SStefan Roese 				 num_iter / 2, num_iter / 2,
1281f1df9364SStefan Roese 				 pattern, EDGE_FP, train_cs_type,
1282f1df9364SStefan Roese 				 cs_num, train_status);
1283f1df9364SStefan Roese 
12842b4ffbf6SChris Packham 			for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
12852b4ffbf6SChris Packham 				VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
12862b4ffbf6SChris Packham 				if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) {
12872b4ffbf6SChris Packham 					if (bit_bit_mask[sybphy_id] == 0)
12882b4ffbf6SChris Packham 						continue; /* this byte bits have no split out state */
1289f1df9364SStefan Roese 
12902b4ffbf6SChris Packham 					for (bit_id = 0; bit_id < bit_end; bit_id++) {
12912b4ffbf6SChris Packham 						if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0)
12922b4ffbf6SChris Packham 							continue; /* this bit is non split goto next bit */
1293f1df9364SStefan Roese 
12942b4ffbf6SChris Packham 						/* enter the result to the data base */
12952b4ffbf6SChris Packham 						status = ddr3_tip_read_training_result
12962b4ffbf6SChris Packham 							(dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id,
12972b4ffbf6SChris Packham 							 bit_id, HWS_LOW2HIGH, direction, result_type,
12982b4ffbf6SChris Packham 							 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
12992b4ffbf6SChris Packham 							 &l2h_if_train_res, 0, 0, 1);
13002b4ffbf6SChris Packham 
13012b4ffbf6SChris Packham 						if (MV_OK != status)
13022b4ffbf6SChris Packham 							return status;
13032b4ffbf6SChris Packham 
13042b4ffbf6SChris Packham 						l2h_adll_value[sybphy_id][bit_id] =
13052b4ffbf6SChris Packham 							l2h_if_train_res[sybphy_id *
13062b4ffbf6SChris Packham 							BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK;
1307f1df9364SStefan Roese 					}
1308f1df9364SStefan Roese 				}
13092b4ffbf6SChris Packham 			}
13102b4ffbf6SChris Packham 			/* Search from middle to start */
13112b4ffbf6SChris Packham 			ddr3_tip_ip_training
13122b4ffbf6SChris Packham 				(dev_num, ACCESS_TYPE_UNICAST,
13132b4ffbf6SChris Packham 				 if_id, ACCESS_TYPE_MULTICAST,
1314f1df9364SStefan Roese 				 PARAM_NOT_CARE, result_type,
1315f1df9364SStefan Roese 				 control_element, HWS_HIGH2LOW,
1316f1df9364SStefan Roese 				 direction, interface_mask,
1317f1df9364SStefan Roese 				 num_iter / 2, num_iter / 2,
1318f1df9364SStefan Roese 				 pattern, EDGE_FP, train_cs_type,
1319f1df9364SStefan Roese 				 cs_num, train_status);
1320f1df9364SStefan Roese 
13212b4ffbf6SChris Packham 			for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
13222b4ffbf6SChris Packham 				VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
13232b4ffbf6SChris Packham 				if (byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) {
13242b4ffbf6SChris Packham 					if (bit_bit_mask[sybphy_id] == 0)
1325f1df9364SStefan Roese 						continue;
1326f1df9364SStefan Roese 
13272b4ffbf6SChris Packham 					for (bit_id = 0; bit_id < bit_end; bit_id++) {
13282b4ffbf6SChris Packham 						if ((bit_bit_mask[sybphy_id] & (1 << bit_id)) == 0)
1329f1df9364SStefan Roese 							continue;
13302b4ffbf6SChris Packham 
13312b4ffbf6SChris Packham 						status = ddr3_tip_read_training_result
13322b4ffbf6SChris Packham 							(dev_num, if_id, ACCESS_TYPE_UNICAST, sybphy_id,
13332b4ffbf6SChris Packham 							 bit_id, HWS_HIGH2LOW, direction, result_type,
13342b4ffbf6SChris Packham 							 TRAINING_LOAD_OPERATION_UNLOAD, CS_SINGLE,
13352b4ffbf6SChris Packham 							 &h2l_if_train_res, 0, cons_tap, 1);
13362b4ffbf6SChris Packham 
13372b4ffbf6SChris Packham 						if (MV_OK != status)
13382b4ffbf6SChris Packham 							return status;
13392b4ffbf6SChris Packham 
13402b4ffbf6SChris Packham 						h2l_adll_value[sybphy_id][bit_id] =
13412b4ffbf6SChris Packham 							h2l_if_train_res[sybphy_id *
13422b4ffbf6SChris Packham 							BUS_WIDTH_IN_BITS + bit_id] & PUP_RESULT_EDGE_1_MASK;
1343f1df9364SStefan Roese 					}
1344f1df9364SStefan Roese 				}
13452b4ffbf6SChris Packham 			}
13462b4ffbf6SChris Packham 		} /* end if bit_bit_mask_active */
13472b4ffbf6SChris Packham 		/*
13482b4ffbf6SChris Packham 			* phase 3 will occur only in write operation
13492b4ffbf6SChris Packham 			* find the maximum and the minimum center of each subphy
13502b4ffbf6SChris Packham 			*/
13512b4ffbf6SChris Packham 		for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
13522b4ffbf6SChris Packham 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
13532b4ffbf6SChris Packham 
13542b4ffbf6SChris Packham 			if ((byte_status[if_id][sybphy_id] != BYTE_NOT_DEFINED) && (direction == OPER_WRITE)) {
13552b4ffbf6SChris Packham 				/* clear the arrays and parameters */
13562b4ffbf6SChris Packham 				center_subphy_adll_window[sybphy_id] = 0;
13572b4ffbf6SChris Packham 				max_center_subphy_adll[sybphy_id] = 0;
13582b4ffbf6SChris Packham 				min_center_subphy_adll[sybphy_id] = 64;
13592b4ffbf6SChris Packham 				/* find the max and min center adll value in the current subphy */
13602b4ffbf6SChris Packham 				for (bit_id = 0; bit_id < bit_end; bit_id++) {
13612b4ffbf6SChris Packham 					/* debug print all the bit edges after alignment */
13622b4ffbf6SChris Packham 					DEBUG_TRAINING_IP_ENGINE
13632b4ffbf6SChris Packham 						(DEBUG_LEVEL_TRACE,
13642b4ffbf6SChris Packham 						 ("if_id %d sybphy_id %d bit %d l2h %d h2l %d\n",
13652b4ffbf6SChris Packham 						 if_id, sybphy_id, bit_id, l2h_adll_value[sybphy_id][bit_id],
13662b4ffbf6SChris Packham 						 h2l_adll_value[sybphy_id][bit_id]));
13672b4ffbf6SChris Packham 
13682b4ffbf6SChris Packham 					if (((l2h_adll_value[sybphy_id][bit_id] +
13692b4ffbf6SChris Packham 					      h2l_adll_value[sybphy_id][bit_id]) / 2) >
13702b4ffbf6SChris Packham 					      max_center_subphy_adll[sybphy_id])
13712b4ffbf6SChris Packham 						max_center_subphy_adll[sybphy_id] =
13722b4ffbf6SChris Packham 						(l2h_adll_value[sybphy_id][bit_id] +
13732b4ffbf6SChris Packham 						 h2l_adll_value[sybphy_id][bit_id]) / 2;
13742b4ffbf6SChris Packham 					if (((l2h_adll_value[sybphy_id][bit_id] +
13752b4ffbf6SChris Packham 					      h2l_adll_value[sybphy_id][bit_id]) / 2) <
13762b4ffbf6SChris Packham 					      min_center_subphy_adll[sybphy_id])
13772b4ffbf6SChris Packham 						min_center_subphy_adll[sybphy_id] =
13782b4ffbf6SChris Packham 						(l2h_adll_value[sybphy_id][bit_id] +
13792b4ffbf6SChris Packham 						 h2l_adll_value[sybphy_id][bit_id]) / 2;
13802b4ffbf6SChris Packham 				}
13812b4ffbf6SChris Packham 
13822b4ffbf6SChris Packham 				/* calculate the center of the current subphy */
13832b4ffbf6SChris Packham 				center_subphy_adll_window[sybphy_id] =
13842b4ffbf6SChris Packham 					max_center_subphy_adll[sybphy_id] -
13852b4ffbf6SChris Packham 					min_center_subphy_adll[sybphy_id];
13862b4ffbf6SChris Packham 				DEBUG_TRAINING_IP_ENGINE
13872b4ffbf6SChris Packham 					(DEBUG_LEVEL_TRACE,
13882b4ffbf6SChris Packham 					 ("if_id %d sybphy_id %d min center %d max center %d center %d\n",
13892b4ffbf6SChris Packham 					 if_id, sybphy_id, min_center_subphy_adll[sybphy_id],
13902b4ffbf6SChris Packham 					 max_center_subphy_adll[sybphy_id],
13912b4ffbf6SChris Packham 					 center_subphy_adll_window[sybphy_id]));
13922b4ffbf6SChris Packham 			}
13932b4ffbf6SChris Packham 		}
13942b4ffbf6SChris Packham 		/*
13952b4ffbf6SChris Packham 			* check byte state and fix bits state if needed
13962b4ffbf6SChris Packham 			* in case the level 1 and 2 above subphy results are
13972b4ffbf6SChris Packham 			* homogeneous continue to the next subphy
13982b4ffbf6SChris Packham 			*/
13992b4ffbf6SChris Packham 		for (sybphy_id = 0; sybphy_id < octets_per_if_num; sybphy_id++) {
14002b4ffbf6SChris Packham 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, sybphy_id);
14012b4ffbf6SChris Packham 			if ((byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_LOW) ||
14022b4ffbf6SChris Packham 			    (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_HIGH) ||
14032b4ffbf6SChris Packham 			    (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_IN) ||
14042b4ffbf6SChris Packham 			    (byte_status[if_id][sybphy_id] == BYTE_HOMOGENEOUS_SPLIT_OUT) ||
14052b4ffbf6SChris Packham 			    (byte_status[if_id][sybphy_id] == BYTE_NOT_DEFINED))
14062b4ffbf6SChris Packham 			continue;
14072b4ffbf6SChris Packham 
14082b4ffbf6SChris Packham 			/*
14092b4ffbf6SChris Packham 			 * in case all of the bits in the current subphy are
14102b4ffbf6SChris Packham 			 * less than 32 which will find alignment in the subphy bits
14112b4ffbf6SChris Packham 			 * mark this subphy as homogeneous split in
14122b4ffbf6SChris Packham 			*/
14132b4ffbf6SChris Packham 			if (center_subphy_adll_window[sybphy_id] <= 31)
14142b4ffbf6SChris Packham 				byte_status[if_id][sybphy_id] = BYTE_HOMOGENEOUS_SPLIT_IN;
14152b4ffbf6SChris Packham 
14162b4ffbf6SChris Packham 			/*
14172b4ffbf6SChris Packham 				* in case the current byte is split_out and the center is bigger than 31
14182b4ffbf6SChris Packham 				* the byte can be aligned. in this case add 64 to the the low ui bits aligning it
14192b4ffbf6SChris Packham 				* to the other ui bits
14202b4ffbf6SChris Packham 				*/
14212b4ffbf6SChris Packham 			if (center_subphy_adll_window[sybphy_id] >= 32) {
14222b4ffbf6SChris Packham 				byte_status[if_id][sybphy_id] = BYTE_SPLIT_OUT_MIX;
14232b4ffbf6SChris Packham 
14242b4ffbf6SChris Packham 				DEBUG_TRAINING_IP_ENGINE
14252b4ffbf6SChris Packham 					(DEBUG_LEVEL_TRACE,
14262b4ffbf6SChris Packham 					 ("if_id %d sybphy_id %d byte state 0x%x\n",
14272b4ffbf6SChris Packham 					 if_id, sybphy_id, byte_status[if_id][sybphy_id]));
14282b4ffbf6SChris Packham 				for (bit_id = 0; bit_id < bit_end; bit_id++) {
14292b4ffbf6SChris Packham 					if (bit_state[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] == BIT_LOW_UI) {
14302b4ffbf6SChris Packham 						l2h_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64;
14312b4ffbf6SChris Packham 						h2l_if_train_res[sybphy_id * BUS_WIDTH_IN_BITS + bit_id] += 64;
14322b4ffbf6SChris Packham 					}
14332b4ffbf6SChris Packham 					DEBUG_TRAINING_IP_ENGINE
14342b4ffbf6SChris Packham 						(DEBUG_LEVEL_TRACE,
14352b4ffbf6SChris Packham 						 ("if_id %d sybphy_id %d bit_id %d added 64 adlls\n",
14362b4ffbf6SChris Packham 						 if_id, sybphy_id, bit_id));
14372b4ffbf6SChris Packham 				}
14382b4ffbf6SChris Packham 			}
14392b4ffbf6SChris Packham 		}
14402b4ffbf6SChris Packham 	} /* for all interfaces */
1441f1df9364SStefan Roese 
1442f1df9364SStefan Roese 	return MV_OK;
1443f1df9364SStefan Roese }
1444f1df9364SStefan Roese 
mv_ddr_tip_sub_phy_byte_status_get(u32 if_id,u32 subphy_id)14452b4ffbf6SChris Packham u8 mv_ddr_tip_sub_phy_byte_status_get(u32 if_id, u32 subphy_id)
14462b4ffbf6SChris Packham {
14472b4ffbf6SChris Packham 	return byte_status[if_id][subphy_id];
14482b4ffbf6SChris Packham }
14492b4ffbf6SChris Packham 
mv_ddr_tip_sub_phy_byte_status_set(u32 if_id,u32 subphy_id,u8 byte_status_data)14502b4ffbf6SChris Packham void mv_ddr_tip_sub_phy_byte_status_set(u32 if_id, u32 subphy_id, u8 byte_status_data)
14512b4ffbf6SChris Packham {
14522b4ffbf6SChris Packham 	byte_status[if_id][subphy_id] = byte_status_data;
14532b4ffbf6SChris Packham }
14542b4ffbf6SChris Packham 
1455f1df9364SStefan Roese /*
1456f1df9364SStefan Roese  * Load phy values
1457f1df9364SStefan Roese  */
ddr3_tip_load_phy_values(int b_load)1458f1df9364SStefan Roese int ddr3_tip_load_phy_values(int b_load)
1459f1df9364SStefan Roese {
1460f1df9364SStefan Roese 	u32 bus_cnt = 0, if_id, dev_num = 0;
14612b4ffbf6SChris Packham 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
14622b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1463f1df9364SStefan Roese 
1464f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
14652b4ffbf6SChris Packham 		VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
14662b4ffbf6SChris Packham 		for (bus_cnt = 0; bus_cnt < octets_per_if_num; bus_cnt++) {
14672b4ffbf6SChris Packham 			VALIDATE_BUS_ACTIVE(tm->bus_act_mask, bus_cnt);
1468f1df9364SStefan Roese 			if (b_load == 1) {
1469f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_read
1470f1df9364SStefan Roese 					     (dev_num, if_id,
1471f1df9364SStefan Roese 					      ACCESS_TYPE_UNICAST, bus_cnt,
1472f1df9364SStefan Roese 					      DDR_PHY_DATA,
14732b4ffbf6SChris Packham 					      CTX_PHY_REG(effective_cs),
1474f1df9364SStefan Roese 					      &phy_reg_bk[if_id][bus_cnt]
1475f1df9364SStefan Roese 					      [0]));
1476f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_read
1477f1df9364SStefan Roese 					     (dev_num, if_id,
1478f1df9364SStefan Roese 					      ACCESS_TYPE_UNICAST, bus_cnt,
1479f1df9364SStefan Roese 					      DDR_PHY_DATA,
14802b4ffbf6SChris Packham 					      RL_PHY_REG(effective_cs),
1481f1df9364SStefan Roese 					      &phy_reg_bk[if_id][bus_cnt]
1482f1df9364SStefan Roese 					      [1]));
1483f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_read
1484f1df9364SStefan Roese 					     (dev_num, if_id,
1485f1df9364SStefan Roese 					      ACCESS_TYPE_UNICAST, bus_cnt,
1486f1df9364SStefan Roese 					      DDR_PHY_DATA,
14872b4ffbf6SChris Packham 					      CRX_PHY_REG(effective_cs),
1488f1df9364SStefan Roese 					      &phy_reg_bk[if_id][bus_cnt]
1489f1df9364SStefan Roese 					      [2]));
1490f1df9364SStefan Roese 			} else {
1491f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_write
1492f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
1493f1df9364SStefan Roese 					      if_id, ACCESS_TYPE_UNICAST,
1494f1df9364SStefan Roese 					      bus_cnt, DDR_PHY_DATA,
14952b4ffbf6SChris Packham 					      CTX_PHY_REG(effective_cs),
1496f1df9364SStefan Roese 					      phy_reg_bk[if_id][bus_cnt]
1497f1df9364SStefan Roese 					      [0]));
1498f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_write
1499f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
1500f1df9364SStefan Roese 					      if_id, ACCESS_TYPE_UNICAST,
1501f1df9364SStefan Roese 					      bus_cnt, DDR_PHY_DATA,
15022b4ffbf6SChris Packham 					      RL_PHY_REG(effective_cs),
1503f1df9364SStefan Roese 					      phy_reg_bk[if_id][bus_cnt]
1504f1df9364SStefan Roese 					      [1]));
1505f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_write
1506f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
1507f1df9364SStefan Roese 					      if_id, ACCESS_TYPE_UNICAST,
1508f1df9364SStefan Roese 					      bus_cnt, DDR_PHY_DATA,
15092b4ffbf6SChris Packham 					      CRX_PHY_REG(effective_cs),
1510f1df9364SStefan Roese 					      phy_reg_bk[if_id][bus_cnt]
1511f1df9364SStefan Roese 					      [2]));
1512f1df9364SStefan Roese 			}
1513f1df9364SStefan Roese 		}
1514f1df9364SStefan Roese 	}
1515f1df9364SStefan Roese 
1516f1df9364SStefan Roese 	return MV_OK;
1517f1df9364SStefan Roese }
1518f1df9364SStefan Roese 
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)1519f1df9364SStefan Roese int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
1520f1df9364SStefan Roese 			      enum hws_search_dir search_dir,
1521f1df9364SStefan Roese 			      enum hws_dir direction,
1522f1df9364SStefan Roese 			      enum hws_edge_compare edge,
1523f1df9364SStefan Roese 			      u32 init_val1, u32 init_val2,
1524f1df9364SStefan Roese 			      u32 num_of_iterations,
1525f1df9364SStefan Roese 			      u32 start_pattern, u32 end_pattern)
1526f1df9364SStefan Roese {
1527f1df9364SStefan Roese 	u32 pattern, if_id, pup_id;
1528f1df9364SStefan Roese 	enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
1529f1df9364SStefan Roese 	u32 *res = NULL;
1530f1df9364SStefan Roese 	u32 search_state = 0;
15312b4ffbf6SChris Packham 	u32 octets_per_if_num = ddr3_tip_dev_attr_get(dev_num, MV_ATTR_OCTET_PER_INTERFACE);
15322b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1533f1df9364SStefan Roese 
1534f1df9364SStefan Roese 	ddr3_tip_load_phy_values(1);
1535f1df9364SStefan Roese 
1536f1df9364SStefan Roese 	for (pattern = start_pattern; pattern <= end_pattern; pattern++) {
1537f1df9364SStefan Roese 		for (search_state = 0; search_state < HWS_SEARCH_DIR_LIMIT;
1538f1df9364SStefan Roese 		     search_state++) {
1539f1df9364SStefan Roese 			ddr3_tip_ip_training_wrapper(dev_num,
1540f1df9364SStefan Roese 						     ACCESS_TYPE_MULTICAST, 0,
1541f1df9364SStefan Roese 						     ACCESS_TYPE_MULTICAST, 0,
1542f1df9364SStefan Roese 						     result_type,
1543f1df9364SStefan Roese 						     HWS_CONTROL_ELEMENT_ADLL,
1544f1df9364SStefan Roese 						     search_dir, direction,
1545f1df9364SStefan Roese 						     0xfff, init_val1,
1546f1df9364SStefan Roese 						     init_val2,
1547f1df9364SStefan Roese 						     num_of_iterations, pattern,
1548f1df9364SStefan Roese 						     edge, CS_SINGLE,
1549f1df9364SStefan Roese 						     PARAM_NOT_CARE,
1550f1df9364SStefan Roese 						     train_status);
1551f1df9364SStefan Roese 
1552f1df9364SStefan Roese 			for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
1553f1df9364SStefan Roese 			     if_id++) {
15542b4ffbf6SChris Packham 				VALIDATE_IF_ACTIVE(tm->if_act_mask, if_id);
1555f1df9364SStefan Roese 				for (pup_id = 0; pup_id <
15562b4ffbf6SChris Packham 					     octets_per_if_num;
1557f1df9364SStefan Roese 				     pup_id++) {
15582b4ffbf6SChris Packham 					VALIDATE_BUS_ACTIVE(tm->bus_act_mask,
1559f1df9364SStefan Roese 							pup_id);
1560f1df9364SStefan Roese 					CHECK_STATUS
1561f1df9364SStefan Roese 						(ddr3_tip_read_training_result
1562f1df9364SStefan Roese 						 (dev_num, if_id,
1563f1df9364SStefan Roese 						  ACCESS_TYPE_UNICAST, pup_id,
1564f1df9364SStefan Roese 						  ALL_BITS_PER_PUP,
1565f1df9364SStefan Roese 						  search_state,
1566f1df9364SStefan Roese 						  direction, result_type,
1567f1df9364SStefan Roese 						  TRAINING_LOAD_OPERATION_UNLOAD,
1568f1df9364SStefan Roese 						  CS_SINGLE, &res, 1, 0,
1569f1df9364SStefan Roese 						  0));
1570f1df9364SStefan Roese 					if (result_type == RESULT_PER_BYTE) {
1571f1df9364SStefan Roese 						DEBUG_TRAINING_IP_ENGINE
1572f1df9364SStefan Roese 							(DEBUG_LEVEL_INFO,
1573f1df9364SStefan Roese 							 ("search_state %d if_id %d pup_id %d 0x%x\n",
1574f1df9364SStefan Roese 							  search_state, if_id,
1575f1df9364SStefan Roese 							  pup_id, res[0]));
1576f1df9364SStefan Roese 					} else {
1577f1df9364SStefan Roese 						DEBUG_TRAINING_IP_ENGINE
1578f1df9364SStefan Roese 							(DEBUG_LEVEL_INFO,
1579f1df9364SStefan Roese 							 ("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",
1580f1df9364SStefan Roese 							  search_state, if_id,
1581f1df9364SStefan Roese 							  pup_id, res[0],
1582f1df9364SStefan Roese 							  res[1], res[2],
1583f1df9364SStefan Roese 							  res[3], res[4],
1584f1df9364SStefan Roese 							  res[5], res[6],
1585f1df9364SStefan Roese 							  res[7]));
1586f1df9364SStefan Roese 					}
1587f1df9364SStefan Roese 				}
1588f1df9364SStefan Roese 			}	/* interface */
1589f1df9364SStefan Roese 		}		/* search */
1590f1df9364SStefan Roese 	}			/* pattern */
1591f1df9364SStefan Roese 
1592f1df9364SStefan Roese 	ddr3_tip_load_phy_values(0);
1593f1df9364SStefan Roese 
1594f1df9364SStefan Roese 	return MV_OK;
1595f1df9364SStefan Roese }
1596f1df9364SStefan Roese 
mv_ddr_pattern_start_addr_set(struct pattern_info * pattern_tbl,enum hws_pattern pattern,u32 addr)15972b4ffbf6SChris Packham int mv_ddr_pattern_start_addr_set(struct pattern_info *pattern_tbl, enum hws_pattern pattern, u32 addr)
15982b4ffbf6SChris Packham {
15992b4ffbf6SChris Packham 	pattern_tbl[pattern].start_addr = addr;
16002b4ffbf6SChris Packham 
16012b4ffbf6SChris Packham 	return 0;
16022b4ffbf6SChris Packham }
16032b4ffbf6SChris Packham 
ddr3_tip_get_pattern_table()1604f1df9364SStefan Roese struct pattern_info *ddr3_tip_get_pattern_table()
1605f1df9364SStefan Roese {
16062b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1607f1df9364SStefan Roese 
16082b4ffbf6SChris Packham 	if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask))
16092b4ffbf6SChris Packham 		return pattern_table_64;
16102b4ffbf6SChris Packham 	else if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0)
1611f1df9364SStefan Roese 		return pattern_table_32;
1612f1df9364SStefan Roese 	else
1613f1df9364SStefan Roese 		return pattern_table_16;
1614f1df9364SStefan Roese }
1615f1df9364SStefan Roese 
ddr3_tip_get_mask_results_dq_reg()1616f1df9364SStefan Roese u16 *ddr3_tip_get_mask_results_dq_reg()
1617f1df9364SStefan Roese {
16182b4ffbf6SChris Packham #if MAX_BUS_NUM == 5
16192b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1620f1df9364SStefan Roese 
1621f1df9364SStefan Roese 	if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1622f1df9364SStefan Roese 		return mask_results_dq_reg_map_pup3_ecc;
1623f1df9364SStefan Roese 	else
16242b4ffbf6SChris Packham #endif
1625f1df9364SStefan Roese 		return mask_results_dq_reg_map;
1626f1df9364SStefan Roese }
1627f1df9364SStefan Roese 
ddr3_tip_get_mask_results_pup_reg_map()1628f1df9364SStefan Roese u16 *ddr3_tip_get_mask_results_pup_reg_map()
1629f1df9364SStefan Roese {
16302b4ffbf6SChris Packham #if MAX_BUS_NUM == 5
16312b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
1632f1df9364SStefan Roese 
1633f1df9364SStefan Roese 	if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1634f1df9364SStefan Roese 		return mask_results_pup_reg_map_pup3_ecc;
1635f1df9364SStefan Roese 	else
16362b4ffbf6SChris Packham #endif
1637f1df9364SStefan Roese 		return mask_results_pup_reg_map;
1638f1df9364SStefan Roese }
16392b4ffbf6SChris Packham 
16402b4ffbf6SChris Packham /* load expected dm pattern to odpg */
16412b4ffbf6SChris Packham #define LOW_NIBBLE_BYTE_MASK	0xf
16422b4ffbf6SChris Packham #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)16432b4ffbf6SChris Packham int mv_ddr_load_dm_pattern_to_odpg(enum hws_access_type access_type, enum hws_pattern pattern,
16442b4ffbf6SChris Packham 				   enum dm_direction dm_dir)
16452b4ffbf6SChris Packham {
16462b4ffbf6SChris Packham 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
16472b4ffbf6SChris Packham 	struct mv_ddr_topology_map *tm = mv_ddr_topology_map_get();
16482b4ffbf6SChris Packham 	u32 pattern_len = 0;
16492b4ffbf6SChris Packham 	u32 data_low, data_high;
16502b4ffbf6SChris Packham 	u8 dm_data;
16512b4ffbf6SChris Packham 
16522b4ffbf6SChris Packham 	for (pattern_len = 0;
16532b4ffbf6SChris Packham 	     pattern_len < pattern_table[pattern].pattern_len;
16542b4ffbf6SChris Packham 	     pattern_len++) {
16552b4ffbf6SChris Packham 		if (MV_DDR_IS_64BIT_DRAM_MODE(tm->bus_act_mask)) {
16562b4ffbf6SChris Packham 			data_low = pattern_table_get_word(0, pattern, (u8)pattern_len);
16572b4ffbf6SChris Packham 			data_high = data_low;
16582b4ffbf6SChris Packham 		} else {
16592b4ffbf6SChris Packham 			data_low = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2));
16602b4ffbf6SChris Packham 			data_high = pattern_table_get_word(0, pattern, (u8)(pattern_len * 2 + 1));
16612b4ffbf6SChris Packham 		}
16622b4ffbf6SChris Packham 
16632b4ffbf6SChris Packham 		/* odpg mbus dm definition is opposite to ddr4 protocol */
16642b4ffbf6SChris Packham 		if (dm_dir == DM_DIR_INVERSE)
16652b4ffbf6SChris Packham 			dm_data = ~((data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK));
16662b4ffbf6SChris Packham 		else
16672b4ffbf6SChris Packham 			dm_data = (data_low & LOW_NIBBLE_BYTE_MASK) | (data_high & HIGH_NIBBLE_BYTE_MASK);
16682b4ffbf6SChris Packham 
16692b4ffbf6SChris Packham 		ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_LOW_REG, data_low, MASK_ALL_BITS);
16702b4ffbf6SChris Packham 		ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_DATA_HIGH_REG, data_high, MASK_ALL_BITS);
16712b4ffbf6SChris Packham 		ddr3_tip_if_write(0, access_type, 0, ODPG_DATA_WR_ADDR_REG,
16722b4ffbf6SChris Packham 				  pattern_len | ((dm_data & ODPG_DATA_WR_DATA_MASK) << ODPG_DATA_WR_DATA_OFFS),
16732b4ffbf6SChris Packham 				  MASK_ALL_BITS);
16742b4ffbf6SChris Packham 	}
16752b4ffbf6SChris Packham 
16762b4ffbf6SChris Packham 	return MV_OK;
16772b4ffbf6SChris Packham }
1678