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