1 /*******************************************************************************
2 Copyright (C) 2015 Annapurna Labs Ltd.
3
4 This file may be licensed under the terms of the Annapurna Labs Commercial
5 License Agreement.
6
7 Alternatively, this file can be distributed under the terms of the GNU General
8 Public License V2 as published by the Free Software Foundation and can be
9 found at http://www.gnu.org/licenses/gpl-2.0.html
10
11 Alternatively, redistribution and use in source and binary forms, with or
12 without modification, are permitted provided that the following conditions are
13 met:
14
15 * Redistributions of source code must retain the above copyright notice,
16 this list of conditions and the following disclaimer.
17
18 * Redistributions in binary form must reproduce the above copyright
19 notice, this list of conditions and the following disclaimer in
20 the documentation and/or other materials provided with the
21 distribution.
22
23 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30 ANY 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
32 SOFTWARE, 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
al_serdes_hssp_stub_func(void)49 static 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 /******************************************************************************/
al_serdes_25g_type_get(void)59 static enum al_serdes_type al_serdes_25g_type_get(void)
60 {
61 return AL_SRDS_TYPE_25G;
62 }
63
64 /******************************************************************************/
65 /******************************************************************************/
al_serdes_25g_reg_read(struct al_serdes_grp_obj * obj,enum al_serdes_reg_page page,enum al_serdes_reg_type type,uint16_t offset,uint8_t * data)66 static 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(®s_base->gen.reg_addr, addr);
98 *data = al_reg_read32(®s_base->gen.reg_data);
99
100 al_dbg("%s: return(%u)\n", __func__, *data);
101
102 return 0;
103 }
104
al_serdes_25g_reg_write(struct al_serdes_grp_obj * obj,enum al_serdes_reg_page page,enum al_serdes_reg_type type,uint16_t offset,uint8_t data)105 static 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(®s_base->gen.reg_addr, addr);
136 al_reg_write32(®s_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 /******************************************************************************/
al_serdes_25g_reg_masked_read(struct al_serdes_grp_obj * obj,enum al_serdes_reg_page page,uint16_t offset,uint8_t mask,uint8_t shift,uint8_t * data)145 static 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
al_serdes_25g_reg_masked_write(struct al_serdes_grp_obj * obj,enum al_serdes_reg_page page,uint16_t offset,uint8_t mask,uint8_t shift,uint8_t data)165 static 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
al_serdes_25g_mailbox_send_cmd(struct al_serdes_grp_obj * obj,uint8_t cmd,uint8_t * data,uint8_t data_len)190 static 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
al_serdes_25g_mailbox_recv_rsp(struct al_serdes_grp_obj * obj,uint8_t * rsp_code,uint8_t * data,uint8_t * data_len)232 static 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 /******************************************************************************/
al_serdes_25g_bist_rx_enable(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,al_bool enable)279 static 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.
al_serdes_25g_bist_pattern_select(struct al_serdes_grp_obj * obj,enum al_serdes_bist_pattern pattern,uint8_t * user_data)377 static 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
al_serdes_25g_bist_tx_enable(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,al_bool enable)428 static 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
al_serdes_25g_bist_rx_status(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,al_bool * is_locked,al_bool * err_cnt_overflow,uint32_t * err_cnt)484 static 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
al_serdes_25g_eye_diag_run(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,int x_start,int x_stop,unsigned int x_step,int y_start,int y_stop,unsigned int y_step,uint64_t ber_target,uint64_t * buf,uint32_t buf_size)547 static 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
al_serdes_25g_calc_eye_size(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,int * width,int * height)752 static 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
al_serdes_25g_tx_advanced_params_set(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,void * tx_params)832 static 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
al_serdes_25g_tx_advanced_params_get(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,void * tx_params)897 static 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 ¶ms->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 ¶ms->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 ¶ms->total_driver_units);
923 }
924
al_serdes_25g_cdr_is_locked(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane)925 static 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 ®);
937
938 return !!reg;
939
940 }
941
al_serdes_25g_rx_valid(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane)942 static 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 ®);
954
955 return !!reg;
956
957 }
958
al_serdes_25g_signal_is_detected(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane)959 static 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(®s_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
al_serdes_25g_rx_equalization(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane)977 static 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(®s_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(®s_base->gen.rst, reset_mask, reset_mask);
1029
1030 while (1) {
1031 reg_val = al_reg_read32(®s_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(®s_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
al_serdes_25g_gcfsm2_read(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,uint8_t offset,uint16_t * data)1085 static 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
1179 enum 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
1184 enum 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
al_serdes_25g_rx_leq_fsm_op(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,enum al_serdes_25g_rx_leq_fsm_opcode opcode,enum al_serdes_25g_rx_leq_fsm_target target,uint8_t val,uint8_t * data,uint8_t * err)1200 static 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! */
1318 enum 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
al_serdes_25g_tbus_read(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,enum al_serdes_25g_tbus_obj tbus_obj,uint8_t offset,uint16_t * data)1327 static 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
al_serdes_25g_rx_advanced_params_get(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,void * rx_params)1393 static 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] = ¶ms->dfe_first_tap_even0_ctrl;
1461 tap_ptr_arr[1] = ¶ms->dfe_first_tap_even1_ctrl;
1462 tap_ptr_arr[2] = ¶ms->dfe_first_tap_odd0_ctrl;
1463 tap_ptr_arr[3] = ¶ms->dfe_first_tap_odd1_ctrl;
1464 tap_ptr_arr[4] = ¶ms->dfe_second_tap_ctrl;
1465 tap_ptr_arr[5] = ¶ms->dfe_third_tap_ctrl;
1466 tap_ptr_arr[6] = ¶ms->dfe_fourth_tap_ctrl;
1467 tap_ptr_arr[7] = ¶ms->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
al_serdes_25g_tx_diag_info_get(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,void * tx_info)1493 static 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
al_serdes_25g_rx_diag_5bit_signed_set(uint8_t packed_val,int8_t * ptr)1613 static 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
al_serdes_25g_rx_diag_info_get(struct al_serdes_grp_obj * obj,enum al_serdes_lane lane,void * rx_info)1626 static 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 /******************************************************************************/
al_serdes_25g_handle_init(void __iomem * serdes_regs_base,struct al_serdes_grp_obj * obj)1899 int 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