1/*-
2*******************************************************************************
3Copyright (C) 2015 Annapurna Labs Ltd.
4
5This file may be licensed under the terms of the Annapurna Labs Commercial
6License Agreement.
7
8Alternatively, this file can be distributed under the terms of the GNU General
9Public License V2 as published by the Free Software Foundation and can be
10found at http://www.gnu.org/licenses/gpl-2.0.html
11
12Alternatively, redistribution and use in source and binary forms, with or
13without modification, are permitted provided that the following conditions are
14met:
15
16    *     Redistributions of source code must retain the above copyright notice,
17this list of conditions and the following disclaimer.
18
19    *     Redistributions in binary form must reproduce the above copyright
20notice, this list of conditions and the following disclaimer in
21the documentation and/or other materials provided with the
22distribution.
23
24THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31ANY 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
33SOFTWARE, 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
49enum 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
56enum 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
79static 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
203enum al_eth_an_lt_regs {
204	AL_ETH_AN_REGS,
205	AL_ETH_LT_REGS,
206};
207
208static 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
287static 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
366static 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
497void 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
527void 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
554void 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
585void 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
614al_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
625al_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
636al_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
646void 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 *********************************/
653static 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
688static 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
748void 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
805int 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
842int 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
874int 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
897int 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
923void 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
929void 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 *****************************/
960void 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
970void 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
979void 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
999al_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