]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/alpine-hal/eth/al_hal_eth_kr.c
MFC: r362509
[FreeBSD/FreeBSD.git] / sys / contrib / alpine-hal / eth / al_hal_eth_kr.c
1 /*-
2 *******************************************************************************
3 Copyright (C) 2015 Annapurna Labs Ltd.
4
5 This file may be licensed under the terms of the Annapurna Labs Commercial
6 License Agreement.
7
8 Alternatively, this file can be distributed under the terms of the GNU General
9 Public License V2 as published by the Free Software Foundation and can be
10 found at http://www.gnu.org/licenses/gpl-2.0.html
11
12 Alternatively, redistribution and use in source and binary forms, with or
13 without modification, are permitted provided that the following conditions are
14 met:
15
16     *     Redistributions of source code must retain the above copyright notice,
17 this list of conditions and the following disclaimer.
18
19     *     Redistributions in binary form must reproduce the above copyright
20 notice, this list of conditions and the following disclaimer in
21 the documentation and/or other materials provided with the
22 distribution.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34
35 *******************************************************************************/
36 /**
37  *  Ethernet
38  *  @{
39  * @file   al_hal_eth_kr.c
40  *
41  * @brief  KR HAL driver for main functions (auto-neg, Link Training)
42  *
43  */
44
45 #include "al_hal_eth_kr.h"
46 #include "al_hal_eth_mac_regs.h"
47 #include "al_hal_an_lt_wrapper_regs.h"
48
49 enum al_eth_lt_unit_rev {
50         AL_ETH_LT_UNIT_REV_1 = 0,
51         AL_ETH_LT_UNIT_REV_2,
52
53         AL_ETH_LT_UNIT_REV_MAX
54 };
55
56 enum al_eth_an_lt_regs_ids {
57         AL_ETH_KR_AN_CONTROL = 0,
58         AL_ETH_KR_AN_STATUS,
59         AL_ETH_KR_AN_ADV0,
60         AL_ETH_KR_AN_ADV1,
61         AL_ETH_KR_AN_ADV2,
62         AL_ETH_KR_AN_REM_ADV0,
63         AL_ETH_KR_AN_REM_ADV1,
64         AL_ETH_KR_AN_REM_ADV2,
65         AL_ETH_KR_PMD_CONTROL,
66         AL_ETH_KR_PMD_STATUS,
67         AL_ETH_KR_PMD_LP_COEF_UP,
68         AL_ETH_KR_PMD_LP_STATUS_REPORT,
69         AL_ETH_KR_PMD_LD_COEF_UP,
70         AL_ETH_KR_PMD_LD_STATUS_REPORT,
71         AL_ETH_KR_AN_XNP_ADV0,
72         AL_ETH_KR_AN_XNP_ADV1,
73         AL_ETH_KR_AN_XNP_ADV2,
74         AL_ETH_KR_AN_REM_XNP_ADV0,
75         AL_ETH_KR_AN_REM_XNP_ADV1,
76         AL_ETH_KR_AN_REM_XNP_ADV2,
77 };
78
79 static uint32_t al_eth_an_lt_regs_addr[][AL_ETH_LT_UNIT_REV_MAX] = {
80         [AL_ETH_KR_AN_CONTROL]                  =       {0  ,   0x0},
81         [AL_ETH_KR_AN_STATUS]                   =       {1  ,   0x4},
82         [AL_ETH_KR_AN_ADV0]                     =       {16 ,   0x8},
83         [AL_ETH_KR_AN_ADV1]                     =       {17 ,   0xc},
84         [AL_ETH_KR_AN_ADV2]                     =       {18 ,   0x10},
85         [AL_ETH_KR_AN_REM_ADV0]                 =       {19 ,   0x14},
86         [AL_ETH_KR_AN_REM_ADV1]                 =       {20 ,   0x18},
87         [AL_ETH_KR_AN_REM_ADV2]                 =       {21 ,   0x1c},
88         [AL_ETH_KR_PMD_CONTROL]                 =       {150,   0x400},
89         [AL_ETH_KR_PMD_STATUS]                  =       {151,   0x404},
90         [AL_ETH_KR_PMD_LP_COEF_UP]              =       {152,   0x408},
91         [AL_ETH_KR_PMD_LP_STATUS_REPORT]        =       {153,   0x40c},
92         [AL_ETH_KR_PMD_LD_COEF_UP]              =       {154,   0x410},
93         [AL_ETH_KR_PMD_LD_STATUS_REPORT]        =       {155,   0x414},
94         [AL_ETH_KR_AN_XNP_ADV0]                 =       {22 ,   0x24},
95         [AL_ETH_KR_AN_XNP_ADV1]                 =       {23 ,   0x28},
96         [AL_ETH_KR_AN_XNP_ADV2]                 =       {24 ,   0x2c},
97         [AL_ETH_KR_AN_REM_XNP_ADV0]             =       {25 ,   0x30},
98         [AL_ETH_KR_AN_REM_XNP_ADV1]             =       {26 ,   0x34},
99         [AL_ETH_KR_AN_REM_XNP_ADV2]             =       {27 ,   0x38},
100 };
101
102
103 /*
104  * AN(Auto Negotiation) registers
105  * (read / write indirect with al_eth_an_reg_read/write)
106  */
107 #define AL_ETH_KR_AN_CONTROL_RESTART                            AL_BIT(9)
108 #define AL_ETH_KR_AN_CONTROL_ENABLE                             AL_BIT(12)
109 #define AL_ETH_KR_AN_CONTROL_NP_ENABLE                          AL_BIT(13)
110
111 #define AL_ETH_KR_AN_STATUS_COMPLETED                           AL_BIT(5)
112 #define AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED                  AL_BIT(6)
113 #define AL_ETH_KR_AN_STATUS_CHECK_MASK                          0xFF0A
114 #define AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR                      0x0008
115
116 /* AN advertising registers parsing */
117 /* register 1 */
118 #define AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK                        0x001f
119 #define AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT                       0
120 #define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK                     0x03e0
121 #define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT                    5
122 #define AL_ETH_KR_AN_ADV1_CAPABILITY_MASK                       0x1c00
123 #define AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT                      10
124 #define AL_ETH_KR_AN_ADV1_REM_FAULT_MASK                        0x2000
125 #define AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT                       13
126 #define AL_ETH_KR_AN_ADV1_ACK_MASK                              0x4000
127 #define AL_ETH_KR_AN_ADV1_ACK_SHIFT                             14
128 #define AL_ETH_KR_AN_ADV1_NEXT_PAGE_MASK                        0x8000
129 #define AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT                       15
130 /* register 2 */
131 #define AL_ETH_KR_AN_ADV2_TX_NONCE_MASK                         0x001f
132 #define AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT                        0
133 #define AL_ETH_KR_AN_ADV2_TECH_MASK                             0xffe0
134 #define AL_ETH_KR_AN_ADV2_TECH_SHIFT                            5
135 /* register 3 */
136 /* TECH field in the third register is extended to the field in the second
137  * register and it is currently reserved (should be always 0) */
138 #define AL_ETH_KR_AN_ADV3_TECH_MASK                             0x1fff
139 #define AL_ETH_KR_AN_ADV3_TECH_SHIFT                            0
140 #define AL_ETH_KR_AN_ADV3_FEC_MASK                              0xc000
141 #define AL_ETH_KR_AN_ADV3_FEC_SHIFT                             14
142
143 /* Next Page Fields */
144 /* register 1 */
145 #define AL_ETH_KR_AN_NP_ADV1_DATA1_MASK                         0x07ff
146 #define AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT                        0
147 #define AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK                        0x0800
148 #define AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT                       11
149 #define AL_ETH_KR_AN_NP_ADV1_ACK2_MASK                          0x1000
150 #define AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT                         12
151 #define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK                      0x2000
152 #define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT                     13
153 #define AL_ETH_KR_AN_NP_ADV1_NP_MASK                            0x8000
154 #define AL_ETH_KR_AN_NP_ADV1_NP_SHIFT                           15
155
156 /*
157  * LT(Link Training) registers
158  * (read / write indirect with al_eth_pma_reg_read/write)
159  */
160 #define AL_ETH_KR_PMD_CONTROL_RESTART                           0
161 #define AL_ETH_KR_PMD_CONTROL_ENABLE                            1
162
163 #define AL_ETH_KR_PMD_STATUS_RECEIVER_COMPLETED_SHIFT           0
164 #define AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT          1
165 #define AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT 2
166 #define AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT                      3
167
168 #define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK                     0x0003
169 #define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT                    0
170 #define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK                      0x000C
171 #define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT                     2
172 #define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK                      0x0030
173 #define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT                     4
174 #define AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT               12
175 #define AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT                   13
176
177 #define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK               0x0003
178 #define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT              0
179 #define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK                0x000C
180 #define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT               2
181 #define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK                0x0030
182 #define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT               4
183 #define AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT            15
184
185 #define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK                     0x0003
186 #define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT                    0
187 #define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK                      0x000C
188 #define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT                     2
189 #define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK                      0x0030
190 #define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT                     4
191 #define AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT               12
192 #define AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT                   13
193
194 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK               0x0003
195 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT              0
196 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK                0x000C
197 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT               2
198 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK                0x0030
199 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT               4
200 #define AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT     15
201
202
203 enum al_eth_an_lt_regs {
204         AL_ETH_AN_REGS,
205         AL_ETH_LT_REGS,
206 };
207
208 static uint16_t al_eth_an_lt_reg_read(
209                         struct al_hal_eth_adapter *adapter,
210                         enum al_eth_an_lt_regs_ids reg_id,
211                         enum al_eth_an_lt_regs an_lt,
212                         enum al_eth_an_lt_lane lane)
213 {
214         uint32_t val;
215         uint16_t reg_addr;
216
217         if (adapter->rev_id < AL_ETH_REV_ID_3) {
218                 al_assert(lane == AL_ETH_AN__LT_LANE_0);
219
220                 reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1];
221                 if (an_lt == AL_ETH_AN_REGS) {
222                         al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr);
223                         val = al_reg_read32(&adapter->mac_regs_base->kr.an_data);
224                 } else {
225                         al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr);
226                         val = al_reg_read32(&adapter->mac_regs_base->kr.pma_data);
227                 }
228         } else {
229                 struct al_an_lt_wrapper_regs *regs = NULL;
230
231                 reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2];
232
233                 switch (lane) {
234                 case AL_ETH_AN__LT_LANE_0:
235                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
236                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
237                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
238                                        reg_addr);
239
240                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
241                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
242                         val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_0_data);
243                         break;
244                 case AL_ETH_AN__LT_LANE_1:
245                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
246                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
247                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
248                                        reg_addr);
249
250                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
251                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
252                         val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_1_data);
253                         break;
254                 case AL_ETH_AN__LT_LANE_2:
255                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
256                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
257                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
258                                        reg_addr);
259
260                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
261                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
262                         val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_2_data);
263                         break;
264                 case AL_ETH_AN__LT_LANE_3:
265                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
266                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
267                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
268                                        reg_addr);
269
270                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
271                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
272                         val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_3_data);
273                         break;
274                 default:
275                         al_err("%s: Unknown Lane %d\n", __func__, lane);
276                         return 0;
277                 }
278         }
279
280
281         al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__,
282                (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val);
283
284         return (uint16_t)val;
285 }
286
287 static void al_eth_an_lt_reg_write(
288                         struct al_hal_eth_adapter *adapter,
289                         enum al_eth_an_lt_regs_ids reg_id,
290                         enum al_eth_an_lt_regs an_lt,
291                         enum al_eth_an_lt_lane lane,
292                         uint16_t val)
293 {
294         uint16_t reg_addr;
295
296         if (adapter->rev_id < AL_ETH_REV_ID_3) {
297                 reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1];
298                 if (an_lt == AL_ETH_AN_REGS) {
299                         al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr);
300                         al_reg_write32(&adapter->mac_regs_base->kr.an_data, val);
301                 } else {
302                         al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr);
303                         al_reg_write32(&adapter->mac_regs_base->kr.pma_data, val);
304                 }
305         } else {
306                 struct al_an_lt_wrapper_regs *regs = NULL;
307
308                 reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2];
309
310                 switch (lane) {
311                 case AL_ETH_AN__LT_LANE_0:
312                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
313                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
314                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
315                                        reg_addr);
316
317                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
318                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
319                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
320                                        val);
321                         break;
322                 case AL_ETH_AN__LT_LANE_1:
323                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
324                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
325                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
326                                        reg_addr);
327
328                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
329                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
330                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
331                                        val);
332                         break;
333                 case AL_ETH_AN__LT_LANE_2:
334                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
335                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
336                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
337                                        reg_addr);
338
339                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
340                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
341                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
342                                        val);
343                         break;
344                 case AL_ETH_AN__LT_LANE_3:
345                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
346                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
347                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
348                                        reg_addr);
349
350                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
351                                        (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
352                         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
353                                        val);
354                         break;
355                 default:
356                         al_err("%s: Unknown Lane %d\n", __func__, lane);
357                         return;
358                 }
359         }
360
361
362         al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__,
363                (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val);
364 }
365
366 static void al_eth_an_lt_unit_config(struct al_hal_eth_adapter *adapter)
367 {
368         struct al_an_lt_wrapper_regs *regs = NULL;
369         uint32_t cfg_lane_0 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
370         uint32_t cfg_lane_1 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
371         uint32_t cfg_lane_2 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
372         uint32_t cfg_lane_3 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
373
374         switch (adapter->mac_mode) {
375         case AL_ETH_MAC_MODE_10GbE_Serial:
376                 cfg_lane_0 = 0;
377                 AL_REG_FIELD_SET(cfg_lane_0,
378                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
379                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
380                                  AL_ETH_AN_LT_UNIT_20_BIT);
381                 AL_REG_FIELD_SET(cfg_lane_0,
382                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
383                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
384                                  AL_ETH_AN_LT_UNIT_20_BIT);
385
386                 adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_20_BIT;
387
388                 break;
389         case AL_ETH_MAC_MODE_KR_LL_25G:
390                 cfg_lane_0 = 0;
391                 AL_REG_FIELD_SET(cfg_lane_0,
392                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
393                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
394                                  AL_ETH_AN_LT_UNIT_32_BIT);
395                 AL_REG_FIELD_SET(cfg_lane_0,
396                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
397                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
398                                  AL_ETH_AN_LT_UNIT_32_BIT);
399
400                 adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT;
401
402                 break;
403         case AL_ETH_MAC_MODE_XLG_LL_40G:
404                 cfg_lane_0 = 0;
405                 AL_REG_FIELD_SET(cfg_lane_0,
406                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
407                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
408                                  AL_ETH_AN_LT_UNIT_16_BIT);
409                 AL_REG_FIELD_SET(cfg_lane_0,
410                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
411                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
412                                  AL_ETH_AN_LT_UNIT_16_BIT);
413
414                 cfg_lane_1 = 0;
415                 AL_REG_FIELD_SET(cfg_lane_1,
416                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
417                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
418                                  AL_ETH_AN_LT_UNIT_16_BIT);
419                 AL_REG_FIELD_SET(cfg_lane_1,
420                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
421                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
422                                  AL_ETH_AN_LT_UNIT_16_BIT);
423
424                 cfg_lane_2 = 0;
425                 AL_REG_FIELD_SET(cfg_lane_2,
426                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
427                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
428                                  AL_ETH_AN_LT_UNIT_16_BIT);
429                 AL_REG_FIELD_SET(cfg_lane_2,
430                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
431                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
432                                  AL_ETH_AN_LT_UNIT_16_BIT);
433
434                 cfg_lane_3 = 0;
435                 AL_REG_FIELD_SET(cfg_lane_3,
436                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
437                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
438                                  AL_ETH_AN_LT_UNIT_16_BIT);
439                 AL_REG_FIELD_SET(cfg_lane_3,
440                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
441                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
442                                  AL_ETH_AN_LT_UNIT_16_BIT);
443
444                 adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_16_BIT;
445
446                 break;
447         case AL_ETH_MAC_MODE_XLG_LL_50G:
448                 cfg_lane_0 = 0;
449                 AL_REG_FIELD_SET(cfg_lane_0,
450                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
451                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
452                                  AL_ETH_AN_LT_UNIT_32_BIT);
453                 AL_REG_FIELD_SET(cfg_lane_0,
454                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
455                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
456                                  AL_ETH_AN_LT_UNIT_32_BIT);
457
458                 cfg_lane_1 = 0;
459                 AL_REG_FIELD_SET(cfg_lane_1,
460                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
461                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
462                                  AL_ETH_AN_LT_UNIT_32_BIT);
463                 AL_REG_FIELD_SET(cfg_lane_1,
464                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
465                                  AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
466                                  AL_ETH_AN_LT_UNIT_32_BIT);
467
468                 adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT;
469
470                 break;
471         default:
472                 al_err("%s: Unknown mac_mode\n", __func__);
473                 return;
474         }
475
476         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
477                        (uintptr_t)&regs->gen.cfg);
478         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
479                        cfg_lane_0);
480
481         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
482                        (uintptr_t)&regs->gen.cfg);
483         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
484                        cfg_lane_1);
485
486         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
487                        (uintptr_t)&regs->gen.cfg);
488         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
489                        cfg_lane_2);
490
491         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
492                        (uintptr_t)&regs->gen.cfg);
493         al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
494                        cfg_lane_3);
495 }
496
497 void al_eth_lp_coeff_up_get(
498                         struct al_hal_eth_adapter *adapter,
499                         enum al_eth_an_lt_lane lane,
500                         struct al_eth_kr_coef_up_data *lpcoeff)
501 {
502         uint16_t reg;
503
504         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_COEF_UP, AL_ETH_LT_REGS, lane);
505
506         lpcoeff->preset =
507                 (AL_REG_BIT_GET(
508                         reg, AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT) != 0);
509
510         lpcoeff->initialize =
511                 (AL_REG_BIT_GET(
512                         reg, AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT) != 0);
513
514         lpcoeff->c_minus = AL_REG_FIELD_GET(reg,
515                                         AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK,
516                                         AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT);
517
518         lpcoeff->c_zero = AL_REG_FIELD_GET(reg,
519                                         AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK,
520                                         AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT);
521
522         lpcoeff->c_plus = AL_REG_FIELD_GET(reg,
523                                         AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK,
524                                         AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT);
525 }
526
527 void al_eth_lp_status_report_get(
528                         struct al_hal_eth_adapter *adapter,
529                         enum al_eth_an_lt_lane lane,
530                         struct al_eth_kr_status_report_data *status)
531 {
532         uint16_t reg;
533
534         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_STATUS_REPORT, AL_ETH_LT_REGS, lane);
535
536         status->c_minus = AL_REG_FIELD_GET(reg,
537                                     AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK,
538                                     AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT);
539
540         status->c_zero = AL_REG_FIELD_GET(reg,
541                                    AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK,
542                                    AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT);
543
544         status->c_plus = AL_REG_FIELD_GET(reg,
545                                    AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK,
546                                    AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT);
547
548         status->receiver_ready =
549                 (AL_REG_BIT_GET(
550                         reg, AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT) != 0);
551
552 }
553
554 void al_eth_ld_coeff_up_set(
555                         struct al_hal_eth_adapter *adapter,
556                         enum al_eth_an_lt_lane lane,
557                         struct al_eth_kr_coef_up_data *ldcoeff)
558 {
559         uint16_t reg = 0;
560
561         if (ldcoeff->preset)
562                 AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT);
563
564         if (ldcoeff->initialize)
565                 AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT);
566
567         AL_REG_FIELD_SET(reg,
568                          AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK,
569                          AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT,
570                          ldcoeff->c_minus);
571
572         AL_REG_FIELD_SET(reg,
573                          AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK,
574                          AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT,
575                          ldcoeff->c_zero);
576
577         AL_REG_FIELD_SET(reg,
578                          AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK,
579                          AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT,
580                          ldcoeff->c_plus);
581
582         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, reg);
583 }
584
585 void al_eth_ld_status_report_set(
586                         struct al_hal_eth_adapter *adapter,
587                         enum al_eth_an_lt_lane lane,
588                         struct al_eth_kr_status_report_data *status)
589 {
590         uint16_t reg = 0;
591
592         AL_REG_FIELD_SET(reg,
593                          AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK,
594                          AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT,
595                          status->c_minus);
596
597         AL_REG_FIELD_SET(reg,
598                          AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK,
599                          AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT,
600                          status->c_zero);
601
602         AL_REG_FIELD_SET(reg,
603                          AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK,
604                          AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT,
605                          status->c_plus);
606
607         if (status->receiver_ready)
608                 AL_REG_BIT_SET(reg,
609                         AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT);
610
611         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, reg);
612 }
613
614 al_bool al_eth_kr_receiver_frame_lock_get(struct al_hal_eth_adapter *adapter,
615                                           enum al_eth_an_lt_lane lane)
616 {
617         uint16_t reg;
618
619         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
620
621         return (AL_REG_BIT_GET(reg,
622                         AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT) != 0);
623 }
624
625 al_bool al_eth_kr_startup_proto_prog_get(struct al_hal_eth_adapter *adapter,
626                                          enum al_eth_an_lt_lane lane)
627 {
628         uint16_t reg;
629
630         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
631
632         return (AL_REG_BIT_GET(
633                 reg, AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT) != 0);
634 }
635
636 al_bool al_eth_kr_training_status_fail_get(struct al_hal_eth_adapter *adapter,
637                                            enum al_eth_an_lt_lane lane)
638 {
639         uint16_t reg;
640
641         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
642
643         return (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT) != 0);
644 }
645
646 void al_eth_receiver_ready_set(struct al_hal_eth_adapter *adapter,
647                                enum al_eth_an_lt_lane lane)
648 {
649         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 1);
650 }
651
652 /*************************** auto negotiation *********************************/
653 static int al_eth_kr_an_validate_adv(struct al_hal_eth_adapter *adapter,
654                                      struct al_eth_an_adv *an_adv)
655 {
656         al_assert(adapter);
657
658         if (an_adv == NULL)
659                 return 0;
660
661         if (an_adv->selector_field != 1) {
662                 al_err("[%s]: %s failed on selector_field (%d)\n",
663                         adapter->name, __func__, an_adv->selector_field);
664                 return -EINVAL;
665         }
666
667         if (an_adv->capability & AL_BIT(2)) {
668                 al_err("[%s]: %s failed on capability bit 2 (%d)\n",
669                         adapter->name, __func__, an_adv->capability);
670                 return -EINVAL;
671         }
672
673         if (an_adv->remote_fault) {
674                 al_err("[%s]: %s failed on remote_fault (%d)\n",
675                         adapter->name, __func__, an_adv->remote_fault);
676                 return -EINVAL;
677         }
678
679         if (an_adv->acknowledge) {
680                 al_err("[%s]: %s failed on acknowledge (%d)\n",
681                         adapter->name, __func__, an_adv->acknowledge);
682                 return -EINVAL;
683         }
684
685         return 0;
686 }
687
688 static int al_eth_kr_an_write_adv(struct al_hal_eth_adapter *adapter,
689                                struct al_eth_an_adv *an_adv)
690 {
691         uint16_t        reg;
692
693         if(an_adv == NULL)
694                 return 0;
695
696         reg = 0;
697         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK,
698                          AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT,
699                          an_adv->selector_field);
700
701         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK,
702                          AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT,
703                          an_adv->echoed_nonce);
704
705         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_CAPABILITY_MASK,
706                          AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT,
707                          an_adv->capability);
708
709         AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT,
710                            an_adv->remote_fault);
711
712         AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_ACK_SHIFT,
713                            an_adv->acknowledge);
714
715         AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT,
716                            an_adv->next_page);
717
718         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV0, AL_ETH_AN_REGS,
719                                AL_ETH_AN__LT_LANE_0, reg);
720
721         reg = 0;
722         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TX_NONCE_MASK,
723                          AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT,
724                          an_adv->transmitted_nonce);
725
726         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TECH_MASK,
727                          AL_ETH_KR_AN_ADV2_TECH_SHIFT,
728                          an_adv->technology);
729
730         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV1, AL_ETH_AN_REGS,
731                                AL_ETH_AN__LT_LANE_0, reg);
732
733         reg = 0;
734         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_TECH_MASK,
735                          AL_ETH_KR_AN_ADV3_TECH_SHIFT,
736                          an_adv->technology >> 11);
737
738         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_FEC_MASK,
739                          AL_ETH_KR_AN_ADV3_FEC_SHIFT,
740                          an_adv->fec_capability);
741
742         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV2, AL_ETH_AN_REGS,
743                                AL_ETH_AN__LT_LANE_0, reg);
744
745         return 0;
746 }
747
748 void al_eth_kr_an_read_adv(struct al_hal_eth_adapter *adapter,
749                            struct al_eth_an_adv *an_adv)
750 {
751         int16_t reg;
752
753         al_assert(an_adv != NULL);
754
755
756         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV0,
757                                     AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
758
759         an_adv->selector_field = AL_REG_FIELD_GET(reg,
760                                         AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK,
761                                         AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT);
762
763         an_adv->echoed_nonce = AL_REG_FIELD_GET(reg,
764                                         AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK,
765                                         AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT);
766
767         an_adv->capability = AL_REG_FIELD_GET(reg,
768                                         AL_ETH_KR_AN_ADV1_CAPABILITY_MASK,
769                                         AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT);
770
771         an_adv->remote_fault = AL_REG_BIT_GET(reg,
772                                         AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT);
773
774         an_adv->acknowledge = AL_REG_BIT_GET(reg,
775                                         AL_ETH_KR_AN_ADV1_ACK_SHIFT);
776
777         an_adv->next_page = AL_REG_BIT_GET(reg,
778                                         AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT);
779
780
781         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV1,
782                                     AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
783
784         an_adv->transmitted_nonce = AL_REG_FIELD_GET(reg,
785                                          AL_ETH_KR_AN_ADV2_TX_NONCE_MASK,
786                                          AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT);
787
788         an_adv->technology = AL_REG_FIELD_GET(reg,
789                                          AL_ETH_KR_AN_ADV2_TECH_MASK,
790                                          AL_ETH_KR_AN_ADV2_TECH_SHIFT);
791
792
793         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV2,
794                                     AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
795
796         an_adv->technology |= (AL_REG_FIELD_GET(reg,
797                                         AL_ETH_KR_AN_ADV3_TECH_MASK,
798                                         AL_ETH_KR_AN_ADV3_TECH_SHIFT)  << 11);
799
800         an_adv->fec_capability = AL_REG_FIELD_GET(reg,
801                                          AL_ETH_KR_AN_ADV3_FEC_MASK,
802                                          AL_ETH_KR_AN_ADV3_FEC_SHIFT);
803 }
804
805 int al_eth_kr_next_page_read(struct al_hal_eth_adapter *adapter,
806                              struct al_eth_an_np *np)
807 {
808         uint16_t reg;
809
810         reg = al_eth_an_lt_reg_read(adapter,
811                                     AL_ETH_KR_AN_REM_XNP_ADV0,
812                                     AL_ETH_AN_REGS,
813                                     AL_ETH_AN__LT_LANE_0);
814
815         np->unformatted_code_field = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK,
816                                          AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT);
817
818         np->toggle = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK,
819                                          AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT);
820
821         np->ack2 = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK,
822                                          AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT);
823
824         np->msg_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK,
825                                          AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT);
826
827         np->next_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK,
828                                          AL_ETH_KR_AN_NP_ADV1_NP_SHIFT);
829
830         np->unformatted_code_field1 = al_eth_an_lt_reg_read(adapter,
831                                                             AL_ETH_KR_AN_REM_XNP_ADV1,
832                                                             AL_ETH_AN_REGS,
833                                                             AL_ETH_AN__LT_LANE_0);
834         np->unformatted_code_field2 = al_eth_an_lt_reg_read(adapter,
835                                                             AL_ETH_KR_AN_REM_XNP_ADV2,
836                                                             AL_ETH_AN_REGS,
837                                                             AL_ETH_AN__LT_LANE_0);
838
839         return 0;
840 }
841
842 int al_eth_kr_next_page_write(struct al_hal_eth_adapter *adapter,
843                               struct al_eth_an_np *np)
844 {
845         uint16_t reg = 0;
846
847         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK,
848                          AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT,
849                          np->unformatted_code_field);
850         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK,
851                          AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT,
852                          np->toggle);
853         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK,
854                          AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT,
855                          np->ack2);
856         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK,
857                          AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT,
858                          np->msg_page);
859         AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK,
860                          AL_ETH_KR_AN_NP_ADV1_NP_SHIFT,
861                          np->next_page);
862
863         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV0, AL_ETH_AN_REGS,
864                                AL_ETH_AN__LT_LANE_0, reg);
865
866         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV1, AL_ETH_AN_REGS,
867                                AL_ETH_AN__LT_LANE_0, np->unformatted_code_field1);
868         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV2, AL_ETH_AN_REGS,
869                                AL_ETH_AN__LT_LANE_0, np->unformatted_code_field2);
870
871         return 0;
872 }
873
874 int al_eth_kr_an_init(struct al_hal_eth_adapter *adapter,
875                       struct al_eth_an_adv *an_adv)
876 {
877         int             rc;
878
879         if (adapter->rev_id > AL_ETH_REV_ID_2)
880                 al_eth_an_lt_unit_config(adapter);
881
882         rc = al_eth_kr_an_validate_adv(adapter, an_adv);
883         if (rc)
884                 return rc;
885
886         rc = al_eth_kr_an_write_adv(adapter, an_adv);
887         if (rc)
888                 return rc;
889
890         /* clear status */
891         al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS, AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
892
893         al_dbg("[%s]: autonegotiation initialized successfully", adapter->name);
894         return 0;
895 }
896
897 int al_eth_kr_an_start(struct al_hal_eth_adapter *adapter,
898                        enum al_eth_an_lt_lane lane,
899                        al_bool next_page_enable,
900                        al_bool lt_enable)
901 {
902         uint16_t control = AL_ETH_KR_AN_CONTROL_ENABLE | AL_ETH_KR_AN_CONTROL_RESTART;
903
904         al_dbg("Eth [%s]: enable autonegotiation. lt_en %s",
905                 adapter->name, (lt_enable == AL_TRUE) ? "yes" : "no");
906
907         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS,
908                                lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART));
909
910         if (next_page_enable == AL_TRUE)
911                 control |= AL_ETH_KR_AN_CONTROL_NP_ENABLE;
912
913         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS,
914                                lane, control);
915
916         if (lt_enable == AL_TRUE) {
917                 al_eth_kr_lt_initialize(adapter, lane);
918         }
919
920         return 0;
921 }
922
923 void al_eth_kr_an_stop(struct al_hal_eth_adapter *adapter)
924 {
925         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS,
926                                AL_ETH_AN__LT_LANE_0, 0);
927 }
928
929 void al_eth_kr_an_status_check(struct al_hal_eth_adapter *adapter,
930                               al_bool *page_received,
931                               al_bool *an_completed,
932                               al_bool *error)
933 {
934         uint16_t        reg;
935
936         reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS,
937                                     AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
938
939         if ((reg & AL_ETH_KR_AN_STATUS_CHECK_MASK) !=
940                                 AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR) {
941                 al_err("[%s]: %s AN_STATUS (0x%x) indicated error\n",
942                         adapter->name, __func__, reg);
943
944                 *error = AL_TRUE;
945         }
946
947         if (reg & AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED)
948                 *page_received = AL_TRUE;
949         else
950                 *page_received = AL_FALSE;
951
952         if (reg & AL_ETH_KR_AN_STATUS_COMPLETED)
953                 *an_completed = AL_TRUE;
954         else
955                 *an_completed = AL_FALSE;
956 }
957
958
959 /****************************** KR Link Training *****************************/
960 void al_eth_kr_lt_restart(struct al_hal_eth_adapter *adapter,
961                           enum al_eth_an_lt_lane lane)
962 {
963         al_dbg("[%s]: KR LT Restart Link Training.\n", adapter->name);
964
965         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS,
966                                lane, (AL_BIT(AL_ETH_KR_PMD_CONTROL_ENABLE) |
967                                       AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART)));
968 }
969
970 void al_eth_kr_lt_stop(struct al_hal_eth_adapter *adapter,
971                        enum al_eth_an_lt_lane lane)
972 {
973         al_dbg("[%s]: KR LT Stop Link Training.\n", adapter->name);
974
975         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS,
976                                lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART));
977 }
978
979 void al_eth_kr_lt_initialize(struct al_hal_eth_adapter *adapter,
980                              enum al_eth_an_lt_lane lane)
981 {
982         al_dbg("[%s]: KR LT Initialize.\n", adapter->name);
983
984         /* Reset LT state machine */
985         al_eth_kr_lt_stop(adapter, lane);
986
987         /* clear receiver status */
988         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 0);
989
990         /* Coefficient Update to all zero (no command, hold) */
991         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, 0);
992         /* Coefficient Status to all zero (not_updated) */
993         al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, 0);
994
995         /* start */
996         al_eth_kr_lt_restart(adapter, lane);
997 }
998
999 al_bool al_eth_kr_lt_frame_lock_wait(struct al_hal_eth_adapter *adapter,
1000                                      enum al_eth_an_lt_lane lane,
1001                                      uint32_t timeout)
1002 {
1003         uint32_t loop;
1004         uint16_t reg = 0;
1005
1006         for (loop = 0; loop < timeout; loop++) {
1007                 reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
1008
1009                 if (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT)) {
1010                         al_info("[%s]: Failed on Training Failure."
1011                                " loops %d PMD STATUS 0x%04x\n",
1012                                adapter->name, loop, reg);
1013
1014                         return AL_FALSE;
1015                 }
1016                 if (AL_REG_BIT_GET(reg,
1017                         AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT)) {
1018                         al_dbg("[%s]: Frame lock received."
1019                                " loops %d PMD STATUS 0x%04x\n",
1020                                adapter->name, loop, reg);
1021
1022                         return AL_TRUE;
1023                 }
1024                 al_udelay(1);
1025         }
1026         al_info("[%s]: Failed on timeout. PMD STATUS 0x%04x\n",
1027                         adapter->name, reg);
1028
1029         return AL_FALSE;
1030 }