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 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 /******************************************************************************/ 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 /******************************************************************************/ 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 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 /******************************************************************************/ 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 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 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 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 /******************************************************************************/ 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. 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 /******************************************************************************/ 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