1/*******************************************************************************
2Copyright (C) 2015 Annapurna Labs Ltd.
3
4This file may be licensed under the terms of the Annapurna Labs Commercial
5License Agreement.
6
7Alternatively, this file can be distributed under the terms of the GNU General
8Public License V2 as published by the Free Software Foundation and can be
9found at http://www.gnu.org/licenses/gpl-2.0.html
10
11Alternatively, redistribution and use in source and binary forms, with or
12without modification, are permitted provided that the following conditions are
13met:
14
15    *     Redistributions of source code must retain the above copyright notice,
16this list of conditions and the following disclaimer.
17
18    *     Redistributions in binary form must reproduce the above copyright
19notice, this list of conditions and the following disclaimer in
20the documentation and/or other materials provided with the
21distribution.
22
23THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33
34*******************************************************************************/
35
36#include "al_hal_serdes_25g.h"
37#include "al_hal_serdes_25g_regs.h"
38#include "al_hal_serdes_25g_internal_regs.h"
39
40#define AL_SERDES_MB_MAX_DATA_LEN		8
41
42#define AL_SERDES_25G_WAIT_FOR_READY_TO		200
43#define AL_SERDES_25G_RESET_TO			100
44#define AL_SERDES_25G_RESET_NUM_RETRIES		5
45
46#if (!defined(AL_SERDES_BASIC_SERVICES_ONLY)) || (AL_SERDES_BASIC_SERVICES_ONLY == 0)
47#define AL_SRDS_ADV_SRVC(func)			func
48#else
49static void al_serdes_hssp_stub_func(void)
50{
51	al_err("%s: not implemented service called!\n", __func__);
52}
53
54#define AL_SRDS_ADV_SRVC(func)			((typeof(func) *)al_serdes_hssp_stub_func)
55#endif
56
57/******************************************************************************/
58/******************************************************************************/
59static enum al_serdes_type al_serdes_25g_type_get(void)
60{
61	return AL_SRDS_TYPE_25G;
62}
63
64/******************************************************************************/
65/******************************************************************************/
66static int al_serdes_25g_reg_read(
67	struct al_serdes_grp_obj	*obj,
68	enum al_serdes_reg_page		page,
69	enum al_serdes_reg_type		type,
70	uint16_t			offset,
71	uint8_t				*data)
72{
73	struct al_serdes_c_regs __iomem	*regs_base = obj->regs_base;
74	uint32_t addr = 0;
75
76	al_dbg("%s(%p, %d, %d, %u)\n", __func__, obj, page, type, offset);
77
78	al_assert(obj);
79	al_assert(data);
80
81	switch (page) {
82	case AL_SRDS_REG_PAGE_TOP:
83		addr = (SERDES_25G_TOP_BASE + offset);
84		break;
85	case AL_SRDS_REG_PAGE_4_COMMON:
86		addr = (SERDES_25G_CM_BASE + offset);
87		break;
88	case AL_SRDS_REG_PAGE_0_LANE_0:
89	case AL_SRDS_REG_PAGE_1_LANE_1:
90		addr = (SERDES_25G_LANE_BASE + (page * SERDES_25G_LANE_SIZE) + offset);
91		break;
92	default:
93		al_err("%s: wrong serdes type %d\n", __func__, type);
94		return -1;
95	}
96
97	al_reg_write32(&regs_base->gen.reg_addr, addr);
98	*data = al_reg_read32(&regs_base->gen.reg_data);
99
100	al_dbg("%s: return(%u)\n", __func__, *data);
101
102	return 0;
103}
104
105static int al_serdes_25g_reg_write(
106	struct al_serdes_grp_obj	*obj,
107	enum al_serdes_reg_page		page,
108	enum al_serdes_reg_type		type,
109	uint16_t			offset,
110	uint8_t				data)
111{
112	struct al_serdes_c_regs __iomem	*regs_base = obj->regs_base;
113	uint32_t addr = 0;
114
115	al_dbg("%s(%p, %d, %d, %u)\n", __func__, obj, page, type, offset);
116
117	al_assert(obj);
118
119	switch (page) {
120	case AL_SRDS_REG_PAGE_TOP:
121		addr = (SERDES_25G_TOP_BASE + offset);
122		break;
123	case AL_SRDS_REG_PAGE_4_COMMON:
124		addr = (SERDES_25G_CM_BASE + offset);
125		break;
126	case AL_SRDS_REG_PAGE_0_LANE_0:
127	case AL_SRDS_REG_PAGE_1_LANE_1:
128		addr = (SERDES_25G_LANE_BASE + (page * SERDES_25G_LANE_SIZE) + offset);
129		break;
130	default:
131		al_err("%s: wrong serdes type %d\n", __func__, type);
132		return -1;
133	}
134
135	al_reg_write32(&regs_base->gen.reg_addr, addr);
136	al_reg_write32(&regs_base->gen.reg_data, (data | SERDES_C_GEN_REG_DATA_STRB_MASK));
137
138	al_dbg("%s: write(%u)\n", __func__, data);
139
140	return 0;
141}
142
143/******************************************************************************/
144/******************************************************************************/
145static int al_serdes_25g_reg_masked_read(
146	struct al_serdes_grp_obj	*obj,
147	enum al_serdes_reg_page		page,
148	uint16_t			offset,
149	uint8_t				mask,
150	uint8_t				shift,
151	uint8_t				*data)
152{
153	uint8_t val;
154	int status = 0;
155
156	status = al_serdes_25g_reg_read(obj, page, 0, offset, &val);
157	if (status)
158		return status;
159
160	*data = AL_REG_FIELD_GET(val, mask, shift);
161
162	return 0;
163}
164
165static int al_serdes_25g_reg_masked_write(
166	struct al_serdes_grp_obj	*obj,
167	enum al_serdes_reg_page		page,
168	uint16_t			offset,
169	uint8_t				mask,
170	uint8_t				shift,
171	uint8_t				data)
172{
173	uint8_t val;
174	int status = 0;
175
176	status = al_serdes_25g_reg_read(obj, page, 0, offset, &val);
177	if (status)
178		return status;
179
180	val &= (~mask);
181	val |= (data << shift);
182	return al_serdes_25g_reg_write(obj, page, 0, offset, val);
183}
184
185/******************************************************************************/
186/******************************************************************************/
187#define SERDES_25G_MB_RESP_BYTES	16
188#define SERDES_25G_MB_TIMEOUT		5000000 /* uSec */
189
190static int al_serdes_25g_mailbox_send_cmd(
191	struct al_serdes_grp_obj	*obj,
192	uint8_t				cmd,
193	uint8_t				*data,
194	uint8_t				data_len)
195{
196	uint8_t val;
197	int i;
198	uint32_t timeout = SERDES_25G_MB_TIMEOUT;
199
200	if (data_len > AL_SERDES_MB_MAX_DATA_LEN) {
201		al_err("Cannot send command, data too long\n");
202		return -1;
203	}
204
205	/* Wait for CMD_FLAG to clear */
206	while(1) {
207		al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0,
208				       SERDES_25G_TOP_CMD_FLAG_ADDR, &val);
209		if (val == 0)
210			break;
211
212		if (timeout == 0) {
213			al_err("%s: timeout occurred waiting to CMD_FLAG\n", __func__);
214			return -1;
215		}
216
217		timeout--;
218		al_udelay(1);
219	}
220
221	for (i = 0; i < data_len; i++) {
222		al_serdes_25g_reg_write(obj, AL_SRDS_REG_PAGE_TOP, 0,
223					(SERDES_25G_TOP_CMD_DATA0_ADDR + i), data[i]);
224	}
225
226	/* this write will set CMD_FLAG automatically */
227	al_serdes_25g_reg_write(obj, AL_SRDS_REG_PAGE_TOP, 0, SERDES_25G_TOP_CMD_ADDR, cmd);
228
229	return 0;
230}
231
232static int al_serdes_25g_mailbox_recv_rsp(
233	struct al_serdes_grp_obj	*obj,
234	uint8_t				*rsp_code,
235	uint8_t				*data,
236	uint8_t				*data_len)
237{
238	uint8_t val;
239	int i;
240	uint32_t timeout = SERDES_25G_MB_TIMEOUT;
241
242	/* wait for RSP_FLAG to set */
243	while(1) {
244		al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0,
245				       SERDES_25G_TOP_RSP_FLAG_ADDR, &val);
246		if (val == 0x1)
247			break;
248
249		if (timeout == 0) {
250			al_err("%s: timeout occurred waiting to RSP_FLAG\n", __func__);
251			*data_len = 0;
252			return -1;
253		}
254
255		timeout--;
256		al_udelay(1);
257	}
258
259	/* Grab the response code and data */
260	al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0,
261				SERDES_25G_TOP_RSP_ADDR, rsp_code);
262
263	for (i = 0; i < SERDES_25G_MB_RESP_BYTES; i++) {
264		al_serdes_25g_reg_read(obj, AL_SRDS_REG_PAGE_TOP, 0,
265				(SERDES_25G_TOP_RSP_DATA0_ADDR + i), &data[i]);
266	}
267
268	/* clear the RSP_FLAG (write 1 to clear) */
269	al_serdes_25g_reg_write(obj, AL_SRDS_REG_PAGE_TOP, 0,
270				SERDES_25G_TOP_RSP_FLAG_ADDR, 0x1);
271
272	*data_len = SERDES_25G_MB_RESP_BYTES;
273
274	return 0;
275}
276
277/******************************************************************************/
278/******************************************************************************/
279static void al_serdes_25g_bist_rx_enable(
280	struct al_serdes_grp_obj	*obj,
281	enum al_serdes_lane		lane,
282	al_bool				enable)
283{
284	if (enable) {
285		switch (lane) {
286		case 0:
287			al_serdes_25g_reg_masked_write(
288					obj,
289					AL_SRDS_REG_PAGE_TOP,
290					SERDES_25G_TOP_CLOCK_LN0_CLK_RX_ADDR,
291					SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_CG_EN_MASK,
292					SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_CG_EN_SHIFT,
293					0x1);
294			al_serdes_25g_reg_masked_write(
295					obj,
296					AL_SRDS_REG_PAGE_TOP,
297					SERDES_25G_TOP_CLOCK_LN0_CLK_RX_ADDR,
298					SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_BIST_CG_EN_MASK,
299					SERDES_25G_TOP_CLOCK_LN0_CLK_RX_CTRL_BIST_CG_EN_SHIFT,
300					0x1);
301			break;
302		case 1:
303			al_serdes_25g_reg_masked_write(
304					obj,
305					AL_SRDS_REG_PAGE_TOP,
306					SERDES_25G_TOP_CLOCK_LN1_CLK_RX_ADDR,
307					SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_CG_EN_MASK,
308					SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_CG_EN_SHIFT,
309					0x1);
310
311			al_serdes_25g_reg_masked_write(
312					obj,
313					AL_SRDS_REG_PAGE_TOP,
314					SERDES_25G_TOP_CLOCK_LN1_CLK_RX_ADDR,
315					SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_BIST_CG_EN_MASK,
316					SERDES_25G_TOP_CLOCK_LN1_CLK_RX_CTRL_BIST_CG_EN_SHIFT,
317					0x1);
318			break;
319		default:
320			al_err("%s: Wrong serdes lane %d\n", __func__, lane);
321			return;
322		}
323
324		al_serdes_25g_reg_masked_write(
325				obj,
326				(enum al_serdes_reg_page)lane,
327				SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_ADDR,
328				SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_STOP_ON_LOSS_LOCK_MASK,
329				SERDES_25G_LANE_RX_BIST_LOSS_LOCK_CTRL4_STOP_ON_LOSS_LOCK_SHIFT,
330				0);
331		al_serdes_25g_reg_masked_write(
332				obj,
333				(enum al_serdes_reg_page)lane,
334				SERDES_25G_LANE_RX_BIST_CTRL_ADDR,
335				SERDES_25G_LANE_RX_BIST_CTRL_EN_MASK,
336				SERDES_25G_LANE_RX_BIST_CTRL_EN_SHIFT,
337				1);
338		al_serdes_25g_reg_masked_write(
339				obj,
340				(enum al_serdes_reg_page)lane,
341				SERDES_25G_LANE_RX_BIST_CTRL_ADDR,
342				SERDES_25G_LANE_RX_BIST_CTRL_PATTERN_SEL_MASK,
343				SERDES_25G_LANE_RX_BIST_CTRL_PATTERN_SEL_SHIFT,
344				6);
345	} else {
346		/* clear counters */
347		al_serdes_25g_reg_masked_write(
348					obj,
349					(enum al_serdes_reg_page)lane,
350					SERDES_25G_LANE_RX_BIST_CTRL_ADDR,
351					SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_MASK,
352					SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_SHIFT,
353					1);
354
355		al_serdes_25g_reg_masked_write(
356					obj,
357					(enum al_serdes_reg_page)lane,
358					SERDES_25G_LANE_RX_BIST_CTRL_ADDR,
359					SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_MASK,
360					SERDES_25G_LANE_RX_BIST_CTRL_CLEAR_BER_SHIFT,
361					0);
362
363		al_msleep(AL_SERDES_25G_WAIT_FOR_READY_TO);
364
365		/* disable */
366		al_serdes_25g_reg_masked_write(
367				obj,
368				(enum al_serdes_reg_page)lane,
369				SERDES_25G_LANE_RX_BIST_CTRL_ADDR,
370				SERDES_25G_LANE_RX_BIST_CTRL_EN_MASK,
371				SERDES_25G_LANE_RX_BIST_CTRL_EN_SHIFT,
372				0);
373	}
374}
375
376// TODO: [Guy] change API to be per lane.
377static void al_serdes_25g_bist_pattern_select(
378	struct al_serdes_grp_obj	*obj,
379	enum al_serdes_bist_pattern	pattern,
380	uint8_t				*user_data)
381{
382	enum al_serdes_lane lane;
383	uint8_t val = 0;
384
385	switch (pattern) {
386	case AL_SRDS_BIST_PATTERN_USER:
387		al_assert(user_data);
388		val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS_USER;
389		break;
390	case AL_SRDS_BIST_PATTERN_PRBS7:
391		val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS7;
392		break;
393	case AL_SRDS_BIST_PATTERN_PRBS23:
394		val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS23;
395		break;
396	case AL_SRDS_BIST_PATTERN_PRBS31:
397		val = SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_PRBS31;
398		break;
399	case AL_SRDS_BIST_PATTERN_CLK1010:
400	default:
401		al_err("%s: invalid pattern (%d)\n", __func__, pattern);
402		al_assert(0);
403	}
404
405	for (lane = AL_SRDS_LANE_0; lane <= AL_SRDS_LANE_1; lane++) {
406		if (pattern == AL_SRDS_BIST_PATTERN_USER) {
407			int i;
408
409			for (i = 0; i < SERDES_25G_LANE_TX_BIST_UDP_NUM_BYTES; i++)
410				al_serdes_25g_reg_write(
411						obj,
412						(enum al_serdes_reg_page)lane,
413						0,
414						SERDES_25G_LANE_TX_BIST_UDP_ADDR(i),
415						user_data[i]);
416		}
417
418		al_serdes_25g_reg_masked_write(
419					obj,
420					(enum al_serdes_reg_page)lane,
421					SERDES_25G_LANE_TX_BIST_CTRL_ADDR,
422					SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_SEL_MASK,
423					SERDES_25G_LANE_TX_BIST_CTRL_PATTERN_SEL_SHIFT,
424					val);
425	}
426}
427
428static void al_serdes_25g_bist_tx_enable(
429	struct al_serdes_grp_obj	*obj,
430	enum al_serdes_lane		lane,
431	al_bool				enable)
432{
433	if (enable) {
434		al_serdes_25g_reg_masked_write(
435					obj,
436					(enum al_serdes_reg_page)lane,
437					SERDES_25G_LANE_TX_BIST_CTRL_ADDR,
438					SERDES_25G_LANE_TX_BIST_CTRL_EN_MASK,
439					SERDES_25G_LANE_TX_BIST_CTRL_EN_SHIFT,
440					0x1);
441		al_serdes_25g_reg_masked_write(
442					obj,
443					(enum al_serdes_reg_page)lane,
444					SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_ADDR,
445					SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_MASK,
446					SERDES_25G_LANE_TOP_DPL_TXDP_CTRL1_DMUX_TXA_SEL_SHIFT,
447					0x2);
448
449		switch (lane) {
450		case AL_SRDS_LANE_0:
451			al_serdes_25g_reg_masked_write(
452					obj,
453					AL_SRDS_REG_PAGE_TOP,
454					SERDES_25G_TOP_CLOCK_LN0_CLK_TX_ADDR,
455					SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_BIST_CG_EN_MASK,
456					SERDES_25G_TOP_CLOCK_LN0_CLK_TX_CTRL_BIST_CG_EN_SHIFT,
457					0x1);
458			break;
459		case AL_SRDS_LANE_1:
460			al_serdes_25g_reg_masked_write(
461					obj,
462					AL_SRDS_REG_PAGE_TOP,
463					SERDES_25G_TOP_CLOCK_LN1_CLK_TX_ADDR,
464					SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_BIST_CG_EN_MASK,
465					SERDES_25G_TOP_CLOCK_LN1_CLK_TX_CTRL_BIST_CG_EN_SHIFT,
466					0x1);
467			break;
468		default:
469			al_err("%s: Wrong serdes lane %d\n", __func__, lane);
470				return;
471		}
472	} else {
473		al_serdes_25g_reg_masked_write(
474					obj,
475					(enum al_serdes_reg_page)lane,
476					SERDES_25G_LANE_TX_BIST_CTRL_ADDR,
477					SERDES_25G_LANE_TX_BIST_CTRL_EN_MASK,
478					SERDES_25G_LANE_TX_BIST_CTRL_EN_SHIFT,
479					0);
480	}
481
482}
483
484static void al_serdes_25g_bist_rx_status(
485	struct al_serdes_grp_obj	*obj,
486	enum al_serdes_lane		lane,
487	al_bool				*is_locked,
488	al_bool				*err_cnt_overflow,
489	uint32_t			*err_cnt)
490{
491	uint8_t status;
492	uint8_t err1;
493	uint8_t err2;
494	uint8_t err3;
495
496	al_serdes_25g_reg_masked_read(
497		obj,
498		(enum al_serdes_reg_page)lane,
499		SERDES_25G_LANE_RX_BIST_STATUS_ADDR,
500		SERDES_25G_LANE_RX_BIST_STATUS_STATE_MASK,
501		SERDES_25G_LANE_RX_BIST_STATUS_STATE_SHIFT,
502		&status);
503
504	if (status != 3) {
505		*is_locked = AL_FALSE;
506		return;
507	}
508
509	*is_locked = AL_TRUE;
510	*err_cnt_overflow = AL_FALSE;
511
512	al_serdes_25g_reg_masked_read(
513		obj,
514		(enum al_serdes_reg_page)lane,
515		SERDES_25G_LANE_RX_BIST_BER_STATUS0_ADDR,
516		SERDES_25G_LANE_RX_BIST_BER_STATUS0_BIT_ERROR_COUNT_7_0_MASK,
517		SERDES_25G_LANE_RX_BIST_BER_STATUS0_BIT_ERROR_COUNT_7_0_SHIFT,
518		&err1);
519
520	al_serdes_25g_reg_masked_read(
521		obj,
522		(enum al_serdes_reg_page)lane,
523		SERDES_25G_LANE_RX_BIST_BER_STATUS1_ADDR,
524		SERDES_25G_LANE_RX_BIST_BER_STATUS1_BIT_ERROR_COUNT_15_8_MASK,
525		SERDES_25G_LANE_RX_BIST_BER_STATUS1_BIT_ERROR_COUNT_15_8_SHIFT,
526		&err2);
527
528	al_serdes_25g_reg_masked_read(
529		obj,
530		(enum al_serdes_reg_page)lane,
531		SERDES_25G_LANE_RX_BIST_BER_STATUS2_ADDR,
532		SERDES_25G_LANE_RX_BIST_BER_STATUS2_BIT_ERROR_COUNT_23_16_MASK,
533		SERDES_25G_LANE_RX_BIST_BER_STATUS2_BIT_ERROR_COUNT_23_16_SHIFT,
534		&err3);
535
536	*err_cnt = (err1 + (err2 << 8) + (err3 << 16));
537}
538
539#define SERDES_MB_CMD_SWING_CFG		0x83
540#define SERDES_MB_CMD_SAMPLES_COUNT	0x84
541#define SERDES_MB_CMD_START_MEASURE	0x82
542
543#define SERDES_MB_RSP_CODE_0		0
544#define SERDES_MB_RSP_CODE_1		1
545#define SERDES_MB_RSP_CODE_2		2
546
547static int al_serdes_25g_eye_diag_run(
548	struct al_serdes_grp_obj	*obj,
549	enum al_serdes_lane		lane,
550	int				x_start,
551	int				x_stop,
552	unsigned int			x_step,
553	int				y_start,
554	int				y_stop,
555	unsigned int			y_step,
556	uint64_t			ber_target,
557	uint64_t			*buf,
558	uint32_t			buf_size)
559{
560	int rc;
561	uint8_t rsp_code;
562	uint8_t data[16];
563	uint8_t data_len;
564	uint32_t total_bits;
565	uint8_t bits_left_curr_sample;
566	uint8_t bits_left_curr_byte;
567	uint32_t byte = 0;
568	uint32_t x = 0;
569	uint32_t x_samples = (((x_stop - x_start) / x_step) + 1);
570	uint32_t y = 0;
571	uint32_t y_samples = (((y_stop - y_start) / y_step) + 1);
572	uint8_t sample_width = (64 - __builtin_clzl(ber_target));
573	uint8_t msb;
574	uint8_t lsb;
575	uint32_t samples_left = ((x_samples * y_samples));
576	uint8_t sign = 0;
577
578	al_assert(buf_size == (samples_left * sizeof(uint64_t)));
579
580	al_memset(buf, 0, buf_size);
581
582	if (y_start < 0) {
583		y_start *= -1;
584		sign |= 0x1;
585	}
586
587	if (y_stop < 0) {
588		y_stop *= -1;
589		sign |= 0x2;
590	}
591
592	data[0] = lane;
593	data[1] = x_start;
594	data[2] = x_stop;
595	data[3] = x_step;
596	data[4] = y_start;
597	data[5] = y_stop;
598	data[6] = sign;
599	data[7] = y_step;
600
601	rc = al_serdes_25g_mailbox_send_cmd(
602				obj,
603				SERDES_MB_CMD_SWING_CFG,
604				data,
605				8);
606
607	if (rc) {
608		al_err("%s: Failed to send command %d to mailbox.\n",
609			__func__, SERDES_MB_CMD_SWING_CFG);
610		return rc;
611	}
612
613	rc = al_serdes_25g_mailbox_recv_rsp(
614				obj,
615				&rsp_code,
616				data,
617				&data_len);
618
619	if ((rc) || (rsp_code != SERDES_MB_RSP_CODE_0)) {
620		al_err("%s: Failed to send command %d to mailbox. rsp_code %d\n",
621			__func__, SERDES_MB_CMD_SWING_CFG, rsp_code);
622
623		return (ETIMEDOUT);
624	}
625
626	al_assert(sample_width <= 40);
627
628	data[0] = lane;
629	data[1] = ((ber_target >> 32) & 0xFF);
630	data[2] = ((ber_target >> 24) & 0xFF);
631	data[3] = ((ber_target >> 16) & 0xFF);
632	data[4] = ((ber_target >> 8) & 0xFF);
633	data[5] = (ber_target & 0xFF);
634
635	rc = al_serdes_25g_mailbox_send_cmd(
636				obj,
637				SERDES_MB_CMD_SAMPLES_COUNT,
638				data,
639				6);
640
641	if (rc) {
642		al_err("%s: Failed to send command %d to mailbox.\n",
643			__func__, SERDES_MB_CMD_SAMPLES_COUNT);
644		return rc;
645	}
646
647	rc = al_serdes_25g_mailbox_recv_rsp(
648				obj,
649				&rsp_code,
650				data,
651				&data_len);
652
653	if ((rc) || (rsp_code != SERDES_MB_RSP_CODE_0)) {
654		al_err("%s: Failed to send command %d to mailbox. rsp_code %d\n",
655			__func__, SERDES_MB_CMD_SAMPLES_COUNT, rsp_code);
656
657		return (ETIMEDOUT);
658	}
659
660	rc = al_serdes_25g_mailbox_send_cmd(
661				obj,
662				SERDES_MB_CMD_START_MEASURE,
663				data,
664				0);
665
666	bits_left_curr_sample = sample_width;
667
668	while (rsp_code != SERDES_MB_RSP_CODE_1) {
669		uint8_t num_bits = 0;
670
671		rc = al_serdes_25g_mailbox_recv_rsp(
672				obj,
673				&rsp_code,
674				data,
675				&data_len);
676
677		if ((rc != 0) || (rsp_code > SERDES_MB_RSP_CODE_2)) {
678			al_err("%s: command %d return failure. rsp_code %d\n",
679			__func__, SERDES_MB_CMD_START_MEASURE, rsp_code);
680
681			return (ETIMEDOUT);
682		}
683		byte = 0;
684		total_bits = data_len * 8;
685		bits_left_curr_byte = 8;
686		while (total_bits > 0) {
687			num_bits = al_min_t(uint8_t, bits_left_curr_sample, bits_left_curr_byte);
688
689			buf[(y * x_samples) + x] <<= num_bits;
690			msb = bits_left_curr_byte - 1;
691			lsb = msb - num_bits + 1;
692			buf[(y * x_samples) + x] |= (data[byte] & AL_FIELD_MASK(msb, lsb) >> lsb);
693
694			total_bits -= num_bits;
695
696			bits_left_curr_byte -= num_bits;
697			if (!bits_left_curr_byte) {
698				bits_left_curr_byte = 8;
699				byte++;
700			}
701
702			bits_left_curr_sample -= num_bits;
703			if (!bits_left_curr_sample) {
704				y++;
705				if (y == y_samples) {
706					y = 0;
707					x++;
708				}
709
710				samples_left--;
711				bits_left_curr_sample = sample_width;
712			}
713
714			if (samples_left == 0)
715				break;
716		}
717
718		if ((samples_left == 0) && (rsp_code != SERDES_MB_RSP_CODE_1)) {
719			rc = al_serdes_25g_mailbox_recv_rsp(
720						obj,
721						&rsp_code,
722						data,
723						&data_len);
724			if ((rc) || (rsp_code == SERDES_MB_RSP_CODE_0)) {
725				al_err("%s: Parsed enough samples but f/w is still sending more\n",
726					__func__);
727
728				return -EIO;
729			}
730			break;
731		}
732	}
733
734	if (samples_left > 0) {
735		al_err("%s: Still need more samples but f/w has stopped sending them!?!?!?\n",
736			__func__);
737
738		return -EIO;
739	}
740
741	return 0;
742}
743
744#define SERDES_25G_EYE_X_MIN		1
745#define SERDES_25G_EYE_X_MAX		127
746#define SERDES_25G_EYE_Y_MIN		-200
747#define SERDES_25G_EYE_Y_MAX		200
748#define SERDES_25G_EYE_SIZE_MAX_SAMPLES	401
749#define SERDES_25G_EYE_SIZE_BER_TARGET	0xffff
750#define SERDES_25G_EYE_SIZE_ERR_TH	10
751
752static int al_serdes_25g_calc_eye_size(
753		struct al_serdes_grp_obj	*obj,
754		enum al_serdes_lane		lane,
755		int				*width,
756		int				*height)
757{
758	uint64_t samples[SERDES_25G_EYE_SIZE_MAX_SAMPLES];
759	int i;
760	int _width = 0;
761	int _height = 0;
762	int rc;
763	int mid_x = ((SERDES_25G_EYE_X_MIN + SERDES_25G_EYE_X_MAX) / 2);
764	int mid_y = ((SERDES_25G_EYE_Y_MIN + SERDES_25G_EYE_Y_MAX) / 2);
765
766	*height = 0;
767	*width = 0;
768
769	rc = al_serdes_25g_eye_diag_run(obj,
770					lane,
771					mid_x,
772					mid_x,
773					1,
774					SERDES_25G_EYE_Y_MIN,
775					SERDES_25G_EYE_Y_MAX,
776					1,
777					SERDES_25G_EYE_SIZE_BER_TARGET,
778					samples,
779					((SERDES_25G_EYE_Y_MAX - SERDES_25G_EYE_Y_MIN + 1) *
780					  sizeof(uint64_t)));
781
782	if (rc) {
783		al_err("%s: failed to run eye_diag\n", __func__);
784		return rc;
785	}
786
787	for (i = (mid_y - SERDES_25G_EYE_Y_MIN);
788		((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) &&
789			(i < (SERDES_25G_EYE_Y_MAX - SERDES_25G_EYE_Y_MIN + 1)));
790		i++, (_height)++)
791		;
792	for (i = (mid_y - SERDES_25G_EYE_Y_MIN);
793		((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) && (i >= 0));
794		i--, (_height)++)
795		;
796
797	rc = al_serdes_25g_eye_diag_run(obj,
798					lane,
799					SERDES_25G_EYE_X_MIN,
800					SERDES_25G_EYE_X_MAX,
801					1,
802					mid_y,
803					mid_y,
804					1,
805					SERDES_25G_EYE_SIZE_BER_TARGET,
806					samples,
807					((SERDES_25G_EYE_X_MAX - SERDES_25G_EYE_X_MIN + 1) *
808					  sizeof(uint64_t)));
809
810	if (rc) {
811		al_err("%s: failed to run eye_diag\n", __func__);
812		return rc;
813	}
814
815	for (i = (mid_x - SERDES_25G_EYE_X_MIN);
816		((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) &&
817			(i < (SERDES_25G_EYE_X_MAX - SERDES_25G_EYE_X_MIN + 1)));
818		i++, (_width)++)
819		;
820	for (i = (mid_x - SERDES_25G_EYE_X_MIN);
821		((samples[i] < SERDES_25G_EYE_SIZE_ERR_TH) && (i >= 0));
822		i--, (_width)++)
823		;
824
825	*height = _height;
826	*width = _width;
827
828	return 0;
829}
830
831
832static void al_serdes_25g_tx_advanced_params_set(struct al_serdes_grp_obj	*obj,
833					enum al_serdes_lane			lane,
834					void					*tx_params)
835{
836	struct al_serdes_adv_tx_params	*params = tx_params;
837	uint32_t timeout = 5000;
838	uint8_t val = 0;
839
840	al_serdes_25g_reg_masked_write(obj,
841					(enum al_serdes_reg_page)lane,
842					SERDES_25G_LANE_DRV_TXEQ_CTRL3_ADDR,
843					SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_MASK,
844					SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_SHIFT,
845					params->c_minus_1);
846
847	al_serdes_25g_reg_masked_write(obj,
848					(enum al_serdes_reg_page)lane,
849					SERDES_25G_LANE_DRV_TXEQ_CTRL1_ADDR,
850					SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_MASK,
851					SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_SHIFT,
852					params->c_plus_1);
853
854	al_serdes_25g_reg_masked_write(obj,
855					(enum al_serdes_reg_page)lane,
856					SERDES_25G_LANE_DRV_TXEQ_CTRL5_ADDR,
857					SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_MASK,
858					SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_SHIFT,
859					params->total_driver_units);
860
861	al_serdes_25g_reg_masked_write(obj,
862					(enum al_serdes_reg_page)lane,
863					SERDES_25G_LANE_DRV_TXEQ_CTRL0_ADDR,
864					SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_MASK,
865					SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_SHIFT,
866					1);
867
868
869	/* wait for acknowledge */
870	while (1) {
871		al_serdes_25g_reg_masked_read(obj,
872					(enum al_serdes_reg_page)lane,
873					SERDES_25G_LANE_DRV_TXEQ_STATUS0_ADDR,
874					SERDES_25G_LANE_DRV_TXEQ_STATUS0_ACK_MASK,
875					SERDES_25G_LANE_DRV_TXEQ_STATUS0_ACK_SHIFT,
876					&val);
877		if (val == 1)
878			break;
879
880		if (timeout == 0) {
881			al_err("%s: timeout occurred waiting to FW ack\n", __func__);
882			break;
883		}
884
885		timeout--;
886		al_udelay(1);
887	}
888
889	al_serdes_25g_reg_masked_write(obj,
890					(enum al_serdes_reg_page)lane,
891					SERDES_25G_LANE_DRV_TXEQ_CTRL0_ADDR,
892					SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_MASK,
893					SERDES_25G_LANE_DRV_TXEQ_CTRL0_REQ_SHIFT,
894					0);
895}
896
897static void al_serdes_25g_tx_advanced_params_get(struct al_serdes_grp_obj	*obj,
898		enum al_serdes_lane			lane,
899		void					*tx_params)
900{
901	struct al_serdes_adv_tx_params	*params = tx_params;
902
903	al_serdes_25g_reg_masked_read(obj,
904					(enum al_serdes_reg_page)lane,
905					SERDES_25G_LANE_DRV_TXEQ_CTRL3_ADDR,
906					SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_MASK,
907					SERDES_25G_LANE_DRV_TXEQ_CTRL3_TXEQ_CM1_SHIFT,
908					&params->c_minus_1);
909
910	al_serdes_25g_reg_masked_read(obj,
911					(enum al_serdes_reg_page)lane,
912					SERDES_25G_LANE_DRV_TXEQ_CTRL1_ADDR,
913					SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_MASK,
914					SERDES_25G_LANE_DRV_TXEQ_CTRL1_TXEQ_C1_SHIFT,
915					&params->c_plus_1);
916
917	al_serdes_25g_reg_masked_read(obj,
918					(enum al_serdes_reg_page)lane,
919					SERDES_25G_LANE_DRV_TXEQ_CTRL5_ADDR,
920					SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_MASK,
921					SERDES_25G_LANE_DRV_TXEQ_CTRL5_DRV_SWING_SHIFT,
922					&params->total_driver_units);
923}
924
925static al_bool al_serdes_25g_cdr_is_locked(
926		struct al_serdes_grp_obj	*obj,
927		enum al_serdes_lane		lane)
928{
929	uint8_t reg;
930
931	al_serdes_25g_reg_masked_read(obj,
932				(enum al_serdes_reg_page)lane,
933				SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_ADDR,
934				SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_LOCKED_MASK,
935				SERDES_25G_LANE_CDR_RXCLK_DLPF_STATUS5_LOCKED_SHIFT,
936				&reg);
937
938	return !!reg;
939
940}
941
942static al_bool al_serdes_25g_rx_valid(
943		struct al_serdes_grp_obj	*obj,
944		enum al_serdes_lane		lane)
945{
946	uint8_t reg;
947
948	al_serdes_25g_reg_masked_read(obj,
949				(enum al_serdes_reg_page)lane,
950				SERDES_25G_LANE_TOP_LN_STAT_CTRL0_ADDR,
951				SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_MASK,
952				SERDES_25G_LANE_TOP_LN_STAT_CTRL0_RXVALID_SHIFT,
953				&reg);
954
955	return !!reg;
956
957}
958
959static al_bool al_serdes_25g_signal_is_detected(
960		struct al_serdes_grp_obj	*obj,
961		enum al_serdes_lane		lane)
962{
963	struct al_serdes_c_regs __iomem	*regs_base = obj->regs_base;
964	uint32_t reg;
965	al_bool signal_detect = AL_FALSE;
966
967	reg = al_reg_read32(&regs_base->lane[lane].stat);
968
969	signal_detect = ((reg & (SERDES_C_LANE_STAT_LN_STAT_LOS |
970				 SERDES_C_LANE_STAT_LN_STAT_LOS_DEGLITCH)) ?
971					AL_FALSE : AL_TRUE);
972
973	return signal_detect;
974
975}
976
977static int al_serdes_25g_rx_equalization(
978		struct al_serdes_grp_obj	*obj,
979		enum al_serdes_lane		lane)
980{
981	struct al_serdes_c_regs __iomem	*regs_base = obj->regs_base;
982	uint32_t ready_mask = (SERDES_C_GEN_STATUS_CM0_RST_PD_READY | SERDES_C_GEN_STATUS_CM0_OK_O);
983	uint32_t reset_mask;
984	uint32_t timeout;
985	uint32_t reg_val;
986	uint32_t retries = AL_SERDES_25G_RESET_NUM_RETRIES;
987	int status = 0;
988
989	if (lane == 0) {
990		ready_mask |= SERDES_C_GEN_STATUS_LN0_RST_PD_READY;
991		reset_mask = SERDES_C_GEN_RST_LN0_RST_N;
992	} else {
993		ready_mask |= SERDES_C_GEN_STATUS_LN1_RST_PD_READY;
994		reset_mask = SERDES_C_GEN_RST_LN1_RST_N;
995	}
996
997	while (retries > 0) {
998		timeout = AL_SERDES_25G_WAIT_FOR_READY_TO;
999		status = 0;
1000
1001		al_reg_write32_masked(&regs_base->gen.rst, reset_mask, 0);
1002
1003		al_msleep(AL_SERDES_25G_RESET_TO);
1004
1005		al_serdes_25g_reg_masked_write(obj,
1006					(enum al_serdes_reg_page)lane,
1007					SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_ADDR,
1008					SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT0_EN_MASK,
1009					SERDES_25G_LANE_FEATURE_CTLE_ADAPT_MBS_CFG_INIT0_EN_SHIFT,
1010					0);
1011
1012		al_serdes_25g_reg_masked_write(obj,
1013					(enum al_serdes_reg_page)lane,
1014					SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_ADDR,
1015					SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBF_START_MASK,
1016					SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBF_START_SHIFT,
1017					7);
1018
1019		al_serdes_25g_reg_masked_write(obj,
1020					(enum al_serdes_reg_page)lane,
1021					SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_ADDR,
1022					SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBG_START_MASK,
1023					SERDES_25G_LANE_LEQ_REFCLK_EQ_MB_CTRL1_EQ_MBG_START_SHIFT,
1024					15);
1025
1026		al_msleep(AL_SERDES_25G_RESET_TO);
1027
1028		al_reg_write32_masked(&regs_base->gen.rst, reset_mask, reset_mask);
1029
1030		while (1) {
1031			reg_val = al_reg_read32(&regs_base->gen.status);
1032			if ((reg_val & ready_mask) == ready_mask)
1033				break;
1034
1035			al_udelay(1);
1036			timeout--;
1037
1038			if (timeout == 0) {
1039				al_err("%s: Timeout waiting for serdes ready\n", __func__);
1040				status = ETIMEDOUT;
1041				retries--;
1042				break;
1043			}
1044		}
1045
1046		if (status)
1047			continue;
1048
1049		while (1) {
1050			reg_val = al_reg_read32(&regs_base->lane[lane].stat);
1051			reg_val &= (SERDES_C_LANE_STAT_LNX_STAT_OK |
1052				    SERDES_C_LANE_STAT_LN_STAT_RXVALID);
1053			if (reg_val == (SERDES_C_LANE_STAT_LNX_STAT_OK |
1054					SERDES_C_LANE_STAT_LN_STAT_RXVALID))
1055				break;
1056
1057			al_udelay(1);
1058			timeout--;
1059
1060			if (timeout == 0) {
1061				al_err("%s: TO waiting for lane ready (%x)\n", __func__, reg_val);
1062				status = ETIMEDOUT;
1063				retries--;
1064				break;
1065			}
1066		}
1067
1068		if (status)
1069			continue;
1070
1071		break;
1072	}
1073
1074	if (retries == 0) {
1075		al_err("%s: Failed to run equalization\n", __func__);
1076		status = ETIMEDOUT;
1077	}
1078
1079	return status;
1080
1081}
1082
1083#define AL_SERDES_25G_GCFSM2_READ_TIMEOUT		2000000 /* uSec */
1084
1085static int al_serdes_25g_gcfsm2_read(
1086		struct al_serdes_grp_obj	*obj,
1087		enum al_serdes_lane		lane,
1088		uint8_t			offset,
1089		uint16_t		*data)
1090{
1091	int status = 0;
1092	uint32_t timeout = AL_SERDES_25G_GCFSM2_READ_TIMEOUT;
1093	uint8_t ack = 0;
1094	uint8_t data_low, data_high;
1095
1096	al_assert(data);
1097
1098	/* Make sure GCFSM2 REQuest is off */
1099	al_serdes_25g_reg_masked_write(
1100			obj,
1101			(enum al_serdes_reg_page)lane,
1102			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR,
1103			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK,
1104			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT,
1105			0);
1106	/* Write GCFSM2 CMD; CMD=0 for Read Request */
1107	al_serdes_25g_reg_masked_write(
1108			obj,
1109			(enum al_serdes_reg_page)lane,
1110			SERDES_25G_LANE_GCFSM2_CMD_CTRL1_ADDR,
1111			SERDES_25G_LANE_GCFSM2_CMD_CTRL1_CMD_MASK,
1112			SERDES_25G_LANE_GCFSM2_CMD_CTRL1_CMD_SHIFT,
1113			0);
1114	/* Write GCFSM2 the Address we wish to read */
1115	al_serdes_25g_reg_write(
1116			obj,
1117			(enum al_serdes_reg_page)lane,
1118			0,
1119			SERDES_25G_LANE_GCFSM2_CMD_CTRL2_ADDR,
1120			offset);
1121	/* Issue a command REQuest */
1122	al_serdes_25g_reg_masked_write(
1123			obj,
1124			(enum al_serdes_reg_page)lane,
1125			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR,
1126			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK,
1127			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT,
1128			1);
1129	/* Poll on GCFSM2 ACK */
1130	while (1) {
1131		al_serdes_25g_reg_masked_read(
1132				obj,
1133				(enum al_serdes_reg_page)lane,
1134				SERDES_25G_LANE_GCFSM2_CMD_STATUS_ADDR,
1135				SERDES_25G_LANE_GCFSM2_CMD_STATUS_ACK_MASK,
1136				SERDES_25G_LANE_GCFSM2_CMD_STATUS_ACK_SHIFT,
1137				&ack);
1138
1139		if (ack || (timeout == 0))
1140			break;
1141
1142		timeout--;
1143		al_udelay(1);
1144	}
1145
1146	if (ack) {
1147		/* Read 12bit of register value */
1148		al_serdes_25g_reg_read(
1149				obj,
1150				(enum al_serdes_reg_page)lane,
1151				0,
1152				SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS0_ADDR,
1153				&data_low);
1154		al_serdes_25g_reg_masked_read(
1155				obj,
1156				(enum al_serdes_reg_page)lane,
1157				SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_ADDR,
1158				SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_11_8_MASK,
1159				SERDES_25G_LANE_GCFSM2_READ_SHADOW_DATA_STATUS1_11_8_SHIFT,
1160				&data_high);
1161		*data = (data_high << 8) | data_low;
1162	} else {
1163		al_err("%s: TO waiting for GCFSM2 req to complete (%x)\n", __func__, offset);
1164		status = ETIMEDOUT;
1165	}
1166
1167	/* Deassert the GCFSM2 REQuest */
1168	al_serdes_25g_reg_masked_write(
1169			obj,
1170			(enum al_serdes_reg_page)lane,
1171			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_ADDR,
1172			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_MASK,
1173			SERDES_25G_LANE_GCFSM2_CMD_CTRL0_REQ_SHIFT,
1174			0);
1175
1176	return status;
1177}
1178
1179enum al_serdes_25g_rx_leq_fsm_opcode {
1180	AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ		= 0x1,
1181	AL_SERDES_25G_RX_LEQ_FSM_OPCODE_WRITE		= 0x2,
1182};
1183
1184enum al_serdes_25g_rx_leq_fsm_target {
1185	AL_SERDES_25G_RX_LEQ_FSM_TARGET_AGC_SOURCE		= 0x1,
1186	AL_SERDES_25G_RX_LEQ_FSM_TARGET_PLE_ATT			= 0x2,
1187	AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_LFG			= 0x3,
1188	AL_SERDES_25G_RX_LEQ_FSM_TARGET_GN_APG			= 0x4,
1189	AL_SERDES_25G_RX_LEQ_FSM_TARGET_GNEQ_CCL_LFG	= 0x5,
1190	AL_SERDES_25G_RX_LEQ_FSM_TARGET_HFG_SQL			= 0x6,
1191	AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBF			= 0x8,
1192	AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBG			= 0x9,
1193	AL_SERDES_25G_RX_LEQ_FSM_TARGET_VSCAN			= 0xA,
1194	AL_SERDES_25G_RX_LEQ_FSM_TARGET_HSCAN			= 0xB,
1195	AL_SERDES_25G_RX_LEQ_FSM_TARGET_EYE_INTF		= 0xC,
1196};
1197
1198#define AL_SERDES_25G_RX_LEQ_FSM_TIMEOUT		2000000 /* uSec */
1199
1200static int al_serdes_25g_rx_leq_fsm_op(
1201		struct al_serdes_grp_obj	*obj,
1202		enum al_serdes_lane	lane,
1203		enum al_serdes_25g_rx_leq_fsm_opcode	opcode,
1204		enum al_serdes_25g_rx_leq_fsm_target	target,
1205		uint8_t	val,
1206		uint8_t	*data,
1207		uint8_t	*err)
1208{
1209	uint32_t reg;
1210	uint32_t timeout = AL_SERDES_25G_RX_LEQ_FSM_TIMEOUT;
1211	uint8_t ack = 0;
1212	int status = 0;
1213
1214	al_assert(data);
1215	al_assert(err);
1216
1217	/* Write the OpCode & Target to LEQ FSM */
1218	reg = (target << 4) | opcode;
1219	al_serdes_25g_reg_write(
1220			obj,
1221			(enum al_serdes_reg_page)lane,
1222			0,
1223			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD0_ADDR,
1224			reg);
1225
1226	/* Write 0 as MiscOption value to LEQ FSM */
1227	al_serdes_25g_reg_write(
1228			obj,
1229			(enum al_serdes_reg_page)lane,
1230			0,
1231			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD2_ADDR,
1232			0);
1233
1234	/* Write the ArgumentValue to LEQ FSM if needed*/
1235	if (opcode == AL_SERDES_25G_RX_LEQ_FSM_OPCODE_WRITE) {
1236		al_serdes_25g_reg_write(
1237				obj,
1238				(enum al_serdes_reg_page)lane,
1239				0,
1240				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CMD1_ADDR,
1241				val);
1242	}
1243
1244	/* Issue an LEQ FSM Command Request */
1245	al_serdes_25g_reg_masked_write(
1246			obj,
1247			(enum al_serdes_reg_page)lane,
1248			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_ADDR,
1249			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_MASK,
1250			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_SHIFT,
1251			1);
1252
1253	/* Poll on LEQ FSM Command acknowledge */
1254	while (1) {
1255		al_serdes_25g_reg_masked_read(
1256				obj,
1257				(enum al_serdes_reg_page)lane,
1258				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_ADDR,
1259				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_LEQ_FSM_CMD_ACK_MASK,
1260				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS5_LEQ_FSM_CMD_ACK_SHIFT,
1261				&ack);
1262
1263		if (ack || (timeout == 0))
1264			break;
1265
1266		timeout--;
1267		al_udelay(1);
1268	}
1269
1270	if (ack) {
1271		uint8_t err1, err2;
1272		al_serdes_25g_reg_read(
1273				obj,
1274				(enum al_serdes_reg_page)lane,
1275				0,
1276				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_ADDR,
1277				err);
1278
1279		err1 = (*err &
1280			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR1_MASK) >>
1281			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR1_SHIFT;
1282		err2 = (*err &
1283			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR2_MASK) >>
1284			SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS0_LEQ_FSM_STATUS_ERROR2_SHIFT;
1285
1286		if (err1 || err2) {
1287			al_err("%s: error in RX LEQ FSM req, err status 1=0x%x, err status 2=0x%x",
1288					__func__, err1, err2);
1289			status = -EIO;
1290		}
1291
1292		/* Read LEQ FSM Command return Value */
1293		al_serdes_25g_reg_read(
1294				obj,
1295				(enum al_serdes_reg_page)lane,
1296				0,
1297				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_STATUS3_ADDR,
1298				data);
1299
1300		/* Clear an LEQ FSM Command Request */
1301		al_serdes_25g_reg_masked_write(
1302				obj,
1303				(enum al_serdes_reg_page)lane,
1304				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_ADDR,
1305				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_MASK,
1306				SERDES_25G_LANE_LEQ_REFCLK_LEQ_FSM_CTRL0_LEQ_FSM_CMD_REQ_SHIFT,
1307				0);
1308	} else {
1309		al_err("%s: TO waiting for RX LEQ FSM req to complete (opcode %x, target %x, val %x)\n",
1310				__func__, opcode, target, val);
1311		status = ETIMEDOUT;
1312	}
1313
1314	return status;
1315}
1316
1317/* enum values correspond to HW values, don't change! */
1318enum al_serdes_25g_tbus_obj {
1319	AL_SERDES_25G_TBUS_OBJ_TOP	= 0,
1320	AL_SERDES_25G_TBUS_OBJ_CMU	= 1,
1321	AL_SERDES_25G_TBUS_OBJ_LANE	= 2,
1322};
1323
1324#define AL_SERDES_25G_TBUS_DELAY	1000 /* uSec */
1325#define AL_SERDES_25G_TBUS_ADDR_HIGH_SHIFT	5
1326
1327static int al_serdes_25g_tbus_read(
1328		struct al_serdes_grp_obj	*obj,
1329		enum al_serdes_lane	lane,
1330		enum al_serdes_25g_tbus_obj	tbus_obj,
1331		uint8_t	offset,
1332		uint16_t	*data)
1333{
1334	uint8_t addr_high, val_high, val_low;
1335
1336	al_assert(lane < AL_SRDS_NUM_LANES);
1337
1338	if (tbus_obj == AL_SERDES_25G_TBUS_OBJ_TOP)
1339		addr_high = AL_SERDES_25G_TBUS_OBJ_TOP;
1340	else if (tbus_obj == AL_SERDES_25G_TBUS_OBJ_CMU)
1341		addr_high = AL_SERDES_25G_TBUS_OBJ_CMU;
1342	else
1343		addr_high = AL_SERDES_25G_TBUS_OBJ_LANE + lane;
1344
1345	addr_high <<= AL_SERDES_25G_TBUS_ADDR_HIGH_SHIFT;
1346
1347	al_serdes_25g_reg_write(
1348			obj,
1349			AL_SRDS_REG_PAGE_TOP,
1350			0,
1351			SERDES_25G_TOP_TBUS_ADDR_7_0_ADDR,
1352			offset);
1353
1354	al_serdes_25g_reg_write(
1355			obj,
1356			AL_SRDS_REG_PAGE_TOP,
1357			0,
1358			SERDES_25G_TOP_TBUS_ADDR_15_8_ADDR,
1359			addr_high);
1360
1361	al_udelay(AL_SERDES_25G_TBUS_DELAY);
1362
1363	al_serdes_25g_reg_read(
1364			obj,
1365			AL_SRDS_REG_PAGE_TOP,
1366			0,
1367			SERDES_25G_TOP_TBUS_DATA_7_0_ADDR,
1368			&val_low);
1369
1370	al_serdes_25g_reg_masked_read(
1371			obj,
1372			AL_SRDS_REG_PAGE_TOP,
1373			SERDES_25G_TOP_TBUS_DATA_11_8_ADDR,
1374			SERDES_25G_TOP_TBUS_DATA_11_8_MASK,
1375			SERDES_25G_TOP_TBUS_DATA_11_8_SHIFT,
1376			&val_high);
1377
1378	*data = (val_high << 8) | val_low;
1379
1380	return 0;
1381}
1382
1383#define AL_SERDES_25G_RX_ADV_PARAMS_ATT_MASK	0x07
1384#define AL_SERDES_25G_RX_ADV_PARAMS_APG_MASK	0x03
1385#define AL_SERDES_25G_RX_ADV_PARAMS_LFG_MASK	0x1F
1386#define AL_SERDES_25G_RX_ADV_PARAMS_HFG_MASK	0x1F
1387#define AL_SERDES_25G_RX_ADV_PARAMS_MBG_MASK	0x0F
1388#define AL_SERDES_25G_RX_ADV_PARAMS_MBF_MASK	0x0F
1389#define AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_CNT			8
1390#define AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_MASK		0x1F
1391#define AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_SIGN_SHIFT	7
1392
1393static void al_serdes_25g_rx_advanced_params_get(
1394		struct al_serdes_grp_obj	*obj,
1395		enum al_serdes_lane			lane,
1396		void					*rx_params)
1397{
1398	struct al_serdes_25g_adv_rx_params *params = rx_params;
1399	uint8_t value, err;
1400	int8_t tap_weight;
1401	uint8_t tap_sign;
1402	int8_t *tap_ptr_arr[AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_CNT];
1403	int rc;
1404	int i;
1405
1406	rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ,
1407			AL_SERDES_25G_RX_LEQ_FSM_TARGET_PLE_ATT, 0, &value, &err);
1408	if (rc || err) {
1409		al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read att, rc %d, err %d\n",
1410				__func__, rc, err);
1411		return;
1412	}
1413	params->att = value & AL_SERDES_25G_RX_ADV_PARAMS_ATT_MASK;
1414
1415	rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ,
1416			AL_SERDES_25G_RX_LEQ_FSM_TARGET_GN_APG, 0, &value, &err);
1417	if (rc || err) {
1418		al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read apg, rc %d, err %d\n",
1419				__func__, rc, err);
1420		return;
1421	}
1422	params->apg = value & AL_SERDES_25G_RX_ADV_PARAMS_APG_MASK;
1423
1424	rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ,
1425			AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_LFG, 0, &value, &err);
1426	if (rc || err) {
1427		al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read lfg, rc %d, err %d\n",
1428				__func__, rc, err);
1429		return;
1430	}
1431	params->lfg = value & AL_SERDES_25G_RX_ADV_PARAMS_LFG_MASK;
1432
1433	rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ,
1434			AL_SERDES_25G_RX_LEQ_FSM_TARGET_HFG_SQL, 0, &value, &err);
1435	if (rc || err) {
1436		al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read hfg, rc %d, err %d\n",
1437				__func__, rc, err);
1438		return;
1439	}
1440	params->hfg = value & AL_SERDES_25G_RX_ADV_PARAMS_HFG_MASK;
1441
1442	rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ,
1443			AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBG, 0, &value, &err);
1444	if (rc || err) {
1445		al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read mbg, rc %d, err %d\n",
1446				__func__, rc, err);
1447		return;
1448	}
1449	params->mbg = value & AL_SERDES_25G_RX_ADV_PARAMS_MBG_MASK;
1450
1451	rc = al_serdes_25g_rx_leq_fsm_op(obj, lane, AL_SERDES_25G_RX_LEQ_FSM_OPCODE_READ,
1452			AL_SERDES_25G_RX_LEQ_FSM_TARGET_EQ_MBF, 0, &value, &err);
1453	if (rc || err) {
1454		al_err("%s: al_serdes_25g_rx_leq_fsm_op failed to read mbf, rc %d, err %d\n",
1455				__func__, rc, err);
1456		return;
1457	}
1458	params->mbf = value & AL_SERDES_25G_RX_ADV_PARAMS_MBF_MASK;
1459
1460	tap_ptr_arr[0] = &params->dfe_first_tap_even0_ctrl;
1461	tap_ptr_arr[1] = &params->dfe_first_tap_even1_ctrl;
1462	tap_ptr_arr[2] = &params->dfe_first_tap_odd0_ctrl;
1463	tap_ptr_arr[3] = &params->dfe_first_tap_odd1_ctrl;
1464	tap_ptr_arr[4] = &params->dfe_second_tap_ctrl;
1465	tap_ptr_arr[5] = &params->dfe_third_tap_ctrl;
1466	tap_ptr_arr[6] = &params->dfe_fourth_tap_ctrl;
1467	tap_ptr_arr[7] = &params->dfe_fifth_tap_ctrl;
1468
1469	for (i = 0; i < AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_CNT; i++) {
1470		al_serdes_25g_reg_read(
1471				obj,
1472				(enum al_serdes_reg_page)lane,
1473				0,
1474				SERDES_25G_LANE_DFE_REFCLK_TAP_VAL_STATUS0_ADDR + i,
1475				&value);
1476
1477		tap_weight = value & AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_MASK;
1478		tap_sign = (value & AL_BIT(AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_SIGN_SHIFT)) >>
1479				AL_SERDES_25G_RX_ADV_PARAMS_DFE_TAP_SIGN_SHIFT;
1480		if (tap_sign == 0)
1481			tap_weight = 0 - tap_weight;
1482
1483		*tap_ptr_arr[i] = tap_weight;
1484	}
1485}
1486
1487#define AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_ADDR		0x0B
1488#define AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_MASK		0x3F
1489#define AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_SIGN_SHIFT	7
1490#define AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_ADDR		0x0C
1491#define AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_MASK		0xFFF
1492
1493static void al_serdes_25g_tx_diag_info_get(
1494		struct al_serdes_grp_obj	*obj,
1495		enum al_serdes_lane		lane,
1496		void *tx_info)
1497{
1498	struct al_serdes_25g_tx_diag_info *info = tx_info;
1499	uint8_t cal_x1, cal_x1_fixed, cal_x2, cal_xp5_fixed;
1500	uint16_t val16, sign;
1501	uint8_t val8, abs;
1502	int rc;
1503
1504	al_serdes_25g_reg_read(
1505			obj,
1506			(enum al_serdes_reg_page)lane,
1507			0,
1508			SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_ADDR,
1509			&val8);
1510	info->regulated_supply = val8 & SERDES_25G_LANE_TOP_AFE_TXCP_CTRL0_REG_TXCP_TRIM_MASK;
1511
1512	rc = al_serdes_25g_gcfsm2_read(
1513			obj,
1514			lane,
1515			AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_ADDR,
1516			&val16);
1517	if (rc) {
1518		al_err("%s: al_serdes_25g_gcfsm2_read failed to read dcd_trim, rc %d\n",
1519				__func__, rc);
1520		return;
1521	}
1522
1523	abs = val16 & AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_MASK;
1524	sign = (val16 & AL_BIT(AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_SIGN_SHIFT)) >>
1525			AL_SERDES_25G_TX_DIAG_GCFSM2_DCD_TRIM_SIGN_SHIFT;
1526	if (sign)
1527		info->dcd_trim = abs;
1528	else
1529		info->dcd_trim = 0 - abs;
1530
1531	rc = al_serdes_25g_gcfsm2_read(
1532			obj,
1533			lane,
1534			AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_ADDR,
1535			&val16);
1536	if (rc) {
1537		al_err("%s: al_serdes_25g_gcfsm2_read failed to read clk_delay, rc %d\n",
1538				__func__, rc);
1539		return;
1540	}
1541	info->clk_delay = val16 & AL_SERDES_25G_TX_DIAG_GCFSM2_CLK_DELAY_MASK;
1542
1543	al_serdes_25g_reg_read(
1544			obj,
1545			(enum al_serdes_reg_page)lane,
1546			0,
1547			SERDES_25G_CM_TOP_AFE_TXTC_CTRL2_ADDR,
1548			&val8);
1549	cal_x1 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_MASK) >>
1550			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_SHIFT;
1551	cal_x1_fixed = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_FIXED_MASK) >>
1552			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL2_TXTC_CALP_X1_FIXED_SHIFT;
1553	al_serdes_25g_reg_read(
1554			obj,
1555			(enum al_serdes_reg_page)lane,
1556			0,
1557			SERDES_25G_CM_TOP_AFE_TXTC_CTRL3_ADDR,
1558			&val8);
1559	cal_x2 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_X2_MASK) >>
1560			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_X2_SHIFT;
1561	cal_xp5_fixed = (val8 &
1562			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_XP5_FIXED_MASK) >>
1563					SERDES_25G_CMU_TOP_AFE_TXTC_CTRL3_TXTC_CALP_XP5_FIXED_SHIFT;
1564	info->calp_multiplied_by_2 = 4 * cal_x2 + 2 * cal_x1 + 2 * cal_x1_fixed + cal_xp5_fixed;
1565
1566	al_serdes_25g_reg_read(
1567			obj,
1568			(enum al_serdes_reg_page)lane,
1569			0,
1570			SERDES_25G_CM_TOP_AFE_TXTC_CTRL0_ADDR,
1571			&val8);
1572	cal_x1 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_MASK) >>
1573			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_SHIFT;
1574	cal_x1_fixed = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_FIXED_MASK) >>
1575			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL0_TXTC_CALN_X1_FIXED_SHIFT;
1576	al_serdes_25g_reg_read(
1577			obj,
1578			(enum al_serdes_reg_page)lane,
1579			0,
1580			SERDES_25G_CM_TOP_AFE_TXTC_CTRL1_ADDR,
1581			&val8);
1582	cal_x2 = (val8 & SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_X2_MASK) >>
1583			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_X2_SHIFT;
1584	cal_xp5_fixed = (val8 &
1585			SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_XP5_FIXED_MASK) >>
1586					SERDES_25G_CMU_TOP_AFE_TXTC_CTRL1_TXTC_CALN_XP5_FIXED_SHIFT;
1587	info->caln_multiplied_by_2 = 4 * cal_x2 + 2 * cal_x1 + 2 * cal_x1_fixed + cal_xp5_fixed;
1588}
1589
1590#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_ABS_MASK			0x1F
1591#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK				0x3F
1592#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_SIGN_SHIFT		5
1593#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK			0xFC0
1594#define AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT		6
1595#define AL_SERDES_25G_RX_DIAG_LEQ_EQ_COUNT					5
1596#define AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_EQ_ADDR			0
1597#define AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_GAINSTAGE_ADDR		0x5
1598#define AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_EVEN_ADDR		0x6
1599#define AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_ODD_ADDR		0x7
1600#define AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_EVEN_ADDR		0x8
1601#define AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_ODD_ADDR			0x9
1602#define AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_ADDR		0xF
1603#define AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_MASK		0xFFF
1604#define AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_EVEN_ADDR	0x11
1605#define AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_ODD_ADDR		0x12
1606#define AL_SERDES_25G_RX_DIAG_TBUS_EDGE_SLICER_ADDR			0x13
1607#define AL_SERDES_25G_RX_DIAG_TBUS_EYE_SLICER_ADDR			0x23
1608#define AL_SERDES_25G_RX_DIAG_TBUS_CDR_CLK_Q_ADDR			0x2
1609#define AL_SERDES_25G_RX_DIAG_TBUS_CDR_CLK_I_ADDR			0x1
1610#define AL_SERDES_25G_RX_DIAG_CDR_RXCLK_DLPF_L_ADDR			0x26
1611#define AL_SERDES_25G_RX_DIAG_CDR_RXCLK_DLPF_H_ADDR			0x27
1612
1613static inline void al_serdes_25g_rx_diag_5bit_signed_set(uint8_t packed_val, int8_t *ptr)
1614{
1615	uint8_t abs, sign;
1616
1617	abs = packed_val & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_ABS_MASK;
1618	sign = (packed_val & AL_BIT(AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_SIGN_SHIFT)) >>
1619			AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_SIGN_SHIFT;
1620	if (sign)
1621		*ptr = abs;
1622	else
1623		*ptr = 0 - abs;
1624}
1625
1626static void al_serdes_25g_rx_diag_info_get(
1627		struct al_serdes_grp_obj	*obj,
1628		enum al_serdes_lane		lane,
1629		void *rx_info)
1630{
1631	struct al_serdes_25g_rx_diag_info *info = rx_info;
1632	uint16_t val16;
1633	uint8_t val8, val8_2;
1634	int rc;
1635	int i;
1636
1637	al_serdes_25g_reg_read(
1638			obj,
1639			(enum al_serdes_reg_page)lane,
1640			0,
1641			SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS0_ADDR,
1642			&val8);
1643	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->los_offset);
1644
1645	al_serdes_25g_reg_read(
1646			obj,
1647			(enum al_serdes_reg_page)lane,
1648			0,
1649			SERDES_25G_LANE_LOS_REFCLK_CALIBRATION_STATUS1_ADDR,
1650			&val8);
1651	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->agc_offset);
1652
1653	rc = al_serdes_25g_gcfsm2_read(
1654			obj,
1655			lane,
1656			AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_GAINSTAGE_ADDR,
1657			&val16);
1658	if (rc) {
1659		al_err("%s: al_serdes_25g_gcfsm2_read failed to read leq_gainstage, rc %d\n",
1660				__func__, rc);
1661		return;
1662	}
1663	val8 = (uint8_t)val16;
1664	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_gainstage_offset);
1665
1666	for (i = 0; i < AL_SERDES_25G_RX_DIAG_LEQ_EQ_COUNT; i++) {
1667		rc = al_serdes_25g_gcfsm2_read(
1668				obj,
1669				lane,
1670				AL_SERDES_25G_RX_DIAG_GCFSM2_LEQ_EQ_ADDR + i,
1671				&val16);
1672		if (rc) {
1673			al_err("%s: al_serdes_25g_gcfsm2_read failed to read leq_eq %d, rc %d\n",
1674					__func__, i, rc);
1675			return;
1676		}
1677		val8 = (uint8_t)val16;
1678
1679		switch (i) {
1680		case 0:
1681			al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq1_offset);
1682			break;
1683		case 1:
1684			al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq2_offset);
1685			break;
1686		case 2:
1687			al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq3_offset);
1688			break;
1689		case 3:
1690			al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq4_offset);
1691			break;
1692		case 4:
1693			al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->leq_eq5_offset);
1694			break;
1695		default:
1696			break;
1697		}
1698	}
1699
1700	rc = al_serdes_25g_gcfsm2_read(
1701			obj,
1702			lane,
1703			AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_EVEN_ADDR,
1704			&val16);
1705	if (rc) {
1706		al_err("%s: al_serdes_25g_gcfsm2_read failed to read summer_even_offset, rc %d\n",
1707				__func__, rc);
1708		return;
1709	}
1710	val8 = (uint8_t)val16;
1711	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->summer_even_offset);
1712
1713	rc = al_serdes_25g_gcfsm2_read(
1714			obj,
1715			lane,
1716			AL_SERDES_25G_RX_DIAG_GCFSM2_SUMMER_ODD_ADDR,
1717			&val16);
1718	if (rc) {
1719		al_err("%s: al_serdes_25g_gcfsm2_read failed to read summer_odd_offset, rc %d\n",
1720				__func__, rc);
1721		return;
1722	}
1723	val8 = (uint8_t)val16;
1724	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->summer_odd_offset);
1725
1726	rc = al_serdes_25g_gcfsm2_read(
1727			obj,
1728			lane,
1729			AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_EVEN_ADDR,
1730			&val16);
1731	if (rc) {
1732		al_err("%s: al_serdes_25g_gcfsm2_read failed to read vscan_even_offset, rc %d\n",
1733				__func__, rc);
1734		return;
1735	}
1736	val8 = (uint8_t)val16;
1737	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->vscan_even_offset);
1738
1739	rc = al_serdes_25g_gcfsm2_read(
1740			obj,
1741			lane,
1742			AL_SERDES_25G_RX_DIAG_GCFSM2_VSCAN_ODD_ADDR,
1743			&val16);
1744	if (rc) {
1745		al_err("%s: al_serdes_25g_gcfsm2_read failed to read vscan_odd_offset, rc %d\n",
1746				__func__, rc);
1747		return;
1748	}
1749	val8 = (uint8_t)val16;
1750	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->vscan_odd_offset);
1751
1752	al_serdes_25g_tbus_read(
1753			obj,
1754			lane,
1755			AL_SERDES_25G_TBUS_OBJ_LANE,
1756			AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_EVEN_ADDR,
1757			&val16);
1758	val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK);
1759	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_even0_offset);
1760	val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >>
1761			AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT);
1762	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_even1_offset);
1763
1764	al_serdes_25g_tbus_read(
1765			obj,
1766			lane,
1767			AL_SERDES_25G_TBUS_OBJ_LANE,
1768			AL_SERDES_25G_RX_DIAG_TBUS_DATA_SLICER_ODD_ADDR,
1769			&val16);
1770	val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK);
1771	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_odd0_offset);
1772	val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >>
1773			AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT);
1774	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->data_slicer_odd1_offset);
1775
1776	al_serdes_25g_tbus_read(
1777			obj,
1778			lane,
1779			AL_SERDES_25G_TBUS_OBJ_LANE,
1780			AL_SERDES_25G_RX_DIAG_TBUS_EDGE_SLICER_ADDR,
1781			&val16);
1782	val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK);
1783	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->edge_slicer_even_offset);
1784	val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >>
1785			AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT);
1786	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->edge_slicer_odd_offset);
1787
1788	al_serdes_25g_tbus_read(
1789			obj,
1790			lane,
1791			AL_SERDES_25G_TBUS_OBJ_LANE,
1792			AL_SERDES_25G_RX_DIAG_TBUS_EYE_SLICER_ADDR,
1793			&val16);
1794	val8 = (uint8_t)(val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_MASK);
1795	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->eye_slicer_even_offset);
1796	val8 = (uint8_t)((val16 & AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_MASK) >>
1797			AL_SERDES_25G_RX_DIAG_SIGNED_5BIT_HIGH_SHIFT);
1798	al_serdes_25g_rx_diag_5bit_signed_set(val8, &info->eye_slicer_odd_offset);
1799
1800	al_serdes_25g_reg_masked_read(
1801			obj,
1802			(enum al_serdes_reg_page)lane,
1803			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_ADDR,
1804			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_RXCDR_HSCAN_CLKQ_MASK,
1805			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL0_RXCDR_HSCAN_CLKQ_SHIFT,
1806			&info->cdr_clk_q);
1807
1808	al_serdes_25g_reg_masked_read(
1809			obj,
1810			(enum al_serdes_reg_page)lane,
1811			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_ADDR,
1812			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_RXCDR_HSCAN_CLKI_MASK,
1813			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL1_RXCDR_HSCAN_CLKI_SHIFT,
1814			&info->cdr_clk_i);
1815
1816	al_serdes_25g_reg_masked_read(
1817			obj,
1818			(enum al_serdes_reg_page)lane,
1819			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_ADDR,
1820			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_RXCDR_HSCAN_EYE_MASK,
1821			SERDES_25G_LANE_CDR_REFCLK_AFE_PI_CTRL2_RXCDR_HSCAN_EYE_SHIFT,
1822			&info->cdr_dll);
1823
1824	al_serdes_25g_reg_masked_read(
1825			obj,
1826			(enum al_serdes_reg_page)lane,
1827			SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_ADDR,
1828			SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_RXCDR_DOSC_MASK,
1829			SERDES_25G_LANE_CDR_REFCLK_AFE_VCO_CTRL2_RXCDR_DOSC_SHIFT,
1830			&info->cdr_vco_dosc);
1831
1832	al_serdes_25g_reg_read(
1833			obj,
1834			(enum al_serdes_reg_page)lane,
1835			0,
1836			SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_ADDR,
1837			&val8_2);
1838	al_serdes_25g_reg_read(
1839			obj,
1840			(enum al_serdes_reg_page)lane,
1841			0,
1842			SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL0_ADDR,
1843			&val8);
1844	val8_2 &= SERDES_25G_LANE_CDR_RXCLK_LOAD_MODE_CTRL1_DLPF_VAL_8_MASK;
1845	info->cdr_dlpf = (uint16_t)val8_2 << 8 | val8;
1846
1847	rc = al_serdes_25g_gcfsm2_read(
1848			obj,
1849			lane,
1850			AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_ADDR,
1851			&val16);
1852	if (rc) {
1853		al_err("%s: al_serdes_25g_gcfsm2_read failed to read cdr_vco_fr, rc %d\n",
1854				__func__, rc);
1855		return;
1856	}
1857	info->cdr_vco_fr = val16 & AL_SERDES_25G_RX_DIAG_GCFSM2_CDR_VCO_FR_MASK;
1858
1859	al_serdes_25g_reg_masked_read(
1860			obj,
1861			(enum al_serdes_reg_page)lane,
1862			SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_ADDR,
1863			SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_BLW_ZERO_MASK,
1864			SERDES_25G_LANE_LEQ_REFCLK_AFE_PLE_CTRL0_RXLEQ_PLE_BLW_ZERO_SHIFT,
1865			&info->ple_resistance);
1866
1867	al_serdes_25g_reg_read(
1868			obj,
1869			(enum al_serdes_reg_page)lane,
1870			0,
1871			SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_ADDR,
1872			&val8);
1873
1874	info->rx_term_mode = (val8 & SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_MASK) >>
1875			SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_HIZ_SHIFT;
1876
1877	info->rx_coupling = (val8 & SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_MASK) >>
1878			SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL0_RXTERM_VCM_GND_SHIFT;
1879
1880	al_serdes_25g_reg_masked_read(
1881			obj,
1882			(enum al_serdes_reg_page)lane,
1883			SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_ADDR,
1884			SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_MASK,
1885			SERDES_25G_LANE_TOP_AFE_RXTERM_CTRL1_RXTERM_VAL_SHIFT,
1886			&info->rx_term_cal_code);
1887
1888	al_serdes_25g_reg_masked_read(
1889			obj,
1890			(enum al_serdes_reg_page)lane,
1891			SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_ADDR,
1892			SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_BIASI_TRIM_MASK,
1893			SERDES_25G_LANE_LEQ_REFCLK_AFE_BIAS_CTRL1_RXLEQ_BIASI_TRIM_SHIFT,
1894			&info->rx_sheet_res_cal_code);
1895}
1896
1897/******************************************************************************/
1898/******************************************************************************/
1899int al_serdes_25g_handle_init(
1900	void __iomem			*serdes_regs_base,
1901	struct al_serdes_grp_obj	*obj)
1902{
1903	al_dbg(
1904		"%s(%p, %p)\n",
1905		__func__,
1906		serdes_regs_base,
1907		obj);
1908
1909	al_memset(obj, 0, sizeof(struct al_serdes_grp_obj));
1910
1911	obj->regs_base = (struct al_serdes_regs *)serdes_regs_base;
1912	obj->type_get = al_serdes_25g_type_get;
1913	obj->reg_read = al_serdes_25g_reg_read;
1914	obj->reg_write = al_serdes_25g_reg_write;
1915	obj->bist_overrides_enable = NULL;
1916	obj->bist_overrides_disable = NULL;
1917	obj->rx_rate_change = NULL;
1918	obj->group_pm_set = NULL;
1919	obj->lane_pm_set = NULL;
1920	obj->pma_hard_reset_group = NULL;
1921	obj->pma_hard_reset_lane = NULL;
1922	obj->loopback_control = NULL;
1923	obj->bist_pattern_select = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_pattern_select);
1924	obj->bist_tx_enable = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_tx_enable);
1925	obj->bist_tx_err_inject = NULL;
1926	obj->bist_rx_enable = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_rx_enable);
1927	obj->bist_rx_status = AL_SRDS_ADV_SRVC(al_serdes_25g_bist_rx_status);
1928	obj->tx_deemph_preset = NULL;
1929	obj->tx_deemph_inc = NULL;
1930	obj->tx_deemph_dec = NULL;
1931	obj->eye_measure_run = NULL;
1932	obj->eye_diag_sample = NULL;
1933	obj->eye_diag_run = AL_SRDS_ADV_SRVC(al_serdes_25g_eye_diag_run);
1934	obj->cdr_is_locked = AL_SRDS_ADV_SRVC(al_serdes_25g_cdr_is_locked);
1935	obj->rx_valid = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_valid);
1936	obj->signal_is_detected = AL_SRDS_ADV_SRVC(al_serdes_25g_signal_is_detected);
1937	obj->tx_advanced_params_set = AL_SRDS_ADV_SRVC(al_serdes_25g_tx_advanced_params_set);
1938	obj->tx_advanced_params_get = AL_SRDS_ADV_SRVC(al_serdes_25g_tx_advanced_params_get);
1939	obj->rx_advanced_params_set = NULL;
1940	obj->rx_advanced_params_get = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_advanced_params_get);
1941	obj->tx_diag_info_get = AL_SRDS_ADV_SRVC(al_serdes_25g_tx_diag_info_get);
1942	obj->rx_diag_info_get = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_diag_info_get);
1943	obj->mode_set_sgmii = NULL;
1944	obj->mode_set_kr = NULL;
1945	obj->rx_equalization = AL_SRDS_ADV_SRVC(al_serdes_25g_rx_equalization);
1946	obj->calc_eye_size = AL_SRDS_ADV_SRVC(al_serdes_25g_calc_eye_size);
1947	obj->sris_config = NULL;
1948
1949	return 0;
1950}
1951
1952