xref: /rk3399_rockchip-uboot/drivers/ddr/marvell/a38x/ddr3_training_ip_engine.c (revision 3c9cc70d7153da442575112d9a2643eecd17d534)
1*f1df9364SStefan Roese /*
2*f1df9364SStefan Roese  * Copyright (C) Marvell International Ltd. and its affiliates
3*f1df9364SStefan Roese  *
4*f1df9364SStefan Roese  * SPDX-License-Identifier:	GPL-2.0
5*f1df9364SStefan Roese  */
6*f1df9364SStefan Roese 
7*f1df9364SStefan Roese #include <common.h>
8*f1df9364SStefan Roese #include <spl.h>
9*f1df9364SStefan Roese #include <asm/io.h>
10*f1df9364SStefan Roese #include <asm/arch/cpu.h>
11*f1df9364SStefan Roese #include <asm/arch/soc.h>
12*f1df9364SStefan Roese 
13*f1df9364SStefan Roese #include "ddr3_init.h"
14*f1df9364SStefan Roese 
15*f1df9364SStefan Roese #define PATTERN_1	0x55555555
16*f1df9364SStefan Roese #define PATTERN_2	0xaaaaaaaa
17*f1df9364SStefan Roese 
18*f1df9364SStefan Roese #define VALIDATE_TRAINING_LIMIT(e1, e2)			\
19*f1df9364SStefan Roese 	((((e2) - (e1) + 1) > 33) && ((e1) < 67))
20*f1df9364SStefan Roese 
21*f1df9364SStefan Roese u32 phy_reg_bk[MAX_INTERFACE_NUM][MAX_BUS_NUM][BUS_WIDTH_IN_BITS];
22*f1df9364SStefan Roese 
23*f1df9364SStefan Roese u32 training_res[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS *
24*f1df9364SStefan Roese 		 HWS_SEARCH_DIR_LIMIT];
25*f1df9364SStefan Roese 
26*f1df9364SStefan Roese u16 mask_results_dq_reg_map[] = {
27*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
28*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
29*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
30*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
31*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
32*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
33*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
34*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
35*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
36*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
37*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
38*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
39*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_0_REG, RESULT_CONTROL_PUP_3_BIT_1_REG,
40*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_2_REG, RESULT_CONTROL_PUP_3_BIT_3_REG,
41*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_4_REG, RESULT_CONTROL_PUP_3_BIT_5_REG,
42*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_3_BIT_6_REG, RESULT_CONTROL_PUP_3_BIT_7_REG,
43*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
44*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
45*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
46*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
47*f1df9364SStefan Roese };
48*f1df9364SStefan Roese 
49*f1df9364SStefan Roese u16 mask_results_pup_reg_map[] = {
50*f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
51*f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_3_REG,
52*f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_4_REG
53*f1df9364SStefan Roese };
54*f1df9364SStefan Roese 
55*f1df9364SStefan Roese u16 mask_results_dq_reg_map_pup3_ecc[] = {
56*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_0_REG, RESULT_CONTROL_PUP_0_BIT_1_REG,
57*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_2_REG, RESULT_CONTROL_PUP_0_BIT_3_REG,
58*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_4_REG, RESULT_CONTROL_PUP_0_BIT_5_REG,
59*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_0_BIT_6_REG, RESULT_CONTROL_PUP_0_BIT_7_REG,
60*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_0_REG, RESULT_CONTROL_PUP_1_BIT_1_REG,
61*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_2_REG, RESULT_CONTROL_PUP_1_BIT_3_REG,
62*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_4_REG, RESULT_CONTROL_PUP_1_BIT_5_REG,
63*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_1_BIT_6_REG, RESULT_CONTROL_PUP_1_BIT_7_REG,
64*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_0_REG, RESULT_CONTROL_PUP_2_BIT_1_REG,
65*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_2_REG, RESULT_CONTROL_PUP_2_BIT_3_REG,
66*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_4_REG, RESULT_CONTROL_PUP_2_BIT_5_REG,
67*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_2_BIT_6_REG, RESULT_CONTROL_PUP_2_BIT_7_REG,
68*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
69*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
70*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
71*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
72*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_0_REG, RESULT_CONTROL_PUP_4_BIT_1_REG,
73*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_2_REG, RESULT_CONTROL_PUP_4_BIT_3_REG,
74*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_4_REG, RESULT_CONTROL_PUP_4_BIT_5_REG,
75*f1df9364SStefan Roese 	RESULT_CONTROL_PUP_4_BIT_6_REG, RESULT_CONTROL_PUP_4_BIT_7_REG,
76*f1df9364SStefan Roese };
77*f1df9364SStefan Roese 
78*f1df9364SStefan Roese u16 mask_results_pup_reg_map_pup3_ecc[] = {
79*f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_0_REG, RESULT_CONTROL_BYTE_PUP_1_REG,
80*f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_2_REG, RESULT_CONTROL_BYTE_PUP_4_REG,
81*f1df9364SStefan Roese 	RESULT_CONTROL_BYTE_PUP_4_REG
82*f1df9364SStefan Roese };
83*f1df9364SStefan Roese 
84*f1df9364SStefan Roese struct pattern_info pattern_table_16[] = {
85*f1df9364SStefan Roese 	/*
86*f1df9364SStefan Roese 	 * num tx phases, tx burst, delay between, rx pattern,
87*f1df9364SStefan Roese 	 * start_address, pattern_len
88*f1df9364SStefan Roese 	 */
89*f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0080, 2},	/* PATTERN_PBS1 */
90*f1df9364SStefan Roese 	{1, 1, 2, 1, 0x00c0, 2},	/* PATTERN_PBS2 */
91*f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0100, 2},	/* PATTERN_RL */
92*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0140, 16},	/* PATTERN_STATIC_PBS */
93*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0190, 16},	/* PATTERN_KILLER_DQ0 */
94*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x01d0, 16},	/* PATTERN_KILLER_DQ1 */
95*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0210, 16},	/* PATTERN_KILLER_DQ2 */
96*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0250, 16},	/* PATTERN_KILLER_DQ3 */
97*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0290, 16},	/* PATTERN_KILLER_DQ4 */
98*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x02d0, 16},	/* PATTERN_KILLER_DQ5 */
99*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0310, 16},	/* PATTERN_KILLER_DQ6 */
100*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0350, 16},	/* PATTERN_KILLER_DQ7 */
101*f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0380, 2},	/* PATTERN_PBS3 */
102*f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0000, 2},	/* PATTERN_RL2 */
103*f1df9364SStefan Roese 	{1, 1, 2, 1, 0x0040, 2},	/* PATTERN_TEST */
104*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x03c0, 16},	/* PATTERN_FULL_SSO_1T */
105*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0400, 16},	/* PATTERN_FULL_SSO_2T */
106*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0440, 16},	/* PATTERN_FULL_SSO_3T */
107*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x0480, 16},	/* PATTERN_FULL_SSO_4T */
108*f1df9364SStefan Roese 	{0xf, 0x7, 2, 0x7, 0x04c0, 16}	/* PATTERN_VREF */
109*f1df9364SStefan Roese 	/*Note: actual start_address is <<3 of defined addess */
110*f1df9364SStefan Roese };
111*f1df9364SStefan Roese 
112*f1df9364SStefan Roese struct pattern_info pattern_table_32[] = {
113*f1df9364SStefan Roese 	/*
114*f1df9364SStefan Roese 	 * num tx phases, tx burst, delay between, rx pattern,
115*f1df9364SStefan Roese 	 * start_address, pattern_len
116*f1df9364SStefan Roese 	 */
117*f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0080, 4},	/* PATTERN_PBS1 */
118*f1df9364SStefan Roese 	{3, 3, 2, 3, 0x00c0, 4},	/* PATTERN_PBS2 */
119*f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0100, 4},	/* PATTERN_RL */
120*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0140, 32},	/* PATTERN_STATIC_PBS */
121*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0190, 32},	/* PATTERN_KILLER_DQ0 */
122*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x01d0, 32},	/* PATTERN_KILLER_DQ1 */
123*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0210, 32},	/* PATTERN_KILLER_DQ2 */
124*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0250, 32},	/* PATTERN_KILLER_DQ3 */
125*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0290, 32},	/* PATTERN_KILLER_DQ4 */
126*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x02d0, 32},	/* PATTERN_KILLER_DQ5 */
127*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0310, 32},	/* PATTERN_KILLER_DQ6 */
128*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0350, 32},	/* PATTERN_KILLER_DQ7 */
129*f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0380, 4},	/* PATTERN_PBS3 */
130*f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0000, 4},	/* PATTERN_RL2 */
131*f1df9364SStefan Roese 	{3, 3, 2, 3, 0x0040, 4},	/* PATTERN_TEST */
132*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x03c0, 32},	/* PATTERN_FULL_SSO_1T */
133*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0400, 32},	/* PATTERN_FULL_SSO_2T */
134*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0440, 32},	/* PATTERN_FULL_SSO_3T */
135*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x0480, 32},	/* PATTERN_FULL_SSO_4T */
136*f1df9364SStefan Roese 	{0x1f, 0xf, 2, 0xf, 0x04c0, 32}	/* PATTERN_VREF */
137*f1df9364SStefan Roese 	/*Note: actual start_address is <<3 of defined addess */
138*f1df9364SStefan Roese };
139*f1df9364SStefan Roese 
140*f1df9364SStefan Roese u32 train_dev_num;
141*f1df9364SStefan Roese enum hws_ddr_cs traintrain_cs_type;
142*f1df9364SStefan Roese u32 train_pup_num;
143*f1df9364SStefan Roese enum hws_training_result train_result_type;
144*f1df9364SStefan Roese enum hws_control_element train_control_element;
145*f1df9364SStefan Roese enum hws_search_dir traine_search_dir;
146*f1df9364SStefan Roese enum hws_dir train_direction;
147*f1df9364SStefan Roese u32 train_if_select;
148*f1df9364SStefan Roese u32 train_init_value;
149*f1df9364SStefan Roese u32 train_number_iterations;
150*f1df9364SStefan Roese enum hws_pattern train_pattern;
151*f1df9364SStefan Roese enum hws_edge_compare train_edge_compare;
152*f1df9364SStefan Roese u32 train_cs_num;
153*f1df9364SStefan Roese u32 train_if_acess, train_if_id, train_pup_access;
154*f1df9364SStefan Roese u32 max_polling_for_done = 1000000;
155*f1df9364SStefan Roese 
ddr3_tip_get_buf_ptr(u32 dev_num,enum hws_search_dir search,enum hws_training_result result_type,u32 interface_num)156*f1df9364SStefan Roese u32 *ddr3_tip_get_buf_ptr(u32 dev_num, enum hws_search_dir search,
157*f1df9364SStefan Roese 			  enum hws_training_result result_type,
158*f1df9364SStefan Roese 			  u32 interface_num)
159*f1df9364SStefan Roese {
160*f1df9364SStefan Roese 	u32 *buf_ptr = NULL;
161*f1df9364SStefan Roese 
162*f1df9364SStefan Roese 	buf_ptr = &training_res
163*f1df9364SStefan Roese 		[MAX_INTERFACE_NUM * MAX_BUS_NUM * BUS_WIDTH_IN_BITS * search +
164*f1df9364SStefan Roese 		 interface_num * MAX_BUS_NUM * BUS_WIDTH_IN_BITS];
165*f1df9364SStefan Roese 
166*f1df9364SStefan Roese 	return buf_ptr;
167*f1df9364SStefan Roese }
168*f1df9364SStefan Roese 
169*f1df9364SStefan Roese /*
170*f1df9364SStefan Roese  * IP Training search
171*f1df9364SStefan Roese  * Note: for one edge search only from fail to pass, else jitter can
172*f1df9364SStefan Roese  * be be entered into solution.
173*f1df9364SStefan 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)174*f1df9364SStefan Roese int ddr3_tip_ip_training(u32 dev_num, enum hws_access_type access_type,
175*f1df9364SStefan Roese 			 u32 interface_num,
176*f1df9364SStefan Roese 			 enum hws_access_type pup_access_type,
177*f1df9364SStefan Roese 			 u32 pup_num, enum hws_training_result result_type,
178*f1df9364SStefan Roese 			 enum hws_control_element control_element,
179*f1df9364SStefan Roese 			 enum hws_search_dir search_dir, enum hws_dir direction,
180*f1df9364SStefan Roese 			 u32 interface_mask, u32 init_value, u32 num_iter,
181*f1df9364SStefan Roese 			 enum hws_pattern pattern,
182*f1df9364SStefan Roese 			 enum hws_edge_compare edge_comp,
183*f1df9364SStefan Roese 			 enum hws_ddr_cs cs_type, u32 cs_num,
184*f1df9364SStefan Roese 			 enum hws_training_ip_stat *train_status)
185*f1df9364SStefan Roese {
186*f1df9364SStefan Roese 	u32 mask_dq_num_of_regs, mask_pup_num_of_regs, index_cnt, poll_cnt,
187*f1df9364SStefan Roese 		reg_data, pup_id;
188*f1df9364SStefan Roese 	u32 tx_burst_size;
189*f1df9364SStefan Roese 	u32 delay_between_burst;
190*f1df9364SStefan Roese 	u32 rd_mode;
191*f1df9364SStefan Roese 	u32 read_data[MAX_INTERFACE_NUM];
192*f1df9364SStefan Roese 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
193*f1df9364SStefan Roese 	u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
194*f1df9364SStefan Roese 	u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
195*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
196*f1df9364SStefan Roese 
197*f1df9364SStefan Roese 	if (pup_num >= tm->num_of_bus_per_interface) {
198*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
199*f1df9364SStefan Roese 					 ("pup_num %d not valid\n", pup_num));
200*f1df9364SStefan Roese 	}
201*f1df9364SStefan Roese 	if (interface_num >= MAX_INTERFACE_NUM) {
202*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
203*f1df9364SStefan Roese 					 ("if_id %d not valid\n",
204*f1df9364SStefan Roese 					  interface_num));
205*f1df9364SStefan Roese 	}
206*f1df9364SStefan Roese 	if (train_status == NULL) {
207*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
208*f1df9364SStefan Roese 					 ("error param 4\n"));
209*f1df9364SStefan Roese 		return MV_BAD_PARAM;
210*f1df9364SStefan Roese 	}
211*f1df9364SStefan Roese 
212*f1df9364SStefan Roese 	/* load pattern */
213*f1df9364SStefan Roese 	if (cs_type == CS_SINGLE) {
214*f1df9364SStefan Roese 		/* All CSs to CS0     */
215*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
216*f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
217*f1df9364SStefan Roese 			      CS_ENABLE_REG, 1 << 3, 1 << 3));
218*f1df9364SStefan Roese 		/* All CSs to CS0     */
219*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
220*f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
221*f1df9364SStefan Roese 			      ODPG_DATA_CONTROL_REG,
222*f1df9364SStefan Roese 			      (0x3 | (effective_cs << 26)), 0xc000003));
223*f1df9364SStefan Roese 	} else {
224*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
225*f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
226*f1df9364SStefan Roese 			      CS_ENABLE_REG, 0, 1 << 3));
227*f1df9364SStefan Roese 		/*  CS select */
228*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
229*f1df9364SStefan Roese 			     (dev_num, access_type, interface_num,
230*f1df9364SStefan Roese 			      ODPG_DATA_CONTROL_REG, 0x3 | cs_num << 26,
231*f1df9364SStefan Roese 			      0x3 | 3 << 26));
232*f1df9364SStefan Roese 	}
233*f1df9364SStefan Roese 
234*f1df9364SStefan Roese 	/* load pattern to ODPG */
235*f1df9364SStefan Roese 	ddr3_tip_load_pattern_to_odpg(dev_num, access_type, interface_num,
236*f1df9364SStefan Roese 				      pattern,
237*f1df9364SStefan Roese 				      pattern_table[pattern].start_addr);
238*f1df9364SStefan Roese 	tx_burst_size =	(direction == OPER_WRITE) ?
239*f1df9364SStefan Roese 		pattern_table[pattern].tx_burst_size : 0;
240*f1df9364SStefan Roese 	delay_between_burst = (direction == OPER_WRITE) ? 2 : 0;
241*f1df9364SStefan Roese 	rd_mode = (direction == OPER_WRITE) ? 1 : 0;
242*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_configure_odpg
243*f1df9364SStefan Roese 		     (dev_num, access_type, interface_num, direction,
244*f1df9364SStefan Roese 		      pattern_table[pattern].num_of_phases_tx, tx_burst_size,
245*f1df9364SStefan Roese 		      pattern_table[pattern].num_of_phases_rx,
246*f1df9364SStefan Roese 		      delay_between_burst, rd_mode, effective_cs, STRESS_NONE,
247*f1df9364SStefan Roese 		      DURATION_SINGLE));
248*f1df9364SStefan Roese 	reg_data = (direction == OPER_READ) ? 0 : (0x3 << 30);
249*f1df9364SStefan Roese 	reg_data |= (direction == OPER_READ) ? 0x60 : 0xfa;
250*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
251*f1df9364SStefan Roese 		     (dev_num, access_type, interface_num,
252*f1df9364SStefan Roese 		      ODPG_WRITE_READ_MODE_ENABLE_REG, reg_data,
253*f1df9364SStefan Roese 		      MASK_ALL_BITS));
254*f1df9364SStefan Roese 	reg_data = (edge_comp == EDGE_PF || edge_comp == EDGE_FP) ? 0 : 1 << 6;
255*f1df9364SStefan Roese 	reg_data |= (edge_comp == EDGE_PF || edge_comp == EDGE_PFP) ?
256*f1df9364SStefan Roese 		(1 << 7) : 0;
257*f1df9364SStefan Roese 
258*f1df9364SStefan Roese 	/* change from Pass to Fail will lock the result */
259*f1df9364SStefan Roese 	if (pup_access_type == ACCESS_TYPE_MULTICAST)
260*f1df9364SStefan Roese 		reg_data |= 0xe << 14;
261*f1df9364SStefan Roese 	else
262*f1df9364SStefan Roese 		reg_data |= pup_num << 14;
263*f1df9364SStefan Roese 
264*f1df9364SStefan Roese 	if (edge_comp == EDGE_FP) {
265*f1df9364SStefan Roese 		/* don't search for readl edge change, only the state */
266*f1df9364SStefan Roese 		reg_data |= (0 << 20);
267*f1df9364SStefan Roese 	} else if (edge_comp == EDGE_FPF) {
268*f1df9364SStefan Roese 		reg_data |= (0 << 20);
269*f1df9364SStefan Roese 	} else {
270*f1df9364SStefan Roese 		reg_data |= (3 << 20);
271*f1df9364SStefan Roese 	}
272*f1df9364SStefan Roese 
273*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
274*f1df9364SStefan Roese 		     (dev_num, access_type, interface_num,
275*f1df9364SStefan Roese 		      ODPG_TRAINING_CONTROL_REG,
276*f1df9364SStefan Roese 		      reg_data | (0x7 << 8) | (0x7 << 11),
277*f1df9364SStefan Roese 		      (0x3 | (0x3 << 2) | (0x3 << 6) | (1 << 5) | (0x7 << 8) |
278*f1df9364SStefan Roese 		       (0x7 << 11) | (0xf << 14) | (0x3 << 18) | (3 << 20))));
279*f1df9364SStefan Roese 	reg_data = (search_dir == HWS_LOW2HIGH) ? 0 : (1 << 8);
280*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
281*f1df9364SStefan Roese 		     (dev_num, access_type, interface_num, ODPG_OBJ1_OPCODE_REG,
282*f1df9364SStefan Roese 		      1 | reg_data | init_value << 9 | (1 << 25) | (1 << 26),
283*f1df9364SStefan Roese 		      0xff | (1 << 8) | (0xffff << 9) | (1 << 25) | (1 << 26)));
284*f1df9364SStefan Roese 
285*f1df9364SStefan Roese 	/*
286*f1df9364SStefan Roese 	 * Write2_dunit(0x10b4, Number_iteration , [15:0])
287*f1df9364SStefan Roese 	 * Max number of iterations
288*f1df9364SStefan Roese 	 */
289*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
290*f1df9364SStefan Roese 				       ODPG_OBJ1_ITER_CNT_REG, num_iter,
291*f1df9364SStefan Roese 				       0xffff));
292*f1df9364SStefan Roese 	if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
293*f1df9364SStefan Roese 	    direction == OPER_READ) {
294*f1df9364SStefan Roese 		/*
295*f1df9364SStefan Roese 		 * Write2_dunit(0x10c0, 0x5f , [7:0])
296*f1df9364SStefan Roese 		 * MC PBS Reg Address at DDR PHY
297*f1df9364SStefan Roese 		 */
298*f1df9364SStefan Roese 		reg_data = 0x5f +
299*f1df9364SStefan Roese 			effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET;
300*f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_DQ_SKEW &&
301*f1df9364SStefan Roese 		   direction == OPER_WRITE) {
302*f1df9364SStefan Roese 		reg_data = 0x1f +
303*f1df9364SStefan Roese 			effective_cs * CALIBRATED_OBJECTS_REG_ADDR_OFFSET;
304*f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
305*f1df9364SStefan Roese 		   direction == OPER_WRITE) {
306*f1df9364SStefan Roese 		/*
307*f1df9364SStefan Roese 		 * LOOP         0x00000001 + 4*n:
308*f1df9364SStefan Roese 		 * where n (0-3) represents M_CS number
309*f1df9364SStefan Roese 		 */
310*f1df9364SStefan Roese 		/*
311*f1df9364SStefan Roese 		 * Write2_dunit(0x10c0, 0x1 , [7:0])
312*f1df9364SStefan Roese 		 * ADLL WR Reg Address at DDR PHY
313*f1df9364SStefan Roese 		 */
314*f1df9364SStefan Roese 		reg_data = 1 + effective_cs * CS_REGISTER_ADDR_OFFSET;
315*f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_ADLL &&
316*f1df9364SStefan Roese 		   direction == OPER_READ) {
317*f1df9364SStefan Roese 		/* ADLL RD Reg Address at DDR PHY */
318*f1df9364SStefan Roese 		reg_data = 3 + effective_cs * CS_REGISTER_ADDR_OFFSET;
319*f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
320*f1df9364SStefan Roese 		   direction == OPER_WRITE) {
321*f1df9364SStefan Roese 		/* TBD not defined in 0.5.0 requirement  */
322*f1df9364SStefan Roese 	} else if (control_element == HWS_CONTROL_ELEMENT_DQS_SKEW &&
323*f1df9364SStefan Roese 		   direction == OPER_READ) {
324*f1df9364SStefan Roese 		/* TBD not defined in 0.5.0 requirement */
325*f1df9364SStefan Roese 	}
326*f1df9364SStefan Roese 
327*f1df9364SStefan Roese 	reg_data |= (0x6 << 28);
328*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
329*f1df9364SStefan Roese 		     (dev_num, access_type, interface_num, CALIB_OBJ_PRFA_REG,
330*f1df9364SStefan Roese 		      reg_data | (init_value << 8),
331*f1df9364SStefan Roese 		      0xff | (0xffff << 8) | (0xf << 24) | (u32) (0xf << 28)));
332*f1df9364SStefan Roese 
333*f1df9364SStefan Roese 	mask_dq_num_of_regs = tm->num_of_bus_per_interface * BUS_WIDTH_IN_BITS;
334*f1df9364SStefan Roese 	mask_pup_num_of_regs = tm->num_of_bus_per_interface;
335*f1df9364SStefan Roese 
336*f1df9364SStefan Roese 	if (result_type == RESULT_PER_BIT) {
337*f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
338*f1df9364SStefan Roese 		     index_cnt++) {
339*f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
340*f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
341*f1df9364SStefan Roese 				      mask_results_dq_reg_map[index_cnt], 0,
342*f1df9364SStefan Roese 				      1 << 24));
343*f1df9364SStefan Roese 		}
344*f1df9364SStefan Roese 
345*f1df9364SStefan Roese 		/* Mask disabled buses */
346*f1df9364SStefan Roese 		for (pup_id = 0; pup_id < tm->num_of_bus_per_interface;
347*f1df9364SStefan Roese 		     pup_id++) {
348*f1df9364SStefan Roese 			if (IS_ACTIVE(tm->bus_act_mask, pup_id) == 1)
349*f1df9364SStefan Roese 				continue;
350*f1df9364SStefan Roese 
351*f1df9364SStefan Roese 			for (index_cnt = (mask_dq_num_of_regs - pup_id * 8);
352*f1df9364SStefan Roese 			     index_cnt <
353*f1df9364SStefan Roese 				     (mask_dq_num_of_regs - (pup_id + 1) * 8);
354*f1df9364SStefan Roese 			     index_cnt++) {
355*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_if_write
356*f1df9364SStefan Roese 					     (dev_num, access_type,
357*f1df9364SStefan Roese 					      interface_num,
358*f1df9364SStefan Roese 					      mask_results_dq_reg_map
359*f1df9364SStefan Roese 					      [index_cnt], (1 << 24), 1 << 24));
360*f1df9364SStefan Roese 			}
361*f1df9364SStefan Roese 		}
362*f1df9364SStefan Roese 
363*f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
364*f1df9364SStefan Roese 		     index_cnt++) {
365*f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
366*f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
367*f1df9364SStefan Roese 				      mask_results_pup_reg_map[index_cnt],
368*f1df9364SStefan Roese 				      (1 << 24), 1 << 24));
369*f1df9364SStefan Roese 		}
370*f1df9364SStefan Roese 	} else if (result_type == RESULT_PER_BYTE) {
371*f1df9364SStefan Roese 		/* write to adll */
372*f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_pup_num_of_regs;
373*f1df9364SStefan Roese 		     index_cnt++) {
374*f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
375*f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
376*f1df9364SStefan Roese 				      mask_results_pup_reg_map[index_cnt], 0,
377*f1df9364SStefan Roese 				      1 << 24));
378*f1df9364SStefan Roese 		}
379*f1df9364SStefan Roese 		for (index_cnt = 0; index_cnt < mask_dq_num_of_regs;
380*f1df9364SStefan Roese 		     index_cnt++) {
381*f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_if_write
382*f1df9364SStefan Roese 				     (dev_num, access_type, interface_num,
383*f1df9364SStefan Roese 				      mask_results_dq_reg_map[index_cnt],
384*f1df9364SStefan Roese 				      (1 << 24), (1 << 24)));
385*f1df9364SStefan Roese 		}
386*f1df9364SStefan Roese 	}
387*f1df9364SStefan Roese 
388*f1df9364SStefan Roese 	/* Start Training Trigger */
389*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write(dev_num, access_type, interface_num,
390*f1df9364SStefan Roese 				       ODPG_TRAINING_TRIGGER_REG, 1, 1));
391*f1df9364SStefan Roese 	/* wait for all RFU tests to finish (or timeout) */
392*f1df9364SStefan Roese 	/* WA for 16 bit mode, more investigation needed */
393*f1df9364SStefan Roese 	mdelay(1);
394*f1df9364SStefan Roese 
395*f1df9364SStefan Roese 	/* Training "Done ?" */
396*f1df9364SStefan Roese 	for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) {
397*f1df9364SStefan Roese 		if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0)
398*f1df9364SStefan Roese 			continue;
399*f1df9364SStefan Roese 
400*f1df9364SStefan Roese 		if (interface_mask & (1 << index_cnt)) {
401*f1df9364SStefan Roese 			/* need to check results for this Dunit */
402*f1df9364SStefan Roese 			for (poll_cnt = 0; poll_cnt < max_polling_for_done;
403*f1df9364SStefan Roese 			     poll_cnt++) {
404*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_if_read
405*f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
406*f1df9364SStefan Roese 					      index_cnt,
407*f1df9364SStefan Roese 					      ODPG_TRAINING_STATUS_REG,
408*f1df9364SStefan Roese 					      &reg_data, MASK_ALL_BITS));
409*f1df9364SStefan Roese 				if ((reg_data & 0x2) != 0) {
410*f1df9364SStefan Roese 					/*done */
411*f1df9364SStefan Roese 					train_status[index_cnt] =
412*f1df9364SStefan Roese 						HWS_TRAINING_IP_STATUS_SUCCESS;
413*f1df9364SStefan Roese 					break;
414*f1df9364SStefan Roese 				}
415*f1df9364SStefan Roese 			}
416*f1df9364SStefan Roese 
417*f1df9364SStefan Roese 			if (poll_cnt == max_polling_for_done) {
418*f1df9364SStefan Roese 				train_status[index_cnt] =
419*f1df9364SStefan Roese 					HWS_TRAINING_IP_STATUS_TIMEOUT;
420*f1df9364SStefan Roese 			}
421*f1df9364SStefan Roese 		}
422*f1df9364SStefan Roese 		/* Be sure that ODPG done */
423*f1df9364SStefan Roese 		CHECK_STATUS(is_odpg_access_done(dev_num, index_cnt));
424*f1df9364SStefan Roese 	}
425*f1df9364SStefan Roese 
426*f1df9364SStefan Roese 	/* Write ODPG done in Dunit */
427*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
428*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
429*f1df9364SStefan Roese 		      ODPG_STATUS_DONE_REG, 0, 0x1));
430*f1df9364SStefan Roese 
431*f1df9364SStefan Roese 	/* wait for all Dunit tests to finish (or timeout) */
432*f1df9364SStefan Roese 	/* Training "Done ?" */
433*f1df9364SStefan Roese 	/* Training "Pass ?" */
434*f1df9364SStefan Roese 	for (index_cnt = 0; index_cnt < MAX_INTERFACE_NUM; index_cnt++) {
435*f1df9364SStefan Roese 		if (IS_ACTIVE(tm->if_act_mask, index_cnt) == 0)
436*f1df9364SStefan Roese 			continue;
437*f1df9364SStefan Roese 
438*f1df9364SStefan Roese 		if (interface_mask & (1 << index_cnt)) {
439*f1df9364SStefan Roese 			/* need to check results for this Dunit */
440*f1df9364SStefan Roese 			for (poll_cnt = 0; poll_cnt < max_polling_for_done;
441*f1df9364SStefan Roese 			     poll_cnt++) {
442*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_if_read
443*f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
444*f1df9364SStefan Roese 					      index_cnt,
445*f1df9364SStefan Roese 					      ODPG_TRAINING_TRIGGER_REG,
446*f1df9364SStefan Roese 					      read_data, MASK_ALL_BITS));
447*f1df9364SStefan Roese 				reg_data = read_data[index_cnt];
448*f1df9364SStefan Roese 				if ((reg_data & 0x2) != 0) {
449*f1df9364SStefan Roese 					/* done */
450*f1df9364SStefan Roese 					if ((reg_data & 0x4) == 0) {
451*f1df9364SStefan Roese 						train_status[index_cnt] =
452*f1df9364SStefan Roese 							HWS_TRAINING_IP_STATUS_SUCCESS;
453*f1df9364SStefan Roese 					} else {
454*f1df9364SStefan Roese 						train_status[index_cnt] =
455*f1df9364SStefan Roese 							HWS_TRAINING_IP_STATUS_FAIL;
456*f1df9364SStefan Roese 					}
457*f1df9364SStefan Roese 					break;
458*f1df9364SStefan Roese 				}
459*f1df9364SStefan Roese 			}
460*f1df9364SStefan Roese 
461*f1df9364SStefan Roese 			if (poll_cnt == max_polling_for_done) {
462*f1df9364SStefan Roese 				train_status[index_cnt] =
463*f1df9364SStefan Roese 					HWS_TRAINING_IP_STATUS_TIMEOUT;
464*f1df9364SStefan Roese 			}
465*f1df9364SStefan Roese 		}
466*f1df9364SStefan Roese 	}
467*f1df9364SStefan Roese 
468*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
469*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
470*f1df9364SStefan Roese 		      ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS));
471*f1df9364SStefan Roese 
472*f1df9364SStefan Roese 	return MV_OK;
473*f1df9364SStefan Roese }
474*f1df9364SStefan Roese 
475*f1df9364SStefan Roese /*
476*f1df9364SStefan Roese  * Load expected Pattern to ODPG
477*f1df9364SStefan 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)478*f1df9364SStefan Roese int ddr3_tip_load_pattern_to_odpg(u32 dev_num, enum hws_access_type access_type,
479*f1df9364SStefan Roese 				  u32 if_id, enum hws_pattern pattern,
480*f1df9364SStefan Roese 				  u32 load_addr)
481*f1df9364SStefan Roese {
482*f1df9364SStefan Roese 	u32 pattern_length_cnt = 0;
483*f1df9364SStefan Roese 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
484*f1df9364SStefan Roese 
485*f1df9364SStefan Roese 	for (pattern_length_cnt = 0;
486*f1df9364SStefan Roese 	     pattern_length_cnt < pattern_table[pattern].pattern_len;
487*f1df9364SStefan Roese 	     pattern_length_cnt++) {
488*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
489*f1df9364SStefan Roese 			     (dev_num, access_type, if_id,
490*f1df9364SStefan Roese 			      ODPG_PATTERN_DATA_LOW_REG,
491*f1df9364SStefan Roese 			      pattern_table_get_word(dev_num, pattern,
492*f1df9364SStefan Roese 						     (u8) (pattern_length_cnt *
493*f1df9364SStefan Roese 							   2)), MASK_ALL_BITS));
494*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
495*f1df9364SStefan Roese 			     (dev_num, access_type, if_id,
496*f1df9364SStefan Roese 			      ODPG_PATTERN_DATA_HI_REG,
497*f1df9364SStefan Roese 			      pattern_table_get_word(dev_num, pattern,
498*f1df9364SStefan Roese 						     (u8) (pattern_length_cnt *
499*f1df9364SStefan Roese 							   2 + 1)),
500*f1df9364SStefan Roese 			      MASK_ALL_BITS));
501*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
502*f1df9364SStefan Roese 			     (dev_num, access_type, if_id,
503*f1df9364SStefan Roese 			      ODPG_PATTERN_ADDR_REG, pattern_length_cnt,
504*f1df9364SStefan Roese 			      MASK_ALL_BITS));
505*f1df9364SStefan Roese 	}
506*f1df9364SStefan Roese 
507*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
508*f1df9364SStefan Roese 		     (dev_num, access_type, if_id,
509*f1df9364SStefan Roese 		      ODPG_PATTERN_ADDR_OFFSET_REG, load_addr, MASK_ALL_BITS));
510*f1df9364SStefan Roese 
511*f1df9364SStefan Roese 	return MV_OK;
512*f1df9364SStefan Roese }
513*f1df9364SStefan Roese 
514*f1df9364SStefan Roese /*
515*f1df9364SStefan Roese  * Configure ODPG
516*f1df9364SStefan 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)517*f1df9364SStefan Roese int ddr3_tip_configure_odpg(u32 dev_num, enum hws_access_type access_type,
518*f1df9364SStefan Roese 			    u32 if_id, enum hws_dir direction, u32 tx_phases,
519*f1df9364SStefan Roese 			    u32 tx_burst_size, u32 rx_phases,
520*f1df9364SStefan Roese 			    u32 delay_between_burst, u32 rd_mode, u32 cs_num,
521*f1df9364SStefan Roese 			    u32 addr_stress_jump, u32 single_pattern)
522*f1df9364SStefan Roese {
523*f1df9364SStefan Roese 	u32 data_value = 0;
524*f1df9364SStefan Roese 	int ret;
525*f1df9364SStefan Roese 
526*f1df9364SStefan Roese 	data_value = ((single_pattern << 2) | (tx_phases << 5) |
527*f1df9364SStefan Roese 		      (tx_burst_size << 11) | (delay_between_burst << 15) |
528*f1df9364SStefan Roese 		      (rx_phases << 21) | (rd_mode << 25) | (cs_num << 26) |
529*f1df9364SStefan Roese 		      (addr_stress_jump << 29));
530*f1df9364SStefan Roese 	ret = ddr3_tip_if_write(dev_num, access_type, if_id,
531*f1df9364SStefan Roese 				ODPG_DATA_CONTROL_REG, data_value, 0xaffffffc);
532*f1df9364SStefan Roese 	if (ret != MV_OK)
533*f1df9364SStefan Roese 		return ret;
534*f1df9364SStefan Roese 
535*f1df9364SStefan Roese 	return MV_OK;
536*f1df9364SStefan Roese }
537*f1df9364SStefan Roese 
ddr3_tip_process_result(u32 * ar_result,enum hws_edge e_edge,enum hws_edge_search e_edge_search,u32 * edge_result)538*f1df9364SStefan Roese int ddr3_tip_process_result(u32 *ar_result, enum hws_edge e_edge,
539*f1df9364SStefan Roese 			    enum hws_edge_search e_edge_search,
540*f1df9364SStefan Roese 			    u32 *edge_result)
541*f1df9364SStefan Roese {
542*f1df9364SStefan Roese 	u32 i, res;
543*f1df9364SStefan Roese 	int tap_val, max_val = -10000, min_val = 10000;
544*f1df9364SStefan Roese 	int lock_success = 1;
545*f1df9364SStefan Roese 
546*f1df9364SStefan Roese 	for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
547*f1df9364SStefan Roese 		res = GET_LOCK_RESULT(ar_result[i]);
548*f1df9364SStefan Roese 		if (res == 0) {
549*f1df9364SStefan Roese 			lock_success = 0;
550*f1df9364SStefan Roese 			break;
551*f1df9364SStefan Roese 		}
552*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
553*f1df9364SStefan Roese 					 ("lock failed for bit %d\n", i));
554*f1df9364SStefan Roese 	}
555*f1df9364SStefan Roese 
556*f1df9364SStefan Roese 	if (lock_success == 1) {
557*f1df9364SStefan Roese 		for (i = 0; i < BUS_WIDTH_IN_BITS; i++) {
558*f1df9364SStefan Roese 			tap_val = GET_TAP_RESULT(ar_result[i], e_edge);
559*f1df9364SStefan Roese 			if (tap_val > max_val)
560*f1df9364SStefan Roese 				max_val = tap_val;
561*f1df9364SStefan Roese 			if (tap_val < min_val)
562*f1df9364SStefan Roese 				min_val = tap_val;
563*f1df9364SStefan Roese 			if (e_edge_search == TRAINING_EDGE_MAX)
564*f1df9364SStefan Roese 				*edge_result = (u32) max_val;
565*f1df9364SStefan Roese 			else
566*f1df9364SStefan Roese 				*edge_result = (u32) min_val;
567*f1df9364SStefan Roese 
568*f1df9364SStefan Roese 			DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
569*f1df9364SStefan Roese 						 ("i %d ar_result[i] 0x%x tap_val %d max_val %d min_val %d Edge_result %d\n",
570*f1df9364SStefan Roese 						  i, ar_result[i], tap_val,
571*f1df9364SStefan Roese 						  max_val, min_val,
572*f1df9364SStefan Roese 						  *edge_result));
573*f1df9364SStefan Roese 		}
574*f1df9364SStefan Roese 	} else {
575*f1df9364SStefan Roese 		return MV_FAIL;
576*f1df9364SStefan Roese 	}
577*f1df9364SStefan Roese 
578*f1df9364SStefan Roese 	return MV_OK;
579*f1df9364SStefan Roese }
580*f1df9364SStefan Roese 
581*f1df9364SStefan Roese /*
582*f1df9364SStefan Roese  * Read training search result
583*f1df9364SStefan 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)584*f1df9364SStefan Roese int ddr3_tip_read_training_result(u32 dev_num, u32 if_id,
585*f1df9364SStefan Roese 				  enum hws_access_type pup_access_type,
586*f1df9364SStefan Roese 				  u32 pup_num, u32 bit_num,
587*f1df9364SStefan Roese 				  enum hws_search_dir search,
588*f1df9364SStefan Roese 				  enum hws_dir direction,
589*f1df9364SStefan Roese 				  enum hws_training_result result_type,
590*f1df9364SStefan Roese 				  enum hws_training_load_op operation,
591*f1df9364SStefan Roese 				  u32 cs_num_type, u32 **load_res,
592*f1df9364SStefan Roese 				  int is_read_from_db, u8 cons_tap,
593*f1df9364SStefan Roese 				  int is_check_result_validity)
594*f1df9364SStefan Roese {
595*f1df9364SStefan Roese 	u32 reg_offset, pup_cnt, start_pup, end_pup, start_reg, end_reg;
596*f1df9364SStefan Roese 	u32 *interface_train_res = NULL;
597*f1df9364SStefan Roese 	u16 *reg_addr = NULL;
598*f1df9364SStefan Roese 	u32 read_data[MAX_INTERFACE_NUM];
599*f1df9364SStefan Roese 	u16 *mask_results_pup_reg_map = ddr3_tip_get_mask_results_pup_reg_map();
600*f1df9364SStefan Roese 	u16 *mask_results_dq_reg_map = ddr3_tip_get_mask_results_dq_reg();
601*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
602*f1df9364SStefan Roese 
603*f1df9364SStefan Roese 	/*
604*f1df9364SStefan Roese 	 * Agreed assumption: all CS mask contain same number of bits,
605*f1df9364SStefan Roese 	 * i.e. in multi CS, the number of CS per memory is the same for
606*f1df9364SStefan Roese 	 * all pups
607*f1df9364SStefan Roese 	 */
608*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
609*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_UNICAST, if_id, CS_ENABLE_REG,
610*f1df9364SStefan Roese 		      (cs_num_type == 0) ? 1 << 3 : 0, (1 << 3)));
611*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
612*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_UNICAST, if_id,
613*f1df9364SStefan Roese 		      ODPG_DATA_CONTROL_REG, (cs_num_type << 26), (3 << 26)));
614*f1df9364SStefan Roese 	DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
615*f1df9364SStefan 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",
616*f1df9364SStefan Roese 				  is_read_from_db, cs_num_type, operation,
617*f1df9364SStefan Roese 				  result_type, direction, search, pup_num,
618*f1df9364SStefan Roese 				  if_id, pup_access_type));
619*f1df9364SStefan Roese 
620*f1df9364SStefan Roese 	if ((load_res == NULL) && (is_read_from_db == 1)) {
621*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
622*f1df9364SStefan Roese 					 ("ddr3_tip_read_training_result load_res = NULL"));
623*f1df9364SStefan Roese 		return MV_FAIL;
624*f1df9364SStefan Roese 	}
625*f1df9364SStefan Roese 	if (pup_num >= tm->num_of_bus_per_interface) {
626*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
627*f1df9364SStefan Roese 					 ("pup_num %d not valid\n", pup_num));
628*f1df9364SStefan Roese 	}
629*f1df9364SStefan Roese 	if (if_id >= MAX_INTERFACE_NUM) {
630*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
631*f1df9364SStefan Roese 					 ("if_id %d not valid\n", if_id));
632*f1df9364SStefan Roese 	}
633*f1df9364SStefan Roese 	if (result_type == RESULT_PER_BIT)
634*f1df9364SStefan Roese 		reg_addr = mask_results_dq_reg_map;
635*f1df9364SStefan Roese 	else
636*f1df9364SStefan Roese 		reg_addr = mask_results_pup_reg_map;
637*f1df9364SStefan Roese 	if (pup_access_type == ACCESS_TYPE_UNICAST) {
638*f1df9364SStefan Roese 		start_pup = pup_num;
639*f1df9364SStefan Roese 		end_pup = pup_num;
640*f1df9364SStefan Roese 	} else {		/*pup_access_type == ACCESS_TYPE_MULTICAST) */
641*f1df9364SStefan Roese 
642*f1df9364SStefan Roese 		start_pup = 0;
643*f1df9364SStefan Roese 		end_pup = tm->num_of_bus_per_interface - 1;
644*f1df9364SStefan Roese 	}
645*f1df9364SStefan Roese 
646*f1df9364SStefan Roese 	for (pup_cnt = start_pup; pup_cnt <= end_pup; pup_cnt++) {
647*f1df9364SStefan Roese 		VALIDATE_ACTIVE(tm->bus_act_mask, pup_cnt);
648*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
649*f1df9364SStefan Roese 			DEBUG_LEVEL_TRACE,
650*f1df9364SStefan Roese 			("if_id %d start_pup %d end_pup %d pup_cnt %d\n",
651*f1df9364SStefan Roese 			 if_id, start_pup, end_pup, pup_cnt));
652*f1df9364SStefan Roese 		if (result_type == RESULT_PER_BIT) {
653*f1df9364SStefan Roese 			if (bit_num == ALL_BITS_PER_PUP) {
654*f1df9364SStefan Roese 				start_reg = pup_cnt * BUS_WIDTH_IN_BITS;
655*f1df9364SStefan Roese 				end_reg = (pup_cnt + 1) * BUS_WIDTH_IN_BITS - 1;
656*f1df9364SStefan Roese 			} else {
657*f1df9364SStefan Roese 				start_reg =
658*f1df9364SStefan Roese 					pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
659*f1df9364SStefan Roese 				end_reg = pup_cnt * BUS_WIDTH_IN_BITS + bit_num;
660*f1df9364SStefan Roese 			}
661*f1df9364SStefan Roese 		} else {
662*f1df9364SStefan Roese 			start_reg = pup_cnt;
663*f1df9364SStefan Roese 			end_reg = pup_cnt;
664*f1df9364SStefan Roese 		}
665*f1df9364SStefan Roese 
666*f1df9364SStefan Roese 		interface_train_res =
667*f1df9364SStefan Roese 			ddr3_tip_get_buf_ptr(dev_num, search, result_type,
668*f1df9364SStefan Roese 					     if_id);
669*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
670*f1df9364SStefan Roese 			DEBUG_LEVEL_TRACE,
671*f1df9364SStefan Roese 			("start_reg %d end_reg %d interface %p\n",
672*f1df9364SStefan Roese 			 start_reg, end_reg, interface_train_res));
673*f1df9364SStefan Roese 		if (interface_train_res == NULL) {
674*f1df9364SStefan Roese 			DEBUG_TRAINING_IP_ENGINE(
675*f1df9364SStefan Roese 				DEBUG_LEVEL_ERROR,
676*f1df9364SStefan Roese 				("interface_train_res is NULL\n"));
677*f1df9364SStefan Roese 			return MV_FAIL;
678*f1df9364SStefan Roese 		}
679*f1df9364SStefan Roese 
680*f1df9364SStefan Roese 		for (reg_offset = start_reg; reg_offset <= end_reg;
681*f1df9364SStefan Roese 		     reg_offset++) {
682*f1df9364SStefan Roese 			if (operation == TRAINING_LOAD_OPERATION_UNLOAD) {
683*f1df9364SStefan Roese 				if (is_read_from_db == 0) {
684*f1df9364SStefan Roese 					CHECK_STATUS(ddr3_tip_if_read
685*f1df9364SStefan Roese 						     (dev_num,
686*f1df9364SStefan Roese 						      ACCESS_TYPE_UNICAST,
687*f1df9364SStefan Roese 						      if_id,
688*f1df9364SStefan Roese 						      reg_addr[reg_offset],
689*f1df9364SStefan Roese 						      read_data,
690*f1df9364SStefan Roese 						      MASK_ALL_BITS));
691*f1df9364SStefan Roese 					if (is_check_result_validity == 1) {
692*f1df9364SStefan Roese 						if ((read_data[if_id] &
693*f1df9364SStefan Roese 						     0x02000000) == 0) {
694*f1df9364SStefan Roese 							interface_train_res
695*f1df9364SStefan Roese 								[reg_offset] =
696*f1df9364SStefan Roese 								0x02000000 +
697*f1df9364SStefan Roese 								64 + cons_tap;
698*f1df9364SStefan Roese 						} else {
699*f1df9364SStefan Roese 							interface_train_res
700*f1df9364SStefan Roese 								[reg_offset] =
701*f1df9364SStefan Roese 								read_data
702*f1df9364SStefan Roese 								[if_id] +
703*f1df9364SStefan Roese 								cons_tap;
704*f1df9364SStefan Roese 						}
705*f1df9364SStefan Roese 					} else {
706*f1df9364SStefan Roese 						interface_train_res[reg_offset]
707*f1df9364SStefan Roese 							= read_data[if_id] +
708*f1df9364SStefan Roese 							cons_tap;
709*f1df9364SStefan Roese 					}
710*f1df9364SStefan Roese 					DEBUG_TRAINING_IP_ENGINE
711*f1df9364SStefan Roese 						(DEBUG_LEVEL_TRACE,
712*f1df9364SStefan Roese 						 ("reg_offset %d value 0x%x addr %p\n",
713*f1df9364SStefan Roese 						  reg_offset,
714*f1df9364SStefan Roese 						  interface_train_res
715*f1df9364SStefan Roese 						  [reg_offset],
716*f1df9364SStefan Roese 						  &interface_train_res
717*f1df9364SStefan Roese 						  [reg_offset]));
718*f1df9364SStefan Roese 				} else {
719*f1df9364SStefan Roese 					*load_res =
720*f1df9364SStefan Roese 						&interface_train_res[start_reg];
721*f1df9364SStefan Roese 					DEBUG_TRAINING_IP_ENGINE
722*f1df9364SStefan Roese 						(DEBUG_LEVEL_TRACE,
723*f1df9364SStefan Roese 						 ("*load_res %p\n", *load_res));
724*f1df9364SStefan Roese 				}
725*f1df9364SStefan Roese 			} else {
726*f1df9364SStefan Roese 				DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_TRACE,
727*f1df9364SStefan Roese 							 ("not supported\n"));
728*f1df9364SStefan Roese 			}
729*f1df9364SStefan Roese 		}
730*f1df9364SStefan Roese 	}
731*f1df9364SStefan Roese 
732*f1df9364SStefan Roese 	return MV_OK;
733*f1df9364SStefan Roese }
734*f1df9364SStefan Roese 
735*f1df9364SStefan Roese /*
736*f1df9364SStefan Roese  * Load all pattern to memory using ODPG
737*f1df9364SStefan Roese  */
ddr3_tip_load_all_pattern_to_mem(u32 dev_num)738*f1df9364SStefan Roese int ddr3_tip_load_all_pattern_to_mem(u32 dev_num)
739*f1df9364SStefan Roese {
740*f1df9364SStefan Roese 	u32 pattern = 0, if_id;
741*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
742*f1df9364SStefan Roese 
743*f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
744*f1df9364SStefan Roese 		VALIDATE_ACTIVE(tm->if_act_mask, if_id);
745*f1df9364SStefan Roese 		training_result[training_stage][if_id] = TEST_SUCCESS;
746*f1df9364SStefan Roese 	}
747*f1df9364SStefan Roese 
748*f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
749*f1df9364SStefan Roese 		VALIDATE_ACTIVE(tm->if_act_mask, if_id);
750*f1df9364SStefan Roese 		/* enable single cs */
751*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
752*f1df9364SStefan Roese 			     (dev_num, ACCESS_TYPE_UNICAST, if_id,
753*f1df9364SStefan Roese 			      CS_ENABLE_REG, (1 << 3), (1 << 3)));
754*f1df9364SStefan Roese 	}
755*f1df9364SStefan Roese 
756*f1df9364SStefan Roese 	for (pattern = 0; pattern < PATTERN_LIMIT; pattern++)
757*f1df9364SStefan Roese 		ddr3_tip_load_pattern_to_mem(dev_num, pattern);
758*f1df9364SStefan Roese 
759*f1df9364SStefan Roese 	return MV_OK;
760*f1df9364SStefan Roese }
761*f1df9364SStefan Roese 
762*f1df9364SStefan Roese /*
763*f1df9364SStefan Roese  * Wait till ODPG access is ready
764*f1df9364SStefan Roese  */
is_odpg_access_done(u32 dev_num,u32 if_id)765*f1df9364SStefan Roese int is_odpg_access_done(u32 dev_num, u32 if_id)
766*f1df9364SStefan Roese {
767*f1df9364SStefan Roese 	u32 poll_cnt = 0, data_value;
768*f1df9364SStefan Roese 	u32 read_data[MAX_INTERFACE_NUM];
769*f1df9364SStefan Roese 
770*f1df9364SStefan Roese 	for (poll_cnt = 0; poll_cnt < MAX_POLLING_ITERATIONS; poll_cnt++) {
771*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_read
772*f1df9364SStefan Roese 			     (dev_num, ACCESS_TYPE_UNICAST, if_id,
773*f1df9364SStefan Roese 			      ODPG_BIST_DONE, read_data, MASK_ALL_BITS));
774*f1df9364SStefan Roese 		data_value = read_data[if_id];
775*f1df9364SStefan Roese 		if (((data_value >> ODPG_BIST_DONE_BIT_OFFS) & 0x1) ==
776*f1df9364SStefan Roese 		    ODPG_BIST_DONE_BIT_VALUE) {
777*f1df9364SStefan Roese 				data_value = data_value & 0xfffffffe;
778*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_if_write
779*f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
780*f1df9364SStefan Roese 					      if_id, ODPG_BIST_DONE, data_value,
781*f1df9364SStefan Roese 					      MASK_ALL_BITS));
782*f1df9364SStefan Roese 				break;
783*f1df9364SStefan Roese 			}
784*f1df9364SStefan Roese 	}
785*f1df9364SStefan Roese 
786*f1df9364SStefan Roese 	if (poll_cnt >= MAX_POLLING_ITERATIONS) {
787*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
788*f1df9364SStefan Roese 					 ("Bist Activate: poll failure 2\n"));
789*f1df9364SStefan Roese 		return MV_FAIL;
790*f1df9364SStefan Roese 	}
791*f1df9364SStefan Roese 
792*f1df9364SStefan Roese 	return MV_OK;
793*f1df9364SStefan Roese }
794*f1df9364SStefan Roese 
795*f1df9364SStefan Roese /*
796*f1df9364SStefan Roese  * Load specific pattern to memory using ODPG
797*f1df9364SStefan Roese  */
ddr3_tip_load_pattern_to_mem(u32 dev_num,enum hws_pattern pattern)798*f1df9364SStefan Roese int ddr3_tip_load_pattern_to_mem(u32 dev_num, enum hws_pattern pattern)
799*f1df9364SStefan Roese {
800*f1df9364SStefan Roese 	u32 reg_data, if_id;
801*f1df9364SStefan Roese 	struct pattern_info *pattern_table = ddr3_tip_get_pattern_table();
802*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
803*f1df9364SStefan Roese 
804*f1df9364SStefan Roese 	/* load pattern to memory */
805*f1df9364SStefan Roese 	/*
806*f1df9364SStefan Roese 	 * Write Tx mode, CS0, phases, Tx burst size, delay between burst,
807*f1df9364SStefan Roese 	 * rx pattern phases
808*f1df9364SStefan Roese 	 */
809*f1df9364SStefan Roese 	reg_data =
810*f1df9364SStefan Roese 		0x1 | (pattern_table[pattern].num_of_phases_tx << 5) |
811*f1df9364SStefan Roese 		(pattern_table[pattern].tx_burst_size << 11) |
812*f1df9364SStefan Roese 		(pattern_table[pattern].delay_between_bursts << 15) |
813*f1df9364SStefan Roese 		(pattern_table[pattern].num_of_phases_rx << 21) | (0x1 << 25) |
814*f1df9364SStefan Roese 		(effective_cs << 26);
815*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
816*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
817*f1df9364SStefan Roese 		      ODPG_DATA_CONTROL_REG, reg_data, MASK_ALL_BITS));
818*f1df9364SStefan Roese 	/* ODPG Write enable from BIST */
819*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
820*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
821*f1df9364SStefan Roese 		      ODPG_DATA_CONTROL_REG, (0x1 | (effective_cs << 26)),
822*f1df9364SStefan Roese 		      0xc000003));
823*f1df9364SStefan Roese 	/* disable error injection */
824*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
825*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
826*f1df9364SStefan Roese 		      ODPG_WRITE_DATA_ERROR_REG, 0, 0x1));
827*f1df9364SStefan Roese 	/* load pattern to ODPG */
828*f1df9364SStefan Roese 	ddr3_tip_load_pattern_to_odpg(dev_num, ACCESS_TYPE_MULTICAST,
829*f1df9364SStefan Roese 				      PARAM_NOT_CARE, pattern,
830*f1df9364SStefan Roese 				      pattern_table[pattern].start_addr);
831*f1df9364SStefan Roese 
832*f1df9364SStefan Roese 	for (if_id = 0; if_id < MAX_INTERFACE_NUM; if_id++) {
833*f1df9364SStefan Roese 		if (IS_ACTIVE(tm->if_act_mask, if_id) == 0)
834*f1df9364SStefan Roese 			continue;
835*f1df9364SStefan Roese 
836*f1df9364SStefan Roese 		CHECK_STATUS(ddr3_tip_if_write
837*f1df9364SStefan Roese 			     (dev_num, ACCESS_TYPE_UNICAST, if_id, 0x1498,
838*f1df9364SStefan Roese 			      0x3, 0xf));
839*f1df9364SStefan Roese 	}
840*f1df9364SStefan Roese 
841*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
842*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
843*f1df9364SStefan Roese 		      ODPG_ENABLE_REG, 0x1 << ODPG_ENABLE_OFFS,
844*f1df9364SStefan Roese 		      (0x1 << ODPG_ENABLE_OFFS)));
845*f1df9364SStefan Roese 
846*f1df9364SStefan Roese 	mdelay(1);
847*f1df9364SStefan Roese 
848*f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
849*f1df9364SStefan Roese 		VALIDATE_ACTIVE(tm->if_act_mask, if_id);
850*f1df9364SStefan Roese 		CHECK_STATUS(is_odpg_access_done(dev_num, if_id));
851*f1df9364SStefan Roese 	}
852*f1df9364SStefan Roese 
853*f1df9364SStefan Roese 	/* Disable ODPG and stop write to memory */
854*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
855*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
856*f1df9364SStefan Roese 		      ODPG_DATA_CONTROL_REG, (0x1 << 30), (u32) (0x3 << 30)));
857*f1df9364SStefan Roese 
858*f1df9364SStefan Roese 	/* return to default */
859*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
860*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE,
861*f1df9364SStefan Roese 		      ODPG_DATA_CONTROL_REG, 0, MASK_ALL_BITS));
862*f1df9364SStefan Roese 
863*f1df9364SStefan Roese 	/* Disable odt0 for CS0 training - need to adjust for multy CS */
864*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_if_write
865*f1df9364SStefan Roese 		     (dev_num, ACCESS_TYPE_MULTICAST, PARAM_NOT_CARE, 0x1498,
866*f1df9364SStefan Roese 		      0x0, 0xf));
867*f1df9364SStefan Roese 
868*f1df9364SStefan Roese 	/* temporary added */
869*f1df9364SStefan Roese 	mdelay(1);
870*f1df9364SStefan Roese 
871*f1df9364SStefan Roese 	return MV_OK;
872*f1df9364SStefan Roese }
873*f1df9364SStefan Roese 
874*f1df9364SStefan Roese /*
875*f1df9364SStefan Roese  * Load specific pattern to memory using CPU
876*f1df9364SStefan Roese  */
ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num,enum hws_pattern pattern,u32 offset)877*f1df9364SStefan Roese int ddr3_tip_load_pattern_to_mem_by_cpu(u32 dev_num, enum hws_pattern pattern,
878*f1df9364SStefan Roese 					u32 offset)
879*f1df9364SStefan Roese {
880*f1df9364SStefan Roese 	/* eranba - TBD */
881*f1df9364SStefan Roese 	return MV_OK;
882*f1df9364SStefan Roese }
883*f1df9364SStefan Roese 
884*f1df9364SStefan Roese /*
885*f1df9364SStefan Roese  * Training search routine
886*f1df9364SStefan 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)887*f1df9364SStefan Roese int ddr3_tip_ip_training_wrapper_int(u32 dev_num,
888*f1df9364SStefan Roese 				     enum hws_access_type access_type,
889*f1df9364SStefan Roese 				     u32 if_id,
890*f1df9364SStefan Roese 				     enum hws_access_type pup_access_type,
891*f1df9364SStefan Roese 				     u32 pup_num, u32 bit_num,
892*f1df9364SStefan Roese 				     enum hws_training_result result_type,
893*f1df9364SStefan Roese 				     enum hws_control_element control_element,
894*f1df9364SStefan Roese 				     enum hws_search_dir search_dir,
895*f1df9364SStefan Roese 				     enum hws_dir direction,
896*f1df9364SStefan Roese 				     u32 interface_mask, u32 init_value_l2h,
897*f1df9364SStefan Roese 				     u32 init_value_h2l, u32 num_iter,
898*f1df9364SStefan Roese 				     enum hws_pattern pattern,
899*f1df9364SStefan Roese 				     enum hws_edge_compare edge_comp,
900*f1df9364SStefan Roese 				     enum hws_ddr_cs train_cs_type, u32 cs_num,
901*f1df9364SStefan Roese 				     enum hws_training_ip_stat *train_status)
902*f1df9364SStefan Roese {
903*f1df9364SStefan Roese 	u32 interface_num = 0, start_if, end_if, init_value_used;
904*f1df9364SStefan Roese 	enum hws_search_dir search_dir_id, start_search, end_search;
905*f1df9364SStefan Roese 	enum hws_edge_compare edge_comp_used;
906*f1df9364SStefan Roese 	u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
907*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
908*f1df9364SStefan Roese 
909*f1df9364SStefan Roese 	if (train_status == NULL) {
910*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
911*f1df9364SStefan Roese 					 ("train_status is NULL\n"));
912*f1df9364SStefan Roese 		return MV_FAIL;
913*f1df9364SStefan Roese 	}
914*f1df9364SStefan Roese 
915*f1df9364SStefan Roese 	if ((train_cs_type > CS_NON_SINGLE) ||
916*f1df9364SStefan Roese 	    (edge_comp >= EDGE_PFP) ||
917*f1df9364SStefan Roese 	    (pattern >= PATTERN_LIMIT) ||
918*f1df9364SStefan Roese 	    (direction > OPER_WRITE_AND_READ) ||
919*f1df9364SStefan Roese 	    (search_dir > HWS_HIGH2LOW) ||
920*f1df9364SStefan Roese 	    (control_element > HWS_CONTROL_ELEMENT_DQS_SKEW) ||
921*f1df9364SStefan Roese 	    (result_type > RESULT_PER_BYTE) ||
922*f1df9364SStefan Roese 	    (pup_num >= tm->num_of_bus_per_interface) ||
923*f1df9364SStefan Roese 	    (pup_access_type > ACCESS_TYPE_MULTICAST) ||
924*f1df9364SStefan Roese 	    (if_id > 11) || (access_type > ACCESS_TYPE_MULTICAST)) {
925*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
926*f1df9364SStefan Roese 			DEBUG_LEVEL_ERROR,
927*f1df9364SStefan 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",
928*f1df9364SStefan Roese 			 train_cs_type, edge_comp, pattern, direction,
929*f1df9364SStefan Roese 			 search_dir, control_element, result_type, pup_num,
930*f1df9364SStefan Roese 			 pup_access_type, if_id, access_type));
931*f1df9364SStefan Roese 		return MV_FAIL;
932*f1df9364SStefan Roese 	}
933*f1df9364SStefan Roese 
934*f1df9364SStefan Roese 	if (edge_comp == EDGE_FPF) {
935*f1df9364SStefan Roese 		start_search = HWS_LOW2HIGH;
936*f1df9364SStefan Roese 		end_search = HWS_HIGH2LOW;
937*f1df9364SStefan Roese 		edge_comp_used = EDGE_FP;
938*f1df9364SStefan Roese 	} else {
939*f1df9364SStefan Roese 		start_search = search_dir;
940*f1df9364SStefan Roese 		end_search = search_dir;
941*f1df9364SStefan Roese 		edge_comp_used = edge_comp;
942*f1df9364SStefan Roese 	}
943*f1df9364SStefan Roese 
944*f1df9364SStefan Roese 	for (search_dir_id = start_search; search_dir_id <= end_search;
945*f1df9364SStefan Roese 	     search_dir_id++) {
946*f1df9364SStefan Roese 		init_value_used = (search_dir_id == HWS_LOW2HIGH) ?
947*f1df9364SStefan Roese 			init_value_l2h : init_value_h2l;
948*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(
949*f1df9364SStefan Roese 			DEBUG_LEVEL_TRACE,
950*f1df9364SStefan 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",
951*f1df9364SStefan Roese 			 dev_num, access_type, if_id, pup_access_type, pup_num,
952*f1df9364SStefan Roese 			 result_type, control_element, search_dir_id,
953*f1df9364SStefan Roese 			 direction, interface_mask, init_value_used, num_iter,
954*f1df9364SStefan Roese 			 pattern, edge_comp_used, train_cs_type, cs_num));
955*f1df9364SStefan Roese 
956*f1df9364SStefan Roese 		ddr3_tip_ip_training(dev_num, access_type, if_id,
957*f1df9364SStefan Roese 				     pup_access_type, pup_num, result_type,
958*f1df9364SStefan Roese 				     control_element, search_dir_id, direction,
959*f1df9364SStefan Roese 				     interface_mask, init_value_used, num_iter,
960*f1df9364SStefan Roese 				     pattern, edge_comp_used, train_cs_type,
961*f1df9364SStefan Roese 				     cs_num, train_status);
962*f1df9364SStefan Roese 		if (access_type == ACCESS_TYPE_MULTICAST) {
963*f1df9364SStefan Roese 			start_if = 0;
964*f1df9364SStefan Roese 			end_if = MAX_INTERFACE_NUM - 1;
965*f1df9364SStefan Roese 		} else {
966*f1df9364SStefan Roese 			start_if = if_id;
967*f1df9364SStefan Roese 			end_if = if_id;
968*f1df9364SStefan Roese 		}
969*f1df9364SStefan Roese 
970*f1df9364SStefan Roese 		for (interface_num = start_if; interface_num <= end_if;
971*f1df9364SStefan Roese 		     interface_num++) {
972*f1df9364SStefan Roese 			VALIDATE_ACTIVE(tm->if_act_mask, interface_num);
973*f1df9364SStefan Roese 			cs_num = 0;
974*f1df9364SStefan Roese 			CHECK_STATUS(ddr3_tip_read_training_result
975*f1df9364SStefan Roese 				     (dev_num, interface_num, pup_access_type,
976*f1df9364SStefan Roese 				      pup_num, bit_num, search_dir_id,
977*f1df9364SStefan Roese 				      direction, result_type,
978*f1df9364SStefan Roese 				      TRAINING_LOAD_OPERATION_UNLOAD,
979*f1df9364SStefan Roese 				      train_cs_type, NULL, 0, cons_tap,
980*f1df9364SStefan Roese 				      0));
981*f1df9364SStefan Roese 		}
982*f1df9364SStefan Roese 	}
983*f1df9364SStefan Roese 
984*f1df9364SStefan Roese 	return MV_OK;
985*f1df9364SStefan Roese }
986*f1df9364SStefan Roese 
987*f1df9364SStefan Roese /*
988*f1df9364SStefan Roese  * Training search & read result routine
989*f1df9364SStefan 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)990*f1df9364SStefan Roese int ddr3_tip_ip_training_wrapper(u32 dev_num, enum hws_access_type access_type,
991*f1df9364SStefan Roese 				 u32 if_id,
992*f1df9364SStefan Roese 				 enum hws_access_type pup_access_type,
993*f1df9364SStefan Roese 				 u32 pup_num,
994*f1df9364SStefan Roese 				 enum hws_training_result result_type,
995*f1df9364SStefan Roese 				 enum hws_control_element control_element,
996*f1df9364SStefan Roese 				 enum hws_search_dir search_dir,
997*f1df9364SStefan Roese 				 enum hws_dir direction, u32 interface_mask,
998*f1df9364SStefan Roese 				 u32 init_value_l2h, u32 init_value_h2l,
999*f1df9364SStefan Roese 				 u32 num_iter, enum hws_pattern pattern,
1000*f1df9364SStefan Roese 				 enum hws_edge_compare edge_comp,
1001*f1df9364SStefan Roese 				 enum hws_ddr_cs train_cs_type, u32 cs_num,
1002*f1df9364SStefan Roese 				 enum hws_training_ip_stat *train_status)
1003*f1df9364SStefan Roese {
1004*f1df9364SStefan Roese 	u8 e1, e2;
1005*f1df9364SStefan Roese 	u32 interface_cnt, bit_id, start_if, end_if, bit_end = 0;
1006*f1df9364SStefan Roese 	u32 *result[HWS_SEARCH_DIR_LIMIT] = { 0 };
1007*f1df9364SStefan Roese 	u8 cons_tap = (direction == OPER_WRITE) ? (64) : (0);
1008*f1df9364SStefan Roese 	u8 bit_bit_mask[MAX_BUS_NUM] = { 0 }, bit_bit_mask_active = 0;
1009*f1df9364SStefan Roese 	u8 pup_id;
1010*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
1011*f1df9364SStefan Roese 
1012*f1df9364SStefan Roese 	if (pup_num >= tm->num_of_bus_per_interface) {
1013*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1014*f1df9364SStefan Roese 					 ("pup_num %d not valid\n", pup_num));
1015*f1df9364SStefan Roese 	}
1016*f1df9364SStefan Roese 
1017*f1df9364SStefan Roese 	if (if_id >= MAX_INTERFACE_NUM) {
1018*f1df9364SStefan Roese 		DEBUG_TRAINING_IP_ENGINE(DEBUG_LEVEL_ERROR,
1019*f1df9364SStefan Roese 					 ("if_id %d not valid\n", if_id));
1020*f1df9364SStefan Roese 	}
1021*f1df9364SStefan Roese 
1022*f1df9364SStefan Roese 	CHECK_STATUS(ddr3_tip_ip_training_wrapper_int
1023*f1df9364SStefan Roese 		     (dev_num, access_type, if_id, pup_access_type, pup_num,
1024*f1df9364SStefan Roese 		      ALL_BITS_PER_PUP, result_type, control_element,
1025*f1df9364SStefan Roese 		      search_dir, direction, interface_mask, init_value_l2h,
1026*f1df9364SStefan Roese 		      init_value_h2l, num_iter, pattern, edge_comp,
1027*f1df9364SStefan Roese 		      train_cs_type, cs_num, train_status));
1028*f1df9364SStefan Roese 
1029*f1df9364SStefan Roese 	if (access_type == ACCESS_TYPE_MULTICAST) {
1030*f1df9364SStefan Roese 		start_if = 0;
1031*f1df9364SStefan Roese 		end_if = MAX_INTERFACE_NUM - 1;
1032*f1df9364SStefan Roese 	} else {
1033*f1df9364SStefan Roese 		start_if = if_id;
1034*f1df9364SStefan Roese 		end_if = if_id;
1035*f1df9364SStefan Roese 	}
1036*f1df9364SStefan Roese 
1037*f1df9364SStefan Roese 	for (interface_cnt = start_if; interface_cnt <= end_if;
1038*f1df9364SStefan Roese 	     interface_cnt++) {
1039*f1df9364SStefan Roese 		VALIDATE_ACTIVE(tm->if_act_mask, interface_cnt);
1040*f1df9364SStefan Roese 		for (pup_id = 0;
1041*f1df9364SStefan Roese 		     pup_id <= (tm->num_of_bus_per_interface - 1); pup_id++) {
1042*f1df9364SStefan Roese 			VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
1043*f1df9364SStefan Roese 			if (result_type == RESULT_PER_BIT)
1044*f1df9364SStefan Roese 				bit_end = BUS_WIDTH_IN_BITS - 1;
1045*f1df9364SStefan Roese 			else
1046*f1df9364SStefan Roese 				bit_end = 0;
1047*f1df9364SStefan Roese 
1048*f1df9364SStefan Roese 			bit_bit_mask[pup_id] = 0;
1049*f1df9364SStefan Roese 			for (bit_id = 0; bit_id <= bit_end; bit_id++) {
1050*f1df9364SStefan Roese 				enum hws_search_dir search_dir_id;
1051*f1df9364SStefan Roese 				for (search_dir_id = HWS_LOW2HIGH;
1052*f1df9364SStefan Roese 				     search_dir_id <= HWS_HIGH2LOW;
1053*f1df9364SStefan Roese 				     search_dir_id++) {
1054*f1df9364SStefan Roese 					CHECK_STATUS
1055*f1df9364SStefan Roese 						(ddr3_tip_read_training_result
1056*f1df9364SStefan Roese 						 (dev_num, interface_cnt,
1057*f1df9364SStefan Roese 						  ACCESS_TYPE_UNICAST, pup_id,
1058*f1df9364SStefan Roese 						  bit_id, search_dir_id,
1059*f1df9364SStefan Roese 						  direction, result_type,
1060*f1df9364SStefan Roese 						  TRAINING_LOAD_OPERATION_UNLOAD,
1061*f1df9364SStefan Roese 						  CS_SINGLE,
1062*f1df9364SStefan Roese 						  &result[search_dir_id],
1063*f1df9364SStefan Roese 						  1, 0, 0));
1064*f1df9364SStefan Roese 				}
1065*f1df9364SStefan Roese 				e1 = GET_TAP_RESULT(result[HWS_LOW2HIGH][0],
1066*f1df9364SStefan Roese 						    EDGE_1);
1067*f1df9364SStefan Roese 				e2 = GET_TAP_RESULT(result[HWS_HIGH2LOW][0],
1068*f1df9364SStefan Roese 						    EDGE_1);
1069*f1df9364SStefan Roese 				DEBUG_TRAINING_IP_ENGINE(
1070*f1df9364SStefan Roese 					DEBUG_LEVEL_INFO,
1071*f1df9364SStefan Roese 					("wrapper if_id %d pup_id %d bit %d l2h 0x%x (e1 0x%x) h2l 0x%x (e2 0x%x)\n",
1072*f1df9364SStefan Roese 					 interface_cnt, pup_id, bit_id,
1073*f1df9364SStefan Roese 					 result[HWS_LOW2HIGH][0], e1,
1074*f1df9364SStefan Roese 					 result[HWS_HIGH2LOW][0], e2));
1075*f1df9364SStefan Roese 				/* TBD validate is valid only for tx */
1076*f1df9364SStefan Roese 				if (VALIDATE_TRAINING_LIMIT(e1, e2) == 1 &&
1077*f1df9364SStefan Roese 				    GET_LOCK_RESULT(result[HWS_LOW2HIGH][0]) &&
1078*f1df9364SStefan Roese 				    GET_LOCK_RESULT(result[HWS_LOW2HIGH][0])) {
1079*f1df9364SStefan Roese 					/* Mark problem bits */
1080*f1df9364SStefan Roese 					bit_bit_mask[pup_id] |= 1 << bit_id;
1081*f1df9364SStefan Roese 					bit_bit_mask_active = 1;
1082*f1df9364SStefan Roese 				}
1083*f1df9364SStefan Roese 			}	/* For all bits */
1084*f1df9364SStefan Roese 		}		/* For all PUPs */
1085*f1df9364SStefan Roese 
1086*f1df9364SStefan Roese 		/* Fix problem bits */
1087*f1df9364SStefan Roese 		if (bit_bit_mask_active != 0) {
1088*f1df9364SStefan Roese 			u32 *l2h_if_train_res = NULL;
1089*f1df9364SStefan Roese 			u32 *h2l_if_train_res = NULL;
1090*f1df9364SStefan Roese 			l2h_if_train_res =
1091*f1df9364SStefan Roese 				ddr3_tip_get_buf_ptr(dev_num, HWS_LOW2HIGH,
1092*f1df9364SStefan Roese 						     result_type,
1093*f1df9364SStefan Roese 						     interface_cnt);
1094*f1df9364SStefan Roese 			h2l_if_train_res =
1095*f1df9364SStefan Roese 				ddr3_tip_get_buf_ptr(dev_num, HWS_HIGH2LOW,
1096*f1df9364SStefan Roese 						     result_type,
1097*f1df9364SStefan Roese 						     interface_cnt);
1098*f1df9364SStefan Roese 
1099*f1df9364SStefan Roese 			ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST,
1100*f1df9364SStefan Roese 					     interface_cnt,
1101*f1df9364SStefan Roese 					     ACCESS_TYPE_MULTICAST,
1102*f1df9364SStefan Roese 					     PARAM_NOT_CARE, result_type,
1103*f1df9364SStefan Roese 					     control_element, HWS_LOW2HIGH,
1104*f1df9364SStefan Roese 					     direction, interface_mask,
1105*f1df9364SStefan Roese 					     num_iter / 2, num_iter / 2,
1106*f1df9364SStefan Roese 					     pattern, EDGE_FP, train_cs_type,
1107*f1df9364SStefan Roese 					     cs_num, train_status);
1108*f1df9364SStefan Roese 
1109*f1df9364SStefan Roese 			for (pup_id = 0;
1110*f1df9364SStefan Roese 			     pup_id <= (tm->num_of_bus_per_interface - 1);
1111*f1df9364SStefan Roese 			     pup_id++) {
1112*f1df9364SStefan Roese 				VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
1113*f1df9364SStefan Roese 
1114*f1df9364SStefan Roese 				if (bit_bit_mask[pup_id] == 0)
1115*f1df9364SStefan Roese 					continue;
1116*f1df9364SStefan Roese 
1117*f1df9364SStefan Roese 				for (bit_id = 0; bit_id <= bit_end; bit_id++) {
1118*f1df9364SStefan Roese 					if ((bit_bit_mask[pup_id] &
1119*f1df9364SStefan Roese 					     (1 << bit_id)) == 0)
1120*f1df9364SStefan Roese 						continue;
1121*f1df9364SStefan Roese 					CHECK_STATUS
1122*f1df9364SStefan Roese 						(ddr3_tip_read_training_result
1123*f1df9364SStefan Roese 						 (dev_num, interface_cnt,
1124*f1df9364SStefan Roese 						  ACCESS_TYPE_UNICAST, pup_id,
1125*f1df9364SStefan Roese 						  bit_id, HWS_LOW2HIGH,
1126*f1df9364SStefan Roese 						  direction,
1127*f1df9364SStefan Roese 						  result_type,
1128*f1df9364SStefan Roese 						  TRAINING_LOAD_OPERATION_UNLOAD,
1129*f1df9364SStefan Roese 						  CS_SINGLE, &l2h_if_train_res,
1130*f1df9364SStefan Roese 						  0, 0, 1));
1131*f1df9364SStefan Roese 				}
1132*f1df9364SStefan Roese 			}
1133*f1df9364SStefan Roese 
1134*f1df9364SStefan Roese 			ddr3_tip_ip_training(dev_num, ACCESS_TYPE_UNICAST,
1135*f1df9364SStefan Roese 					     interface_cnt,
1136*f1df9364SStefan Roese 					     ACCESS_TYPE_MULTICAST,
1137*f1df9364SStefan Roese 					     PARAM_NOT_CARE, result_type,
1138*f1df9364SStefan Roese 					     control_element, HWS_HIGH2LOW,
1139*f1df9364SStefan Roese 					     direction, interface_mask,
1140*f1df9364SStefan Roese 					     num_iter / 2, num_iter / 2,
1141*f1df9364SStefan Roese 					     pattern, EDGE_FP, train_cs_type,
1142*f1df9364SStefan Roese 					     cs_num, train_status);
1143*f1df9364SStefan Roese 
1144*f1df9364SStefan Roese 			for (pup_id = 0;
1145*f1df9364SStefan Roese 			     pup_id <= (tm->num_of_bus_per_interface - 1);
1146*f1df9364SStefan Roese 			     pup_id++) {
1147*f1df9364SStefan Roese 				VALIDATE_ACTIVE(tm->bus_act_mask, pup_id);
1148*f1df9364SStefan Roese 
1149*f1df9364SStefan Roese 				if (bit_bit_mask[pup_id] == 0)
1150*f1df9364SStefan Roese 					continue;
1151*f1df9364SStefan Roese 
1152*f1df9364SStefan Roese 				for (bit_id = 0; bit_id <= bit_end; bit_id++) {
1153*f1df9364SStefan Roese 					if ((bit_bit_mask[pup_id] &
1154*f1df9364SStefan Roese 					     (1 << bit_id)) == 0)
1155*f1df9364SStefan Roese 						continue;
1156*f1df9364SStefan Roese 					CHECK_STATUS
1157*f1df9364SStefan Roese 						(ddr3_tip_read_training_result
1158*f1df9364SStefan Roese 						 (dev_num, interface_cnt,
1159*f1df9364SStefan Roese 						  ACCESS_TYPE_UNICAST, pup_id,
1160*f1df9364SStefan Roese 						  bit_id, HWS_HIGH2LOW, direction,
1161*f1df9364SStefan Roese 						  result_type,
1162*f1df9364SStefan Roese 						  TRAINING_LOAD_OPERATION_UNLOAD,
1163*f1df9364SStefan Roese 						  CS_SINGLE, &h2l_if_train_res,
1164*f1df9364SStefan Roese 						  0, cons_tap, 1));
1165*f1df9364SStefan Roese 				}
1166*f1df9364SStefan Roese 			}
1167*f1df9364SStefan Roese 		}		/* if bit_bit_mask_active */
1168*f1df9364SStefan Roese 	}			/* For all Interfacess */
1169*f1df9364SStefan Roese 
1170*f1df9364SStefan Roese 	return MV_OK;
1171*f1df9364SStefan Roese }
1172*f1df9364SStefan Roese 
1173*f1df9364SStefan Roese /*
1174*f1df9364SStefan Roese  * Load phy values
1175*f1df9364SStefan Roese  */
ddr3_tip_load_phy_values(int b_load)1176*f1df9364SStefan Roese int ddr3_tip_load_phy_values(int b_load)
1177*f1df9364SStefan Roese {
1178*f1df9364SStefan Roese 	u32 bus_cnt = 0, if_id, dev_num = 0;
1179*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
1180*f1df9364SStefan Roese 
1181*f1df9364SStefan Roese 	for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1; if_id++) {
1182*f1df9364SStefan Roese 		VALIDATE_ACTIVE(tm->if_act_mask, if_id);
1183*f1df9364SStefan Roese 		for (bus_cnt = 0; bus_cnt < GET_TOPOLOGY_NUM_OF_BUSES();
1184*f1df9364SStefan Roese 		     bus_cnt++) {
1185*f1df9364SStefan Roese 			VALIDATE_ACTIVE(tm->bus_act_mask, bus_cnt);
1186*f1df9364SStefan Roese 			if (b_load == 1) {
1187*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_read
1188*f1df9364SStefan Roese 					     (dev_num, if_id,
1189*f1df9364SStefan Roese 					      ACCESS_TYPE_UNICAST, bus_cnt,
1190*f1df9364SStefan Roese 					      DDR_PHY_DATA,
1191*f1df9364SStefan Roese 					      WRITE_CENTRALIZATION_PHY_REG +
1192*f1df9364SStefan Roese 					      (effective_cs *
1193*f1df9364SStefan Roese 					       CS_REGISTER_ADDR_OFFSET),
1194*f1df9364SStefan Roese 					      &phy_reg_bk[if_id][bus_cnt]
1195*f1df9364SStefan Roese 					      [0]));
1196*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_read
1197*f1df9364SStefan Roese 					     (dev_num, if_id,
1198*f1df9364SStefan Roese 					      ACCESS_TYPE_UNICAST, bus_cnt,
1199*f1df9364SStefan Roese 					      DDR_PHY_DATA,
1200*f1df9364SStefan Roese 					      RL_PHY_REG +
1201*f1df9364SStefan Roese 					      (effective_cs *
1202*f1df9364SStefan Roese 					       CS_REGISTER_ADDR_OFFSET),
1203*f1df9364SStefan Roese 					      &phy_reg_bk[if_id][bus_cnt]
1204*f1df9364SStefan Roese 					      [1]));
1205*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_read
1206*f1df9364SStefan Roese 					     (dev_num, if_id,
1207*f1df9364SStefan Roese 					      ACCESS_TYPE_UNICAST, bus_cnt,
1208*f1df9364SStefan Roese 					      DDR_PHY_DATA,
1209*f1df9364SStefan Roese 					      READ_CENTRALIZATION_PHY_REG +
1210*f1df9364SStefan Roese 					      (effective_cs *
1211*f1df9364SStefan Roese 					       CS_REGISTER_ADDR_OFFSET),
1212*f1df9364SStefan Roese 					      &phy_reg_bk[if_id][bus_cnt]
1213*f1df9364SStefan Roese 					      [2]));
1214*f1df9364SStefan Roese 			} else {
1215*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_write
1216*f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
1217*f1df9364SStefan Roese 					      if_id, ACCESS_TYPE_UNICAST,
1218*f1df9364SStefan Roese 					      bus_cnt, DDR_PHY_DATA,
1219*f1df9364SStefan Roese 					      WRITE_CENTRALIZATION_PHY_REG +
1220*f1df9364SStefan Roese 					      (effective_cs *
1221*f1df9364SStefan Roese 					       CS_REGISTER_ADDR_OFFSET),
1222*f1df9364SStefan Roese 					      phy_reg_bk[if_id][bus_cnt]
1223*f1df9364SStefan Roese 					      [0]));
1224*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_write
1225*f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
1226*f1df9364SStefan Roese 					      if_id, ACCESS_TYPE_UNICAST,
1227*f1df9364SStefan Roese 					      bus_cnt, DDR_PHY_DATA,
1228*f1df9364SStefan Roese 					      RL_PHY_REG +
1229*f1df9364SStefan Roese 					      (effective_cs *
1230*f1df9364SStefan Roese 					       CS_REGISTER_ADDR_OFFSET),
1231*f1df9364SStefan Roese 					      phy_reg_bk[if_id][bus_cnt]
1232*f1df9364SStefan Roese 					      [1]));
1233*f1df9364SStefan Roese 				CHECK_STATUS(ddr3_tip_bus_write
1234*f1df9364SStefan Roese 					     (dev_num, ACCESS_TYPE_UNICAST,
1235*f1df9364SStefan Roese 					      if_id, ACCESS_TYPE_UNICAST,
1236*f1df9364SStefan Roese 					      bus_cnt, DDR_PHY_DATA,
1237*f1df9364SStefan Roese 					      READ_CENTRALIZATION_PHY_REG +
1238*f1df9364SStefan Roese 					      (effective_cs *
1239*f1df9364SStefan Roese 					       CS_REGISTER_ADDR_OFFSET),
1240*f1df9364SStefan Roese 					      phy_reg_bk[if_id][bus_cnt]
1241*f1df9364SStefan Roese 					      [2]));
1242*f1df9364SStefan Roese 			}
1243*f1df9364SStefan Roese 		}
1244*f1df9364SStefan Roese 	}
1245*f1df9364SStefan Roese 
1246*f1df9364SStefan Roese 	return MV_OK;
1247*f1df9364SStefan Roese }
1248*f1df9364SStefan 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)1249*f1df9364SStefan Roese int ddr3_tip_training_ip_test(u32 dev_num, enum hws_training_result result_type,
1250*f1df9364SStefan Roese 			      enum hws_search_dir search_dir,
1251*f1df9364SStefan Roese 			      enum hws_dir direction,
1252*f1df9364SStefan Roese 			      enum hws_edge_compare edge,
1253*f1df9364SStefan Roese 			      u32 init_val1, u32 init_val2,
1254*f1df9364SStefan Roese 			      u32 num_of_iterations,
1255*f1df9364SStefan Roese 			      u32 start_pattern, u32 end_pattern)
1256*f1df9364SStefan Roese {
1257*f1df9364SStefan Roese 	u32 pattern, if_id, pup_id;
1258*f1df9364SStefan Roese 	enum hws_training_ip_stat train_status[MAX_INTERFACE_NUM];
1259*f1df9364SStefan Roese 	u32 *res = NULL;
1260*f1df9364SStefan Roese 	u32 search_state = 0;
1261*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
1262*f1df9364SStefan Roese 
1263*f1df9364SStefan Roese 	ddr3_tip_load_phy_values(1);
1264*f1df9364SStefan Roese 
1265*f1df9364SStefan Roese 	for (pattern = start_pattern; pattern <= end_pattern; pattern++) {
1266*f1df9364SStefan Roese 		for (search_state = 0; search_state < HWS_SEARCH_DIR_LIMIT;
1267*f1df9364SStefan Roese 		     search_state++) {
1268*f1df9364SStefan Roese 			ddr3_tip_ip_training_wrapper(dev_num,
1269*f1df9364SStefan Roese 						     ACCESS_TYPE_MULTICAST, 0,
1270*f1df9364SStefan Roese 						     ACCESS_TYPE_MULTICAST, 0,
1271*f1df9364SStefan Roese 						     result_type,
1272*f1df9364SStefan Roese 						     HWS_CONTROL_ELEMENT_ADLL,
1273*f1df9364SStefan Roese 						     search_dir, direction,
1274*f1df9364SStefan Roese 						     0xfff, init_val1,
1275*f1df9364SStefan Roese 						     init_val2,
1276*f1df9364SStefan Roese 						     num_of_iterations, pattern,
1277*f1df9364SStefan Roese 						     edge, CS_SINGLE,
1278*f1df9364SStefan Roese 						     PARAM_NOT_CARE,
1279*f1df9364SStefan Roese 						     train_status);
1280*f1df9364SStefan Roese 
1281*f1df9364SStefan Roese 			for (if_id = 0; if_id <= MAX_INTERFACE_NUM - 1;
1282*f1df9364SStefan Roese 			     if_id++) {
1283*f1df9364SStefan Roese 				VALIDATE_ACTIVE(tm->if_act_mask, if_id);
1284*f1df9364SStefan Roese 				for (pup_id = 0; pup_id <
1285*f1df9364SStefan Roese 					     tm->num_of_bus_per_interface;
1286*f1df9364SStefan Roese 				     pup_id++) {
1287*f1df9364SStefan Roese 					VALIDATE_ACTIVE(tm->bus_act_mask,
1288*f1df9364SStefan Roese 							pup_id);
1289*f1df9364SStefan Roese 					CHECK_STATUS
1290*f1df9364SStefan Roese 						(ddr3_tip_read_training_result
1291*f1df9364SStefan Roese 						 (dev_num, if_id,
1292*f1df9364SStefan Roese 						  ACCESS_TYPE_UNICAST, pup_id,
1293*f1df9364SStefan Roese 						  ALL_BITS_PER_PUP,
1294*f1df9364SStefan Roese 						  search_state,
1295*f1df9364SStefan Roese 						  direction, result_type,
1296*f1df9364SStefan Roese 						  TRAINING_LOAD_OPERATION_UNLOAD,
1297*f1df9364SStefan Roese 						  CS_SINGLE, &res, 1, 0,
1298*f1df9364SStefan Roese 						  0));
1299*f1df9364SStefan Roese 					if (result_type == RESULT_PER_BYTE) {
1300*f1df9364SStefan Roese 						DEBUG_TRAINING_IP_ENGINE
1301*f1df9364SStefan Roese 							(DEBUG_LEVEL_INFO,
1302*f1df9364SStefan Roese 							 ("search_state %d if_id %d pup_id %d 0x%x\n",
1303*f1df9364SStefan Roese 							  search_state, if_id,
1304*f1df9364SStefan Roese 							  pup_id, res[0]));
1305*f1df9364SStefan Roese 					} else {
1306*f1df9364SStefan Roese 						DEBUG_TRAINING_IP_ENGINE
1307*f1df9364SStefan Roese 							(DEBUG_LEVEL_INFO,
1308*f1df9364SStefan 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",
1309*f1df9364SStefan Roese 							  search_state, if_id,
1310*f1df9364SStefan Roese 							  pup_id, res[0],
1311*f1df9364SStefan Roese 							  res[1], res[2],
1312*f1df9364SStefan Roese 							  res[3], res[4],
1313*f1df9364SStefan Roese 							  res[5], res[6],
1314*f1df9364SStefan Roese 							  res[7]));
1315*f1df9364SStefan Roese 					}
1316*f1df9364SStefan Roese 				}
1317*f1df9364SStefan Roese 			}	/* interface */
1318*f1df9364SStefan Roese 		}		/* search */
1319*f1df9364SStefan Roese 	}			/* pattern */
1320*f1df9364SStefan Roese 
1321*f1df9364SStefan Roese 	ddr3_tip_load_phy_values(0);
1322*f1df9364SStefan Roese 
1323*f1df9364SStefan Roese 	return MV_OK;
1324*f1df9364SStefan Roese }
1325*f1df9364SStefan Roese 
ddr3_tip_get_pattern_table()1326*f1df9364SStefan Roese struct pattern_info *ddr3_tip_get_pattern_table()
1327*f1df9364SStefan Roese {
1328*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
1329*f1df9364SStefan Roese 
1330*f1df9364SStefan Roese 	if (DDR3_IS_16BIT_DRAM_MODE(tm->bus_act_mask) == 0)
1331*f1df9364SStefan Roese 		return pattern_table_32;
1332*f1df9364SStefan Roese 	else
1333*f1df9364SStefan Roese 		return pattern_table_16;
1334*f1df9364SStefan Roese }
1335*f1df9364SStefan Roese 
ddr3_tip_get_mask_results_dq_reg()1336*f1df9364SStefan Roese u16 *ddr3_tip_get_mask_results_dq_reg()
1337*f1df9364SStefan Roese {
1338*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
1339*f1df9364SStefan Roese 
1340*f1df9364SStefan Roese 	if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1341*f1df9364SStefan Roese 		return mask_results_dq_reg_map_pup3_ecc;
1342*f1df9364SStefan Roese 	else
1343*f1df9364SStefan Roese 		return mask_results_dq_reg_map;
1344*f1df9364SStefan Roese }
1345*f1df9364SStefan Roese 
ddr3_tip_get_mask_results_pup_reg_map()1346*f1df9364SStefan Roese u16 *ddr3_tip_get_mask_results_pup_reg_map()
1347*f1df9364SStefan Roese {
1348*f1df9364SStefan Roese 	struct hws_topology_map *tm = ddr3_get_topology_map();
1349*f1df9364SStefan Roese 
1350*f1df9364SStefan Roese 	if (DDR3_IS_ECC_PUP3_MODE(tm->bus_act_mask))
1351*f1df9364SStefan Roese 		return mask_results_pup_reg_map_pup3_ecc;
1352*f1df9364SStefan Roese 	else
1353*f1df9364SStefan Roese 		return mask_results_pup_reg_map;
1354*f1df9364SStefan Roese }
1355