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