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
al_eth_an_lt_reg_read(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_regs_ids reg_id,enum al_eth_an_lt_regs an_lt,enum al_eth_an_lt_lane lane)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)®s->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)®s->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)®s->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)®s->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)®s->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)®s->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)®s->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)®s->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
al_eth_an_lt_reg_write(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_regs_ids reg_id,enum al_eth_an_lt_regs an_lt,enum al_eth_an_lt_lane lane,uint16_t val)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)®s->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)®s->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)®s->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)®s->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)®s->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)®s->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)®s->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)®s->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
al_eth_an_lt_unit_config(struct al_hal_eth_adapter * adapter)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)®s->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)®s->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)®s->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)®s->gen.cfg);
493 al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
494 cfg_lane_3);
495 }
496
al_eth_lp_coeff_up_get(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane,struct al_eth_kr_coef_up_data * lpcoeff)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
al_eth_lp_status_report_get(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane,struct al_eth_kr_status_report_data * status)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
al_eth_ld_coeff_up_set(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane,struct al_eth_kr_coef_up_data * ldcoeff)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
al_eth_ld_status_report_set(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane,struct al_eth_kr_status_report_data * status)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
al_eth_kr_receiver_frame_lock_get(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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
al_eth_kr_startup_proto_prog_get(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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
al_eth_kr_training_status_fail_get(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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
al_eth_receiver_ready_set(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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 *********************************/
al_eth_kr_an_validate_adv(struct al_hal_eth_adapter * adapter,struct al_eth_an_adv * an_adv)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
al_eth_kr_an_write_adv(struct al_hal_eth_adapter * adapter,struct al_eth_an_adv * an_adv)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
al_eth_kr_an_read_adv(struct al_hal_eth_adapter * adapter,struct al_eth_an_adv * an_adv)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
al_eth_kr_next_page_read(struct al_hal_eth_adapter * adapter,struct al_eth_an_np * np)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
al_eth_kr_next_page_write(struct al_hal_eth_adapter * adapter,struct al_eth_an_np * np)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
al_eth_kr_an_init(struct al_hal_eth_adapter * adapter,struct al_eth_an_adv * an_adv)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
al_eth_kr_an_start(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane,al_bool next_page_enable,al_bool lt_enable)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
al_eth_kr_an_stop(struct al_hal_eth_adapter * adapter)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
al_eth_kr_an_status_check(struct al_hal_eth_adapter * adapter,al_bool * page_received,al_bool * an_completed,al_bool * error)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 *****************************/
al_eth_kr_lt_restart(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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
al_eth_kr_lt_stop(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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
al_eth_kr_lt_initialize(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane)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
al_eth_kr_lt_frame_lock_wait(struct al_hal_eth_adapter * adapter,enum al_eth_an_lt_lane lane,uint32_t timeout)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 }
1031