1294838Szbb/*-
2294838Szbb*******************************************************************************
3294838SzbbCopyright (C) 2015 Annapurna Labs Ltd.
4294838Szbb
5294838SzbbThis file may be licensed under the terms of the Annapurna Labs Commercial
6294838SzbbLicense Agreement.
7294838Szbb
8294838SzbbAlternatively, this file can be distributed under the terms of the GNU General
9294838SzbbPublic License V2 as published by the Free Software Foundation and can be
10294838Szbbfound at http://www.gnu.org/licenses/gpl-2.0.html
11294838Szbb
12294838SzbbAlternatively, redistribution and use in source and binary forms, with or
13294838Szbbwithout modification, are permitted provided that the following conditions are
14294838Szbbmet:
15294838Szbb
16294838Szbb    *     Redistributions of source code must retain the above copyright notice,
17294838Szbbthis list of conditions and the following disclaimer.
18294838Szbb
19294838Szbb    *     Redistributions in binary form must reproduce the above copyright
20294838Szbbnotice, this list of conditions and the following disclaimer in
21294838Szbbthe documentation and/or other materials provided with the
22294838Szbbdistribution.
23294838Szbb
24294838SzbbTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
25294838SzbbANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
26294838SzbbWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27294838SzbbDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
28294838SzbbANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29294838Szbb(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30294838SzbbLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31294838SzbbANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32294838Szbb(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33294838SzbbSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34294838Szbb
35294838Szbb*******************************************************************************/
36294838Szbb/**
37294838Szbb *  Ethernet
38294838Szbb *  @{
39294838Szbb * @file   al_hal_eth_kr.c
40294838Szbb *
41294838Szbb * @brief  KR HAL driver for main functions (auto-neg, Link Training)
42294838Szbb *
43294838Szbb */
44294838Szbb
45294838Szbb#include "al_hal_eth_kr.h"
46294838Szbb#include "al_hal_eth_mac_regs.h"
47294838Szbb#include "al_hal_an_lt_wrapper_regs.h"
48294838Szbb
49294838Szbbenum al_eth_lt_unit_rev {
50294838Szbb	AL_ETH_LT_UNIT_REV_1 = 0,
51294838Szbb	AL_ETH_LT_UNIT_REV_2,
52294838Szbb
53294838Szbb	AL_ETH_LT_UNIT_REV_MAX
54294838Szbb};
55294838Szbb
56294838Szbbenum al_eth_an_lt_regs_ids {
57294838Szbb	AL_ETH_KR_AN_CONTROL = 0,
58294838Szbb	AL_ETH_KR_AN_STATUS,
59294838Szbb	AL_ETH_KR_AN_ADV0,
60294838Szbb	AL_ETH_KR_AN_ADV1,
61294838Szbb	AL_ETH_KR_AN_ADV2,
62294838Szbb	AL_ETH_KR_AN_REM_ADV0,
63294838Szbb	AL_ETH_KR_AN_REM_ADV1,
64294838Szbb	AL_ETH_KR_AN_REM_ADV2,
65294838Szbb	AL_ETH_KR_PMD_CONTROL,
66294838Szbb	AL_ETH_KR_PMD_STATUS,
67294838Szbb	AL_ETH_KR_PMD_LP_COEF_UP,
68294838Szbb	AL_ETH_KR_PMD_LP_STATUS_REPORT,
69294838Szbb	AL_ETH_KR_PMD_LD_COEF_UP,
70294838Szbb	AL_ETH_KR_PMD_LD_STATUS_REPORT,
71294838Szbb	AL_ETH_KR_AN_XNP_ADV0,
72294838Szbb	AL_ETH_KR_AN_XNP_ADV1,
73294838Szbb	AL_ETH_KR_AN_XNP_ADV2,
74294838Szbb	AL_ETH_KR_AN_REM_XNP_ADV0,
75294838Szbb	AL_ETH_KR_AN_REM_XNP_ADV1,
76294838Szbb	AL_ETH_KR_AN_REM_XNP_ADV2,
77294838Szbb};
78294838Szbb
79294838Szbbstatic uint32_t al_eth_an_lt_regs_addr[][AL_ETH_LT_UNIT_REV_MAX] = {
80294838Szbb	[AL_ETH_KR_AN_CONTROL]			=	{0  ,	0x0},
81294838Szbb	[AL_ETH_KR_AN_STATUS]			=	{1  ,	0x4},
82294838Szbb	[AL_ETH_KR_AN_ADV0]			=	{16 ,	0x8},
83294838Szbb	[AL_ETH_KR_AN_ADV1]			=	{17 ,	0xc},
84294838Szbb	[AL_ETH_KR_AN_ADV2]			=	{18 ,	0x10},
85294838Szbb	[AL_ETH_KR_AN_REM_ADV0]			=	{19 ,	0x14},
86294838Szbb	[AL_ETH_KR_AN_REM_ADV1]			=	{20 ,	0x18},
87294838Szbb	[AL_ETH_KR_AN_REM_ADV2]			=	{21 ,	0x1c},
88294838Szbb	[AL_ETH_KR_PMD_CONTROL]			=	{150,	0x400},
89294838Szbb	[AL_ETH_KR_PMD_STATUS]			=	{151,	0x404},
90294838Szbb	[AL_ETH_KR_PMD_LP_COEF_UP]		=	{152,	0x408},
91294838Szbb	[AL_ETH_KR_PMD_LP_STATUS_REPORT]	=	{153,	0x40c},
92294838Szbb	[AL_ETH_KR_PMD_LD_COEF_UP]		=	{154,	0x410},
93294838Szbb	[AL_ETH_KR_PMD_LD_STATUS_REPORT]	=	{155,	0x414},
94294838Szbb	[AL_ETH_KR_AN_XNP_ADV0]			=	{22 ,   0x24},
95294838Szbb	[AL_ETH_KR_AN_XNP_ADV1]			=	{23 ,   0x28},
96294838Szbb	[AL_ETH_KR_AN_XNP_ADV2]			=	{24 ,   0x2c},
97294838Szbb	[AL_ETH_KR_AN_REM_XNP_ADV0]		=	{25 ,   0x30},
98294838Szbb	[AL_ETH_KR_AN_REM_XNP_ADV1]		=	{26 ,   0x34},
99294838Szbb	[AL_ETH_KR_AN_REM_XNP_ADV2]		=	{27 ,   0x38},
100294838Szbb};
101294838Szbb
102294838Szbb
103294838Szbb/*
104294838Szbb * AN(Auto Negotiation) registers
105294838Szbb * (read / write indirect with al_eth_an_reg_read/write)
106294838Szbb */
107294838Szbb#define AL_ETH_KR_AN_CONTROL_RESTART				AL_BIT(9)
108294838Szbb#define AL_ETH_KR_AN_CONTROL_ENABLE				AL_BIT(12)
109294838Szbb#define AL_ETH_KR_AN_CONTROL_NP_ENABLE				AL_BIT(13)
110294838Szbb
111294838Szbb#define AL_ETH_KR_AN_STATUS_COMPLETED				AL_BIT(5)
112294838Szbb#define AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED			AL_BIT(6)
113294838Szbb#define AL_ETH_KR_AN_STATUS_CHECK_MASK				0xFF0A
114294838Szbb#define AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR			0x0008
115294838Szbb
116294838Szbb/* AN advertising registers parsing */
117294838Szbb/* register 1 */
118294838Szbb#define AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK			0x001f
119294838Szbb#define AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT			0
120294838Szbb#define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK			0x03e0
121294838Szbb#define AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT			5
122294838Szbb#define AL_ETH_KR_AN_ADV1_CAPABILITY_MASK			0x1c00
123294838Szbb#define AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT			10
124294838Szbb#define AL_ETH_KR_AN_ADV1_REM_FAULT_MASK			0x2000
125294838Szbb#define AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT			13
126294838Szbb#define AL_ETH_KR_AN_ADV1_ACK_MASK				0x4000
127294838Szbb#define AL_ETH_KR_AN_ADV1_ACK_SHIFT				14
128294838Szbb#define AL_ETH_KR_AN_ADV1_NEXT_PAGE_MASK			0x8000
129294838Szbb#define AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT			15
130294838Szbb/* register 2 */
131294838Szbb#define AL_ETH_KR_AN_ADV2_TX_NONCE_MASK				0x001f
132294838Szbb#define AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT			0
133294838Szbb#define AL_ETH_KR_AN_ADV2_TECH_MASK				0xffe0
134294838Szbb#define AL_ETH_KR_AN_ADV2_TECH_SHIFT				5
135294838Szbb/* register 3 */
136294838Szbb/* TECH field in the third register is extended to the field in the second
137294838Szbb * register and it is currently reserved (should be always 0) */
138294838Szbb#define AL_ETH_KR_AN_ADV3_TECH_MASK				0x1fff
139294838Szbb#define AL_ETH_KR_AN_ADV3_TECH_SHIFT				0
140294838Szbb#define AL_ETH_KR_AN_ADV3_FEC_MASK				0xc000
141294838Szbb#define AL_ETH_KR_AN_ADV3_FEC_SHIFT				14
142294838Szbb
143294838Szbb/* Next Page Fields */
144294838Szbb/* register 1 */
145294838Szbb#define AL_ETH_KR_AN_NP_ADV1_DATA1_MASK				0x07ff
146294838Szbb#define AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT			0
147294838Szbb#define AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK			0x0800
148294838Szbb#define AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT			11
149294838Szbb#define AL_ETH_KR_AN_NP_ADV1_ACK2_MASK				0x1000
150294838Szbb#define AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT				12
151294838Szbb#define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK			0x2000
152294838Szbb#define AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT			13
153294838Szbb#define AL_ETH_KR_AN_NP_ADV1_NP_MASK				0x8000
154294838Szbb#define AL_ETH_KR_AN_NP_ADV1_NP_SHIFT				15
155294838Szbb
156294838Szbb/*
157294838Szbb * LT(Link Training) registers
158294838Szbb * (read / write indirect with al_eth_pma_reg_read/write)
159294838Szbb */
160294838Szbb#define AL_ETH_KR_PMD_CONTROL_RESTART				0
161294838Szbb#define AL_ETH_KR_PMD_CONTROL_ENABLE				1
162294838Szbb
163294838Szbb#define AL_ETH_KR_PMD_STATUS_RECEIVER_COMPLETED_SHIFT		0
164294838Szbb#define AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT		1
165294838Szbb#define AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT	2
166294838Szbb#define AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT			3
167294838Szbb
168294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK			0x0003
169294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT			0
170294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK			0x000C
171294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT			2
172294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK			0x0030
173294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT			4
174294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT		12
175294838Szbb#define AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT			13
176294838Szbb
177294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK		0x0003
178294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT		0
179294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK		0x000C
180294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT		2
181294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK		0x0030
182294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT		4
183294838Szbb#define AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT		15
184294838Szbb
185294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK			0x0003
186294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT			0
187294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK			0x000C
188294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT			2
189294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK			0x0030
190294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT			4
191294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT		12
192294838Szbb#define AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT			13
193294838Szbb
194294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK		0x0003
195294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT		0
196294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK		0x000C
197294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT		2
198294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK		0x0030
199294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT		4
200294838Szbb#define AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT	15
201294838Szbb
202294838Szbb
203294838Szbbenum al_eth_an_lt_regs {
204294838Szbb	AL_ETH_AN_REGS,
205294838Szbb	AL_ETH_LT_REGS,
206294838Szbb};
207294838Szbb
208294838Szbbstatic uint16_t al_eth_an_lt_reg_read(
209294838Szbb			struct al_hal_eth_adapter *adapter,
210294838Szbb			enum al_eth_an_lt_regs_ids reg_id,
211294838Szbb			enum al_eth_an_lt_regs an_lt,
212294838Szbb			enum al_eth_an_lt_lane lane)
213294838Szbb{
214294838Szbb	uint32_t val;
215294838Szbb	uint16_t reg_addr;
216294838Szbb
217294838Szbb	if (adapter->rev_id < AL_ETH_REV_ID_3) {
218294838Szbb		al_assert(lane == AL_ETH_AN__LT_LANE_0);
219294838Szbb
220294838Szbb		reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1];
221294838Szbb		if (an_lt == AL_ETH_AN_REGS) {
222294838Szbb			al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr);
223294838Szbb			val = al_reg_read32(&adapter->mac_regs_base->kr.an_data);
224294838Szbb		} else {
225294838Szbb			al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr);
226294838Szbb			val = al_reg_read32(&adapter->mac_regs_base->kr.pma_data);
227294838Szbb		}
228294838Szbb	} else {
229294838Szbb		struct al_an_lt_wrapper_regs *regs = NULL;
230294838Szbb
231294838Szbb		reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2];
232294838Szbb
233294838Szbb		switch (lane) {
234294838Szbb		case AL_ETH_AN__LT_LANE_0:
235294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
236294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
237294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
238294838Szbb				       reg_addr);
239294838Szbb
240294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
241294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
242294838Szbb			val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_0_data);
243294838Szbb			break;
244294838Szbb		case AL_ETH_AN__LT_LANE_1:
245294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
246294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
247294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
248294838Szbb				       reg_addr);
249294838Szbb
250294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
251294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
252294838Szbb			val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_1_data);
253294838Szbb			break;
254294838Szbb		case AL_ETH_AN__LT_LANE_2:
255294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
256294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
257294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
258294838Szbb				       reg_addr);
259294838Szbb
260294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
261294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
262294838Szbb			val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_2_data);
263294838Szbb			break;
264294838Szbb		case AL_ETH_AN__LT_LANE_3:
265294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
266294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
267294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
268294838Szbb				       reg_addr);
269294838Szbb
270294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
271294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
272294838Szbb			val = al_reg_read32(&adapter->mac_regs_base->gen_v3.an_lt_3_data);
273294838Szbb			break;
274294838Szbb		default:
275294838Szbb			al_err("%s: Unknown Lane %d\n", __func__, lane);
276294838Szbb			return 0;
277294838Szbb		}
278294838Szbb	}
279294838Szbb
280294838Szbb
281294838Szbb	al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__,
282294838Szbb	       (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val);
283294838Szbb
284294838Szbb	return (uint16_t)val;
285294838Szbb}
286294838Szbb
287294838Szbbstatic void al_eth_an_lt_reg_write(
288294838Szbb			struct al_hal_eth_adapter *adapter,
289294838Szbb			enum al_eth_an_lt_regs_ids reg_id,
290294838Szbb			enum al_eth_an_lt_regs an_lt,
291294838Szbb			enum al_eth_an_lt_lane lane,
292294838Szbb			uint16_t val)
293294838Szbb{
294294838Szbb	uint16_t reg_addr;
295294838Szbb
296294838Szbb	if (adapter->rev_id < AL_ETH_REV_ID_3) {
297294838Szbb		reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_1];
298294838Szbb		if (an_lt == AL_ETH_AN_REGS) {
299294838Szbb			al_reg_write32(&adapter->mac_regs_base->kr.an_addr, reg_addr);
300294838Szbb			al_reg_write32(&adapter->mac_regs_base->kr.an_data, val);
301294838Szbb		} else {
302294838Szbb			al_reg_write32(&adapter->mac_regs_base->kr.pma_addr, reg_addr);
303294838Szbb			al_reg_write32(&adapter->mac_regs_base->kr.pma_data, val);
304294838Szbb		}
305294838Szbb	} else {
306294838Szbb		struct al_an_lt_wrapper_regs *regs = NULL;
307294838Szbb
308294838Szbb		reg_addr = al_eth_an_lt_regs_addr[reg_id][AL_ETH_LT_UNIT_REV_2];
309294838Szbb
310294838Szbb		switch (lane) {
311294838Szbb		case AL_ETH_AN__LT_LANE_0:
312294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
313294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
314294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
315294838Szbb				       reg_addr);
316294838Szbb
317294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
318294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
319294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
320294838Szbb				       val);
321294838Szbb			break;
322294838Szbb		case AL_ETH_AN__LT_LANE_1:
323294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
324294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
325294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
326294838Szbb				       reg_addr);
327294838Szbb
328294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
329294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
330294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
331294838Szbb				       val);
332294838Szbb			break;
333294838Szbb		case AL_ETH_AN__LT_LANE_2:
334294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
335294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
336294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
337294838Szbb				       reg_addr);
338294838Szbb
339294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
340294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
341294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
342294838Szbb				       val);
343294838Szbb			break;
344294838Szbb		case AL_ETH_AN__LT_LANE_3:
345294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
346294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].addr);
347294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
348294838Szbb				       reg_addr);
349294838Szbb
350294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
351294838Szbb				       (uintptr_t)&regs->an_lt[adapter->curr_lt_unit].data);
352294838Szbb			al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
353294838Szbb				       val);
354294838Szbb			break;
355294838Szbb		default:
356294838Szbb			al_err("%s: Unknown Lane %d\n", __func__, lane);
357294838Szbb			return;
358294838Szbb		}
359294838Szbb	}
360294838Szbb
361294838Szbb
362294838Szbb	al_dbg("[%s]: %s - (%s) lane %d, reg %d, val 0x%x", adapter->name, __func__,
363294838Szbb	       (an_lt == AL_ETH_AN_REGS) ? "AN" : "LT", lane, reg_addr, val);
364294838Szbb}
365294838Szbb
366294838Szbbstatic void al_eth_an_lt_unit_config(struct al_hal_eth_adapter *adapter)
367294838Szbb{
368294838Szbb	struct al_an_lt_wrapper_regs *regs = NULL;
369294838Szbb	uint32_t cfg_lane_0 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
370294838Szbb	uint32_t cfg_lane_1 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
371294838Szbb	uint32_t cfg_lane_2 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
372294838Szbb	uint32_t cfg_lane_3 = (AN_LT_WRAPPER_GEN_CFG_BYPASS_RX | AN_LT_WRAPPER_GEN_CFG_BYPASS_TX);
373294838Szbb
374294838Szbb	switch (adapter->mac_mode) {
375294838Szbb	case AL_ETH_MAC_MODE_10GbE_Serial:
376294838Szbb		cfg_lane_0 = 0;
377294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
378294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
379294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
380294838Szbb				 AL_ETH_AN_LT_UNIT_20_BIT);
381294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
382294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
383294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
384294838Szbb				 AL_ETH_AN_LT_UNIT_20_BIT);
385294838Szbb
386294838Szbb		adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_20_BIT;
387294838Szbb
388294838Szbb		break;
389294838Szbb	case AL_ETH_MAC_MODE_KR_LL_25G:
390294838Szbb		cfg_lane_0 = 0;
391294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
392294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
393294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
394294838Szbb				 AL_ETH_AN_LT_UNIT_32_BIT);
395294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
396294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
397294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
398294838Szbb				 AL_ETH_AN_LT_UNIT_32_BIT);
399294838Szbb
400294838Szbb		adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT;
401294838Szbb
402294838Szbb		break;
403294838Szbb	case AL_ETH_MAC_MODE_XLG_LL_40G:
404294838Szbb		cfg_lane_0 = 0;
405294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
406294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
407294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
408294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
409294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
410294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
411294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
412294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
413294838Szbb
414294838Szbb		cfg_lane_1 = 0;
415294838Szbb		AL_REG_FIELD_SET(cfg_lane_1,
416294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
417294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
418294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
419294838Szbb		AL_REG_FIELD_SET(cfg_lane_1,
420294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
421294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
422294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
423294838Szbb
424294838Szbb		cfg_lane_2 = 0;
425294838Szbb		AL_REG_FIELD_SET(cfg_lane_2,
426294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
427294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
428294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
429294838Szbb		AL_REG_FIELD_SET(cfg_lane_2,
430294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
431294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
432294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
433294838Szbb
434294838Szbb		cfg_lane_3 = 0;
435294838Szbb		AL_REG_FIELD_SET(cfg_lane_3,
436294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
437294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
438294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
439294838Szbb		AL_REG_FIELD_SET(cfg_lane_3,
440294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
441294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
442294838Szbb				 AL_ETH_AN_LT_UNIT_16_BIT);
443294838Szbb
444294838Szbb		adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_16_BIT;
445294838Szbb
446294838Szbb		break;
447294838Szbb	case AL_ETH_MAC_MODE_XLG_LL_50G:
448294838Szbb		cfg_lane_0 = 0;
449294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
450294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
451294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
452294838Szbb				 AL_ETH_AN_LT_UNIT_32_BIT);
453294838Szbb		AL_REG_FIELD_SET(cfg_lane_0,
454294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
455294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
456294838Szbb				 AL_ETH_AN_LT_UNIT_32_BIT);
457294838Szbb
458294838Szbb		cfg_lane_1 = 0;
459294838Szbb		AL_REG_FIELD_SET(cfg_lane_1,
460294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_MASK,
461294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_RX_SHIFT,
462294838Szbb				 AL_ETH_AN_LT_UNIT_32_BIT);
463294838Szbb		AL_REG_FIELD_SET(cfg_lane_1,
464294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_MASK,
465294838Szbb				 AN_LT_WRAPPER_GEN_CFG_AN_LT_SEL_TX_SHIFT,
466294838Szbb				 AL_ETH_AN_LT_UNIT_32_BIT);
467294838Szbb
468294838Szbb		adapter->curr_lt_unit = AL_ETH_AN_LT_UNIT_32_BIT;
469294838Szbb
470294838Szbb		break;
471294838Szbb	default:
472294838Szbb		al_err("%s: Unknown mac_mode\n", __func__);
473294838Szbb		return;
474294838Szbb	}
475294838Szbb
476294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_addr,
477294838Szbb		       (uintptr_t)&regs->gen.cfg);
478294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_0_data,
479294838Szbb		       cfg_lane_0);
480294838Szbb
481294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_addr,
482294838Szbb		       (uintptr_t)&regs->gen.cfg);
483294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_1_data,
484294838Szbb		       cfg_lane_1);
485294838Szbb
486294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_addr,
487294838Szbb		       (uintptr_t)&regs->gen.cfg);
488294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_2_data,
489294838Szbb		       cfg_lane_2);
490294838Szbb
491294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_addr,
492294838Szbb		       (uintptr_t)&regs->gen.cfg);
493294838Szbb	al_reg_write32(&adapter->mac_regs_base->gen_v3.an_lt_3_data,
494294838Szbb		       cfg_lane_3);
495294838Szbb}
496294838Szbb
497294838Szbbvoid al_eth_lp_coeff_up_get(
498294838Szbb			struct al_hal_eth_adapter *adapter,
499294838Szbb			enum al_eth_an_lt_lane lane,
500294838Szbb			struct al_eth_kr_coef_up_data *lpcoeff)
501294838Szbb{
502294838Szbb	uint16_t reg;
503294838Szbb
504294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_COEF_UP, AL_ETH_LT_REGS, lane);
505294838Szbb
506294838Szbb	lpcoeff->preset =
507294838Szbb		(AL_REG_BIT_GET(
508294838Szbb			reg, AL_ETH_KR_PMD_LP_COEF_UP_PRESET_SHIFT) != 0);
509294838Szbb
510294838Szbb	lpcoeff->initialize =
511294838Szbb		(AL_REG_BIT_GET(
512294838Szbb			reg, AL_ETH_KR_PMD_LP_COEF_UP_INITIALIZE_SHIFT) != 0);
513294838Szbb
514294838Szbb	lpcoeff->c_minus = AL_REG_FIELD_GET(reg,
515294838Szbb					AL_ETH_KR_PMD_LP_COEF_UP_MINUS_MASK,
516294838Szbb					AL_ETH_KR_PMD_LP_COEF_UP_MINUS_SHIFT);
517294838Szbb
518294838Szbb	lpcoeff->c_zero = AL_REG_FIELD_GET(reg,
519294838Szbb					AL_ETH_KR_PMD_LP_COEF_UP_ZERO_MASK,
520294838Szbb					AL_ETH_KR_PMD_LP_COEF_UP_ZERO_SHIFT);
521294838Szbb
522294838Szbb	lpcoeff->c_plus = AL_REG_FIELD_GET(reg,
523294838Szbb					AL_ETH_KR_PMD_LP_COEF_UP_PLUS_MASK,
524294838Szbb					AL_ETH_KR_PMD_LP_COEF_UP_PLUS_SHIFT);
525294838Szbb}
526294838Szbb
527294838Szbbvoid al_eth_lp_status_report_get(
528294838Szbb			struct al_hal_eth_adapter *adapter,
529294838Szbb			enum al_eth_an_lt_lane lane,
530294838Szbb			struct al_eth_kr_status_report_data *status)
531294838Szbb{
532294838Szbb	uint16_t reg;
533294838Szbb
534294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_LP_STATUS_REPORT, AL_ETH_LT_REGS, lane);
535294838Szbb
536294838Szbb	status->c_minus = AL_REG_FIELD_GET(reg,
537294838Szbb				    AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_MASK,
538294838Szbb				    AL_ETH_KR_PMD_LP_STATUS_REPORT_MINUS_SHIFT);
539294838Szbb
540294838Szbb	status->c_zero = AL_REG_FIELD_GET(reg,
541294838Szbb				   AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_MASK,
542294838Szbb				   AL_ETH_KR_PMD_LP_STATUS_REPORT_ZERO_SHIFT);
543294838Szbb
544294838Szbb	status->c_plus = AL_REG_FIELD_GET(reg,
545294838Szbb				   AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_MASK,
546294838Szbb				   AL_ETH_KR_PMD_LP_STATUS_REPORT_PLUS_SHIFT);
547294838Szbb
548294838Szbb	status->receiver_ready =
549294838Szbb		(AL_REG_BIT_GET(
550294838Szbb			reg, AL_ETH_KR_PMD_LP_STATUS_RECEIVER_READY_SHIFT) != 0);
551294838Szbb
552294838Szbb}
553294838Szbb
554294838Szbbvoid al_eth_ld_coeff_up_set(
555294838Szbb			struct al_hal_eth_adapter *adapter,
556294838Szbb			enum al_eth_an_lt_lane lane,
557294838Szbb			struct al_eth_kr_coef_up_data *ldcoeff)
558294838Szbb{
559294838Szbb	uint16_t reg = 0;
560294838Szbb
561294838Szbb	if (ldcoeff->preset)
562294838Szbb		AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_PRESET_SHIFT);
563294838Szbb
564294838Szbb	if (ldcoeff->initialize)
565294838Szbb		AL_REG_BIT_SET(reg, AL_ETH_KR_PMD_LD_COEF_UP_INITIALIZE_SHIFT);
566294838Szbb
567294838Szbb	AL_REG_FIELD_SET(reg,
568294838Szbb			 AL_ETH_KR_PMD_LD_COEF_UP_MINUS_MASK,
569294838Szbb			 AL_ETH_KR_PMD_LD_COEF_UP_MINUS_SHIFT,
570294838Szbb			 ldcoeff->c_minus);
571294838Szbb
572294838Szbb	AL_REG_FIELD_SET(reg,
573294838Szbb			 AL_ETH_KR_PMD_LD_COEF_UP_ZERO_MASK,
574294838Szbb			 AL_ETH_KR_PMD_LD_COEF_UP_ZERO_SHIFT,
575294838Szbb			 ldcoeff->c_zero);
576294838Szbb
577294838Szbb	AL_REG_FIELD_SET(reg,
578294838Szbb			 AL_ETH_KR_PMD_LD_COEF_UP_PLUS_MASK,
579294838Szbb			 AL_ETH_KR_PMD_LD_COEF_UP_PLUS_SHIFT,
580294838Szbb			 ldcoeff->c_plus);
581294838Szbb
582294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, reg);
583294838Szbb}
584294838Szbb
585294838Szbbvoid al_eth_ld_status_report_set(
586294838Szbb			struct al_hal_eth_adapter *adapter,
587294838Szbb			enum al_eth_an_lt_lane lane,
588294838Szbb			struct al_eth_kr_status_report_data *status)
589294838Szbb{
590294838Szbb	uint16_t reg = 0;
591294838Szbb
592294838Szbb	AL_REG_FIELD_SET(reg,
593294838Szbb			 AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_MASK,
594294838Szbb			 AL_ETH_KR_PMD_LD_STATUS_REPORT_MINUS_SHIFT,
595294838Szbb			 status->c_minus);
596294838Szbb
597294838Szbb	AL_REG_FIELD_SET(reg,
598294838Szbb			 AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_MASK,
599294838Szbb			 AL_ETH_KR_PMD_LD_STATUS_REPORT_ZERO_SHIFT,
600294838Szbb			 status->c_zero);
601294838Szbb
602294838Szbb	AL_REG_FIELD_SET(reg,
603294838Szbb			 AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_MASK,
604294838Szbb			 AL_ETH_KR_PMD_LD_STATUS_REPORT_PLUS_SHIFT,
605294838Szbb			 status->c_plus);
606294838Szbb
607294838Szbb	if (status->receiver_ready)
608294838Szbb		AL_REG_BIT_SET(reg,
609294838Szbb			AL_ETH_KR_PMD_LD_STATUS_REPORT_RECEIVER_READY_SHIFT);
610294838Szbb
611294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, reg);
612294838Szbb}
613294838Szbb
614294838Szbbal_bool al_eth_kr_receiver_frame_lock_get(struct al_hal_eth_adapter *adapter,
615294838Szbb					  enum al_eth_an_lt_lane lane)
616294838Szbb{
617294838Szbb	uint16_t reg;
618294838Szbb
619294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
620294838Szbb
621294838Szbb	return (AL_REG_BIT_GET(reg,
622294838Szbb			AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT) != 0);
623294838Szbb}
624294838Szbb
625294838Szbbal_bool al_eth_kr_startup_proto_prog_get(struct al_hal_eth_adapter *adapter,
626294838Szbb					 enum al_eth_an_lt_lane lane)
627294838Szbb{
628294838Szbb	uint16_t reg;
629294838Szbb
630294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
631294838Szbb
632294838Szbb	return (AL_REG_BIT_GET(
633294838Szbb		reg, AL_ETH_KR_PMD_STATUS_RECEIVER_START_UP_PROTO_PROG_SHIFT) != 0);
634294838Szbb}
635294838Szbb
636294838Szbbal_bool al_eth_kr_training_status_fail_get(struct al_hal_eth_adapter *adapter,
637294838Szbb					   enum al_eth_an_lt_lane lane)
638294838Szbb{
639294838Szbb	uint16_t reg;
640294838Szbb
641294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
642294838Szbb
643294838Szbb	return (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT) != 0);
644294838Szbb}
645294838Szbb
646294838Szbbvoid al_eth_receiver_ready_set(struct al_hal_eth_adapter *adapter,
647294838Szbb			       enum al_eth_an_lt_lane lane)
648294838Szbb{
649294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 1);
650294838Szbb}
651294838Szbb
652294838Szbb/*************************** auto negotiation *********************************/
653294838Szbbstatic int al_eth_kr_an_validate_adv(struct al_hal_eth_adapter *adapter,
654294838Szbb				     struct al_eth_an_adv *an_adv)
655294838Szbb{
656294838Szbb	al_assert(adapter);
657294838Szbb
658294838Szbb	if (an_adv == NULL)
659294838Szbb		return 0;
660294838Szbb
661294838Szbb	if (an_adv->selector_field != 1) {
662294838Szbb		al_err("[%s]: %s failed on selector_field (%d)\n",
663294838Szbb			adapter->name, __func__, an_adv->selector_field);
664294838Szbb		return -EINVAL;
665294838Szbb	}
666294838Szbb
667294838Szbb	if (an_adv->capability & AL_BIT(2)) {
668294838Szbb		al_err("[%s]: %s failed on capability bit 2 (%d)\n",
669294838Szbb			adapter->name, __func__, an_adv->capability);
670294838Szbb		return -EINVAL;
671294838Szbb	}
672294838Szbb
673294838Szbb	if (an_adv->remote_fault) {
674294838Szbb		al_err("[%s]: %s failed on remote_fault (%d)\n",
675294838Szbb			adapter->name, __func__, an_adv->remote_fault);
676294838Szbb		return -EINVAL;
677294838Szbb	}
678294838Szbb
679294838Szbb	if (an_adv->acknowledge) {
680294838Szbb		al_err("[%s]: %s failed on acknowledge (%d)\n",
681294838Szbb			adapter->name, __func__, an_adv->acknowledge);
682294838Szbb		return -EINVAL;
683294838Szbb	}
684294838Szbb
685294838Szbb	return 0;
686294838Szbb}
687294838Szbb
688294838Szbbstatic int al_eth_kr_an_write_adv(struct al_hal_eth_adapter *adapter,
689294838Szbb			       struct al_eth_an_adv *an_adv)
690294838Szbb{
691294838Szbb	uint16_t	reg;
692294838Szbb
693294838Szbb	if(an_adv == NULL)
694294838Szbb		return 0;
695294838Szbb
696294838Szbb	reg = 0;
697294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK,
698294838Szbb			 AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT,
699294838Szbb			 an_adv->selector_field);
700294838Szbb
701294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK,
702294838Szbb			 AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT,
703294838Szbb			 an_adv->echoed_nonce);
704294838Szbb
705294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV1_CAPABILITY_MASK,
706294838Szbb			 AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT,
707294838Szbb			 an_adv->capability);
708294838Szbb
709294838Szbb	AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT,
710294838Szbb			   an_adv->remote_fault);
711294838Szbb
712294838Szbb	AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_ACK_SHIFT,
713294838Szbb			   an_adv->acknowledge);
714294838Szbb
715294838Szbb	AL_REG_BIT_VAL_SET(reg, AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT,
716294838Szbb			   an_adv->next_page);
717294838Szbb
718294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV0, AL_ETH_AN_REGS,
719294838Szbb			       AL_ETH_AN__LT_LANE_0, reg);
720294838Szbb
721294838Szbb	reg = 0;
722294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TX_NONCE_MASK,
723294838Szbb			 AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT,
724294838Szbb			 an_adv->transmitted_nonce);
725294838Szbb
726294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV2_TECH_MASK,
727294838Szbb			 AL_ETH_KR_AN_ADV2_TECH_SHIFT,
728294838Szbb			 an_adv->technology);
729294838Szbb
730294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV1, AL_ETH_AN_REGS,
731294838Szbb			       AL_ETH_AN__LT_LANE_0, reg);
732294838Szbb
733294838Szbb	reg = 0;
734294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_TECH_MASK,
735294838Szbb			 AL_ETH_KR_AN_ADV3_TECH_SHIFT,
736294838Szbb			 an_adv->technology >> 11);
737294838Szbb
738294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_ADV3_FEC_MASK,
739294838Szbb			 AL_ETH_KR_AN_ADV3_FEC_SHIFT,
740294838Szbb			 an_adv->fec_capability);
741294838Szbb
742294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_ADV2, AL_ETH_AN_REGS,
743294838Szbb			       AL_ETH_AN__LT_LANE_0, reg);
744294838Szbb
745294838Szbb	return 0;
746294838Szbb}
747294838Szbb
748294838Szbbvoid al_eth_kr_an_read_adv(struct al_hal_eth_adapter *adapter,
749294838Szbb			   struct al_eth_an_adv *an_adv)
750294838Szbb{
751294838Szbb	int16_t	reg;
752294838Szbb
753294838Szbb	al_assert(an_adv != NULL);
754294838Szbb
755294838Szbb
756294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV0,
757294838Szbb				    AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
758294838Szbb
759294838Szbb	an_adv->selector_field = AL_REG_FIELD_GET(reg,
760294838Szbb					AL_ETH_KR_AN_ADV1_SEL_FIELD_MASK,
761294838Szbb					AL_ETH_KR_AN_ADV1_SEL_FIELD_SHIFT);
762294838Szbb
763294838Szbb	an_adv->echoed_nonce = AL_REG_FIELD_GET(reg,
764294838Szbb					AL_ETH_KR_AN_ADV1_ECHOED_NONCE_MASK,
765294838Szbb					AL_ETH_KR_AN_ADV1_ECHOED_NONCE_SHIFT);
766294838Szbb
767294838Szbb	an_adv->capability = AL_REG_FIELD_GET(reg,
768294838Szbb					AL_ETH_KR_AN_ADV1_CAPABILITY_MASK,
769294838Szbb					AL_ETH_KR_AN_ADV1_CAPABILITY_SHIFT);
770294838Szbb
771294838Szbb	an_adv->remote_fault = AL_REG_BIT_GET(reg,
772294838Szbb					AL_ETH_KR_AN_ADV1_REM_FAULT_SHIFT);
773294838Szbb
774294838Szbb	an_adv->acknowledge = AL_REG_BIT_GET(reg,
775294838Szbb					AL_ETH_KR_AN_ADV1_ACK_SHIFT);
776294838Szbb
777294838Szbb	an_adv->next_page = AL_REG_BIT_GET(reg,
778294838Szbb					AL_ETH_KR_AN_ADV1_NEXT_PAGE_SHIFT);
779294838Szbb
780294838Szbb
781294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV1,
782294838Szbb				    AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
783294838Szbb
784294838Szbb	an_adv->transmitted_nonce = AL_REG_FIELD_GET(reg,
785294838Szbb					 AL_ETH_KR_AN_ADV2_TX_NONCE_MASK,
786294838Szbb					 AL_ETH_KR_AN_ADV2_TX_NONCE_SHIFT);
787294838Szbb
788294838Szbb	an_adv->technology = AL_REG_FIELD_GET(reg,
789294838Szbb					 AL_ETH_KR_AN_ADV2_TECH_MASK,
790294838Szbb					 AL_ETH_KR_AN_ADV2_TECH_SHIFT);
791294838Szbb
792294838Szbb
793294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_REM_ADV2,
794294838Szbb				    AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
795294838Szbb
796294838Szbb	an_adv->technology |= (AL_REG_FIELD_GET(reg,
797294838Szbb					AL_ETH_KR_AN_ADV3_TECH_MASK,
798294838Szbb					AL_ETH_KR_AN_ADV3_TECH_SHIFT)  << 11);
799294838Szbb
800294838Szbb	an_adv->fec_capability = AL_REG_FIELD_GET(reg,
801294838Szbb					 AL_ETH_KR_AN_ADV3_FEC_MASK,
802294838Szbb					 AL_ETH_KR_AN_ADV3_FEC_SHIFT);
803294838Szbb}
804294838Szbb
805294838Szbbint al_eth_kr_next_page_read(struct al_hal_eth_adapter *adapter,
806294838Szbb			     struct al_eth_an_np *np)
807294838Szbb{
808294838Szbb	uint16_t reg;
809294838Szbb
810294838Szbb	reg = al_eth_an_lt_reg_read(adapter,
811294838Szbb				    AL_ETH_KR_AN_REM_XNP_ADV0,
812294838Szbb				    AL_ETH_AN_REGS,
813294838Szbb				    AL_ETH_AN__LT_LANE_0);
814294838Szbb
815294838Szbb	np->unformatted_code_field = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK,
816294838Szbb					 AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT);
817294838Szbb
818294838Szbb	np->toggle = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK,
819294838Szbb					 AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT);
820294838Szbb
821294838Szbb	np->ack2 = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK,
822294838Szbb					 AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT);
823294838Szbb
824294838Szbb	np->msg_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK,
825294838Szbb					 AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT);
826294838Szbb
827294838Szbb	np->next_page = AL_REG_FIELD_GET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK,
828294838Szbb					 AL_ETH_KR_AN_NP_ADV1_NP_SHIFT);
829294838Szbb
830294838Szbb	np->unformatted_code_field1 = al_eth_an_lt_reg_read(adapter,
831294838Szbb							    AL_ETH_KR_AN_REM_XNP_ADV1,
832294838Szbb							    AL_ETH_AN_REGS,
833294838Szbb							    AL_ETH_AN__LT_LANE_0);
834294838Szbb	np->unformatted_code_field2 = al_eth_an_lt_reg_read(adapter,
835294838Szbb							    AL_ETH_KR_AN_REM_XNP_ADV2,
836294838Szbb							    AL_ETH_AN_REGS,
837294838Szbb							    AL_ETH_AN__LT_LANE_0);
838294838Szbb
839294838Szbb	return 0;
840294838Szbb}
841294838Szbb
842294838Szbbint al_eth_kr_next_page_write(struct al_hal_eth_adapter *adapter,
843294838Szbb			      struct al_eth_an_np *np)
844294838Szbb{
845294838Szbb	uint16_t reg = 0;
846294838Szbb
847294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_DATA1_MASK,
848294838Szbb			 AL_ETH_KR_AN_NP_ADV1_DATA1_SHIFT,
849294838Szbb			 np->unformatted_code_field);
850294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_TOGGLE_MASK,
851294838Szbb			 AL_ETH_KR_AN_NP_ADV1_TOGGLE_SHIFT,
852294838Szbb			 np->toggle);
853294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_ACK2_MASK,
854294838Szbb			 AL_ETH_KR_AN_NP_ADV1_ACK2_SHIFT,
855294838Szbb			 np->ack2);
856294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_MASK,
857294838Szbb			 AL_ETH_KR_AN_NP_ADV1_MSG_PAGE_SHIFT,
858294838Szbb			 np->msg_page);
859294838Szbb	AL_REG_FIELD_SET(reg, AL_ETH_KR_AN_NP_ADV1_NP_MASK,
860294838Szbb			 AL_ETH_KR_AN_NP_ADV1_NP_SHIFT,
861294838Szbb			 np->next_page);
862294838Szbb
863294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV0, AL_ETH_AN_REGS,
864294838Szbb			       AL_ETH_AN__LT_LANE_0, reg);
865294838Szbb
866294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV1, AL_ETH_AN_REGS,
867294838Szbb			       AL_ETH_AN__LT_LANE_0, np->unformatted_code_field1);
868294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_XNP_ADV2, AL_ETH_AN_REGS,
869294838Szbb			       AL_ETH_AN__LT_LANE_0, np->unformatted_code_field2);
870294838Szbb
871294838Szbb	return 0;
872294838Szbb}
873294838Szbb
874294838Szbbint al_eth_kr_an_init(struct al_hal_eth_adapter *adapter,
875294838Szbb		      struct al_eth_an_adv *an_adv)
876294838Szbb{
877294838Szbb	int		rc;
878294838Szbb
879294838Szbb	if (adapter->rev_id > AL_ETH_REV_ID_2)
880294838Szbb		al_eth_an_lt_unit_config(adapter);
881294838Szbb
882294838Szbb	rc = al_eth_kr_an_validate_adv(adapter, an_adv);
883294838Szbb	if (rc)
884294838Szbb		return rc;
885294838Szbb
886294838Szbb	rc = al_eth_kr_an_write_adv(adapter, an_adv);
887294838Szbb	if (rc)
888294838Szbb		return rc;
889294838Szbb
890294838Szbb	/* clear status */
891294838Szbb	al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS, AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
892294838Szbb
893294838Szbb	al_dbg("[%s]: autonegotiation initialized successfully", adapter->name);
894294838Szbb	return 0;
895294838Szbb}
896294838Szbb
897294838Szbbint al_eth_kr_an_start(struct al_hal_eth_adapter *adapter,
898294838Szbb		       enum al_eth_an_lt_lane lane,
899294838Szbb		       al_bool next_page_enable,
900294838Szbb		       al_bool lt_enable)
901294838Szbb{
902294838Szbb	uint16_t control = AL_ETH_KR_AN_CONTROL_ENABLE | AL_ETH_KR_AN_CONTROL_RESTART;
903294838Szbb
904294838Szbb	al_dbg("Eth [%s]: enable autonegotiation. lt_en %s",
905294838Szbb		adapter->name, (lt_enable == AL_TRUE) ? "yes" : "no");
906294838Szbb
907294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS,
908294838Szbb			       lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART));
909294838Szbb
910294838Szbb	if (next_page_enable == AL_TRUE)
911294838Szbb		control |= AL_ETH_KR_AN_CONTROL_NP_ENABLE;
912294838Szbb
913294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS,
914294838Szbb			       lane, control);
915294838Szbb
916294838Szbb	if (lt_enable == AL_TRUE) {
917294838Szbb		al_eth_kr_lt_initialize(adapter, lane);
918294838Szbb	}
919294838Szbb
920294838Szbb	return 0;
921294838Szbb}
922294838Szbb
923294838Szbbvoid al_eth_kr_an_stop(struct al_hal_eth_adapter *adapter)
924294838Szbb{
925294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_AN_CONTROL, AL_ETH_AN_REGS,
926294838Szbb			       AL_ETH_AN__LT_LANE_0, 0);
927294838Szbb}
928294838Szbb
929294838Szbbvoid al_eth_kr_an_status_check(struct al_hal_eth_adapter *adapter,
930294838Szbb			      al_bool *page_received,
931294838Szbb			      al_bool *an_completed,
932294838Szbb			      al_bool *error)
933294838Szbb{
934294838Szbb	uint16_t	reg;
935294838Szbb
936294838Szbb	reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_AN_STATUS,
937294838Szbb				    AL_ETH_AN_REGS, AL_ETH_AN__LT_LANE_0);
938294838Szbb
939294838Szbb	if ((reg & AL_ETH_KR_AN_STATUS_CHECK_MASK) !=
940294838Szbb				AL_ETH_KR_AN_STATUS_CHECK_NO_ERROR) {
941294838Szbb		al_err("[%s]: %s AN_STATUS (0x%x) indicated error\n",
942294838Szbb			adapter->name, __func__, reg);
943294838Szbb
944294838Szbb		*error = AL_TRUE;
945294838Szbb	}
946294838Szbb
947294838Szbb	if (reg & AL_ETH_KR_AN_STATUS_BASE_PAGE_RECEIVED)
948294838Szbb		*page_received = AL_TRUE;
949294838Szbb	else
950294838Szbb		*page_received = AL_FALSE;
951294838Szbb
952294838Szbb	if (reg & AL_ETH_KR_AN_STATUS_COMPLETED)
953294838Szbb		*an_completed = AL_TRUE;
954294838Szbb	else
955294838Szbb		*an_completed = AL_FALSE;
956294838Szbb}
957294838Szbb
958294838Szbb
959294838Szbb/****************************** KR Link Training *****************************/
960294838Szbbvoid al_eth_kr_lt_restart(struct al_hal_eth_adapter *adapter,
961294838Szbb			  enum al_eth_an_lt_lane lane)
962294838Szbb{
963294838Szbb	al_dbg("[%s]: KR LT Restart Link Training.\n", adapter->name);
964294838Szbb
965294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS,
966294838Szbb			       lane, (AL_BIT(AL_ETH_KR_PMD_CONTROL_ENABLE) |
967294838Szbb				      AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART)));
968294838Szbb}
969294838Szbb
970294838Szbbvoid al_eth_kr_lt_stop(struct al_hal_eth_adapter *adapter,
971294838Szbb		       enum al_eth_an_lt_lane lane)
972294838Szbb{
973294838Szbb	al_dbg("[%s]: KR LT Stop Link Training.\n", adapter->name);
974294838Szbb
975294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_CONTROL, AL_ETH_LT_REGS,
976294838Szbb			       lane, AL_BIT(AL_ETH_KR_PMD_CONTROL_RESTART));
977294838Szbb}
978294838Szbb
979294838Szbbvoid al_eth_kr_lt_initialize(struct al_hal_eth_adapter *adapter,
980294838Szbb			     enum al_eth_an_lt_lane lane)
981294838Szbb{
982294838Szbb	al_dbg("[%s]: KR LT Initialize.\n", adapter->name);
983294838Szbb
984294838Szbb	/* Reset LT state machine */
985294838Szbb	al_eth_kr_lt_stop(adapter, lane);
986294838Szbb
987294838Szbb	/* clear receiver status */
988294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane, 0);
989294838Szbb
990294838Szbb	/* Coefficient Update to all zero (no command, hold) */
991294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_COEF_UP, AL_ETH_LT_REGS, lane, 0);
992294838Szbb	/* Coefficient Status to all zero (not_updated) */
993294838Szbb	al_eth_an_lt_reg_write(adapter, AL_ETH_KR_PMD_LD_STATUS_REPORT, AL_ETH_LT_REGS, lane, 0);
994294838Szbb
995294838Szbb	/* start */
996294838Szbb	al_eth_kr_lt_restart(adapter, lane);
997294838Szbb}
998294838Szbb
999294838Szbbal_bool al_eth_kr_lt_frame_lock_wait(struct al_hal_eth_adapter *adapter,
1000294838Szbb				     enum al_eth_an_lt_lane lane,
1001294838Szbb				     uint32_t timeout)
1002294838Szbb{
1003294838Szbb	uint32_t loop;
1004294838Szbb	uint16_t reg = 0;
1005294838Szbb
1006294838Szbb	for (loop = 0; loop < timeout; loop++) {
1007294838Szbb		reg = al_eth_an_lt_reg_read(adapter, AL_ETH_KR_PMD_STATUS, AL_ETH_LT_REGS, lane);
1008294838Szbb
1009294838Szbb		if (AL_REG_BIT_GET(reg, AL_ETH_KR_PMD_STATUS_FAILURE_SHIFT)) {
1010294838Szbb			al_info("[%s]: Failed on Training Failure."
1011294838Szbb			       " loops %d PMD STATUS 0x%04x\n",
1012294838Szbb			       adapter->name, loop, reg);
1013294838Szbb
1014294838Szbb			return AL_FALSE;
1015294838Szbb		}
1016294838Szbb		if (AL_REG_BIT_GET(reg,
1017294838Szbb			AL_ETH_KR_PMD_STATUS_RECEIVER_FRAME_LOCK_SHIFT)) {
1018294838Szbb			al_dbg("[%s]: Frame lock received."
1019294838Szbb			       " loops %d PMD STATUS 0x%04x\n",
1020294838Szbb			       adapter->name, loop, reg);
1021294838Szbb
1022294838Szbb			return AL_TRUE;
1023294838Szbb		}
1024294838Szbb		al_udelay(1);
1025294838Szbb	}
1026294838Szbb	al_info("[%s]: Failed on timeout. PMD STATUS 0x%04x\n",
1027294838Szbb			adapter->name, reg);
1028294838Szbb
1029294838Szbb	return AL_FALSE;
1030294838Szbb}
1031