sesto_cfg_seq.c (311485B)
1 /* 2 * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file. 3 * 4 * Copyright 2007-2019 Broadcom Inc. All rights reserved. 5 * 6 */ 7 8 /* 9 * 10 * 11 * This program is the proprietary software of Broadcom Corporation 12 * and/or its licensors, and may only be used, duplicated, modified 13 * or distributed pursuant to the terms and conditions of a separate, 14 * written license agreement executed between you and Broadcom 15 * (an "Authorized License"). Except as set forth in an Authorized 16 * License, Broadcom grants no license (express or implied), right 17 * to use, or waiver of any kind with respect to the Software, and 18 * Broadcom expressly reserves all rights in and to the Software 19 * and all intellectual property rights therein. IF YOU HAVE 20 * NO AUTHORIZED LICENSE, THEN YOU HAVE NO RIGHT TO USE THIS SOFTWARE 21 * IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY BROADCOM AND DISCONTINUE 22 * ALL USE OF THE SOFTWARE. 23 * 24 * Except as expressly set forth in the Authorized License, 25 * 26 * 1. This program, including its structure, sequence and organization, 27 * constitutes the valuable trade secrets of Broadcom, and you shall use 28 * all reasonable efforts to protect the confidentiality thereof, 29 * and to use this information only in connection with your use of 30 * Broadcom integrated circuit products. 31 * 32 * 2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS 33 * PROVIDED "AS IS" AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, 34 * REPRESENTATIONS OR WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, 35 * OR OTHERWISE, WITH RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY 36 * DISCLAIMS ANY AND ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, 37 * NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, 38 * ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR 39 * CORRESPONDENCE TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING 40 * OUT OF USE OR PERFORMANCE OF THE SOFTWARE. 41 * 42 * 3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL 43 * BROADCOM OR ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, 44 * INCIDENTAL, SPECIAL, INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER 45 * ARISING OUT OF OR IN ANY WAY RELATING TO YOUR USE OF OR INABILITY 46 * TO USE THE SOFTWARE EVEN IF BROADCOM HAS BEEN ADVISED OF THE 47 * POSSIBILITY OF SUCH DAMAGES; OR (ii) ANY AMOUNT IN EXCESS OF 48 * THE AMOUNT ACTUALLY PAID FOR THE SOFTWARE ITSELF OR USD 1.00, 49 * WHICHEVER IS GREATER. THESE LIMITATIONS SHALL APPLY NOTWITHSTANDING 50 * ANY FAILURE OF ESSENTIAL PURPOSE OF ANY LIMITED REMEDY.$ 51 */ 52 53 #include <phymod/phymod.h> 54 #include <phymod/phymod_system.h> 55 #include <phymod/phymod_diagnostics.h> 56 #include "sesto_address_defines.h" 57 #include "sesto_reg_structs.h" 58 #include "sesto_cfg_seq.h" 59 #include "sesto_serdes/common/srds_api_enum.h" 60 #include "sesto_serdes/merlin_sesto_src/merlin_sesto_functions.h" 61 #include "sesto_serdes/falcon_furia_sesto_src/falcon_furia_sesto_functions.h" 62 #include <phymod/chip/sesto.h> 63 64 extern unsigned char sesto_falcon_ucode[]; 65 extern unsigned char sesto_merlin_ucode[]; 66 extern unsigned int sesto_falcon_ucode_len; 67 extern unsigned int sesto_merlin_ucode_len; 68 69 int sesto_get_chipid (const phymod_access_t *pa, uint32_t *chipid, uint32_t *rev) 70 { 71 SES_CTRL_CHIP_ID_TYPE_T chipid_lsb; 72 SES_CTRL_CHIP_REVISION_TYPE_T chipid_msb_rev; 73 int rv = PHYMOD_E_NONE; 74 75 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_CHIP_ID_ADR, chipid_lsb.data); 76 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_CHIP_REVISION_ADR, chipid_msb_rev.data); 77 78 *chipid = (chipid_lsb.data) | (chipid_msb_rev.fields.chip_id_19_16 << 16); 79 *rev = chipid_msb_rev.fields.chip_rev; 80 81 PHYMOD_DEBUG_VERBOSE(("CHIP ID: %x REv:%x\n", *chipid, *rev)); 82 83 ERR: 84 return rv; 85 } 86 87 /** Wait master message out 88 * This function is to ensure whether master has sent the previous message 89 * out successfully 90 * 91 * @param pa Pointer to phymod access structure 92 * @param exp_message Expected message specified by user 93 * @param poll_time Poll interval 94 * 95 * @return PHYMOD_E_NONE successful function execution 96 */ 97 int _sesto_wait_mst_msgout(const phymod_access_t *pa, 98 SESTO_MSGOUT_E exp_message, 99 int poll_time) 100 { 101 int retry_count = SESTO_FW_DLOAD_RETRY_CNT; 102 SESTO_MSGOUT_E msgout = 0; 103 SES_GEN_CNTRLS_MSGOUT_TYPE_T msgout_t; 104 int rv = PHYMOD_E_NONE; 105 106 do { 107 /* Read general control msg out Register */ 108 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MSGOUT_ADR, msgout_t.data); 109 msgout = (SESTO_MSGOUT_E) msgout_t.fields.msgout_val; 110 /* wait before reading again */ 111 if (poll_time != 0) { 112 /* sleep for specified useconds*/ 113 PHYMOD_USLEEP(poll_time); 114 } 115 retry_count --; 116 } while ((msgout != exp_message) && retry_count); 117 118 if (!retry_count) { 119 if (exp_message == MSGOUT_PRGRM_DONE) { 120 PHYMOD_DEBUG_VERBOSE(("MSG OUT:%x \n",msgout)); 121 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, (_PHYMOD_MSG("Fusing Firmware failed"))); 122 } else { 123 SESTO_RETURN_WITH_ERR(PHYMOD_E_INIT, (_PHYMOD_MSG("Firmware download failed"))); 124 } 125 } 126 127 ERR: 128 return rv; 129 } 130 131 int _sesto_fw_enable(const phymod_access_t *pa, uint16_t en_dis) 132 { 133 int rv = PHYMOD_E_NONE; 134 135 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, en_dis); 136 137 ERR: 138 return rv; 139 } 140 int sesto_micro_download(const phymod_access_t *pa, unsigned char *ucode, 141 uint32_t len, uint16_t master, uint16_t *chk_sum) 142 { 143 SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_TYPE_T spi_code_load; 144 SES_MICRO_BOOT_BOOT_POR_TYPE_T boot_por; 145 SES_GEN_CNTRLS_MSGIN_TYPE_T msg_in; 146 uint16_t num_bytes = 0, j = 0; 147 uint16_t num_words = 0; 148 uint16_t check_sum = 0, cnt = SESTO_FW_DLOAD_RETRY_CNT, data = 0; 149 int rv = PHYMOD_E_NONE; 150 151 PHYMOD_MEMSET(&spi_code_load, 0 , sizeof(SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_TYPE_T)); 152 153 /* Send boot address */ 154 SESTO_IF_ERR_RETURN( 155 _sesto_wait_mst_msgout(pa, MSGOUT_NEXT, 0)); 156 msg_in.data = 0; 157 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MSGIN_ADR, 158 msg_in.data); 159 SESTO_IF_ERR_RETURN( 160 _sesto_wait_mst_msgout(pa, MSGOUT_NEXT, 0)); 161 /* when code_broadcast_en is enable and slave_code_download_en is enale 162 * we need do msg_in and msg_our as MSGOUT_NEXT */ 163 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_ADR, spi_code_load.data); 164 if (spi_code_load.fields.code_broadcast_en && (!master)) { 165 msg_in.data = 0; 166 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MSGIN_ADR, 167 msg_in.data); 168 169 SESTO_IF_ERR_RETURN( 170 _sesto_wait_mst_msgout(pa, MSGOUT_NEXT, 0)); 171 } 172 173 /* Calculate the number of words */ 174 num_words = (len) / 2; 175 176 /* Update message in value field with word length */ 177 msg_in.fields.msgin_val = num_words; 178 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MSGIN_ADR, 179 msg_in.data); 180 num_bytes = len; 181 for (j = 0; j < num_bytes; j += 2) { 182 /* 183 SESTO_IF_ERR_RETURN 184 (_sesto_wait_mst_msgout(pa, MSGOUT_NEXT, 0)); 185 */ 186 data = (ucode[j + 1] << 8) | ucode[j]; 187 check_sum ^= ucode[j] ^ ucode[j + 1]; 188 189 /* Send next word */ 190 msg_in.fields.msgin_val = data; 191 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MSGIN_ADR, 192 msg_in.data); 193 } 194 do { 195 /* check download_done flags*/ 196 READ_SESTO_PMA_PMD_REG(pa, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 197 if (master) { 198 if (boot_por.fields.mst_dwld_done == 1) { 199 PHYMOD_DEBUG_VERBOSE(("Master Dload Done\n")); 200 break; 201 } 202 } else { 203 if (boot_por.fields.slv_dwld_done == 1) { 204 PHYMOD_DEBUG_VERBOSE(("Slave Dload Done\n")); 205 break; 206 } 207 } 208 } while (cnt --); 209 210 /* check checksum */ 211 check_sum = (check_sum == 0) ? 0x600D : check_sum; 212 if (master) { 213 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_MST_RUNNING_BYTE_CNT, mst_running_byte_cnt_val, data); 214 if (data != num_bytes) { 215 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL,(_PHYMOD_MSG("Master Dload fail:"))); 216 } 217 PHYMOD_DEBUG_VERBOSE(("Master Byte Cnt:%d\n", data)); 218 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_MST_RUNNING_CHKSUM, mst_running_chksum_val, data); 219 if (check_sum != data) { 220 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 221 (_PHYMOD_MSG("Master Dload chksum Fail"))); 222 } 223 PHYMOD_DEBUG_VERBOSE(("Master Chk sum:0x%x\n", data)); 224 *chk_sum = data; 225 } else { 226 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_SLV_RUNNING_BYTE_CNT, slv_running_byte_cnt_val, data); 227 if (data != num_bytes) { 228 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 229 (_PHYMOD_MSG("SLave Dload fail:"))); 230 } 231 PHYMOD_DEBUG_VERBOSE(("Slave Byte Cnt:%d\n", data)); 232 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_SLV_RUNNING_CHKSUM, slv_running_chksum_val, data); 233 if (check_sum != data) { 234 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 235 (_PHYMOD_MSG("Slave Dload chksum fail "))); 236 } 237 PHYMOD_DEBUG_VERBOSE(("Slave cksum Cnt:0x%x\n", data)); 238 *chk_sum = data; 239 } 240 241 ERR: 242 return rv; 243 } 244 245 int _sesto_firmware_download(const phymod_access_t *pm_acc , 246 unsigned char *sesto_master_ucode, unsigned int master_len, 247 unsigned char *sesto_slave_ucode, unsigned int slave_len) 248 { 249 uint16_t data1 = 0, retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 250 SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_TYPE_T spi_code_load; 251 SES_GEN_CNTRLS_GEN_CONTROL2_TYPE_T gen_ctrl2; 252 SES_MICRO_BOOT_BOOT_POR_TYPE_T boot_por; 253 uint16_t mst_check_sum = 0, slv_check_sum = 0; 254 int rv = PHYMOD_E_NONE; 255 256 PHYMOD_MEMSET(&spi_code_load, 0 , sizeof(SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_TYPE_T)); 257 PHYMOD_MEMSET(&gen_ctrl2, 0 , sizeof(SES_GEN_CNTRLS_GEN_CONTROL2_TYPE_T)); 258 PHYMOD_MEMSET(&boot_por, 0 , sizeof(SES_MICRO_BOOT_BOOT_POR_TYPE_T)); 259 260 /* Skip the mst_dwld_down, slv_dwld_done and chip reset check incase broadcast is enabled */ 261 /* Skip the firmware download 262 * mst_download, slv_dwld_done bits are set 263 */ 264 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_MICRO_SYNC_7, brdcst_en, data1); 265 if (!data1) { 266 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 267 if ((boot_por.fields.mst_dwld_done) && 268 (boot_por.fields.slv_dwld_done)) { 269 return SESTO_FW_ALREADY_DOWNLOADED; 270 } 271 272 /* Do chip hard reset and Resetting the Cores */ 273 SESTO_IF_ERR_RETURN( 274 _sesto_core_reset_set(pm_acc, phymodResetModeHard, phymodResetDirectionInOut)); 275 } 276 /* Put Master under Reset */ 277 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_rstb, 0); 278 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_ucp_rstb, 0); 279 280 /* Wait for any pending SPI download 281 * SPI download is not interrupted by Master Reset 282 * (this is a safety feature) so we need to wait its 283 * completion before starting the MDIO Download */ 284 do { 285 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_busy, data1); 286 retry_cnt--; 287 } while((data1 != 0) && (retry_cnt)); 288 if (retry_cnt == 0) { 289 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 290 (_PHYMOD_MSG("ERR:SERBOOT BUSY BIT SET"))); 291 return PHYMOD_E_FAIL; 292 } 293 294 /* Sesto always supports serial mode if Dload 295 * Master followed by slave 296 * Configure master_code_download_en, slave_code_download_en 297 * and broadcast enable */ 298 spi_code_load.fields.code_broadcast_en = 0; 299 spi_code_load.fields.master_code_download_en = 1; 300 spi_code_load.fields.slave_code_download_en = 1; 301 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_ADR, 302 spi_code_load.data); 303 304 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_ADR, data1); 305 spi_code_load.data = data1; 306 if (spi_code_load.fields.code_broadcast_en != 0 && spi_code_load.fields.master_code_download_en != 1 307 && spi_code_load.fields.slave_code_download_en != 1) { 308 return PHYMOD_E_INTERNAL; 309 } 310 /* Select SPI Speed*/ 311 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL3, 312 ucspi_slow, 1); 313 314 /* Check the not downloading branch of the flow digram 315 * before writing to serboot. 316 * wait_mst_msgout(chip_cfg, die, MSGOUT_NOT_DWNLD, 1, 0);*/ 317 318 /* Read / Write boot_por 319 * write to mst_dwld_done and slv_dwld_done. 320 * write to spi_port_used 321 * write to serboot */ 322 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 323 324 /* Force Master New Download */ 325 boot_por.fields.mst_dwld_done = 0; 326 /* Force Slave New Download */ 327 boot_por.fields.slv_dwld_done = 0; 328 boot_por.fields.serboot = 1; 329 boot_por.fields.spi_port_used = 0; 330 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, 331 boot_por.data); 332 333 /* RELEASE Master under Reset */ 334 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_ucp_rstb, 1); 335 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_rstb, 1); 336 337 /* MDI/I2C Download */ 338 /* Waiting for serboot_busy */ 339 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 340 do { 341 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_busy, data1); 342 retry_cnt--; 343 } while ((data1 == 0) && (retry_cnt)); 344 if (retry_cnt == 0) { 345 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 346 (_PHYMOD_MSG("ERR:SERBOOT BUSY BIT SET"))); 347 return PHYMOD_E_FAIL; 348 } 349 /* Start download sequence */ 350 /* master boot*/ 351 SESTO_IF_ERR_RETURN( 352 sesto_micro_download(pm_acc, sesto_master_ucode, 353 master_len, 1, &mst_check_sum)); 354 355 SESTO_IF_ERR_RETURN( 356 sesto_micro_download(pm_acc, sesto_slave_ucode, 357 slave_len, 0, &slv_check_sum)); 358 SESTO_IF_ERR_RETURN( 359 _sesto_wait_mst_msgout(pm_acc, MSGOUT_DWNLD_DONE, 0)); 360 /*uint16_t checksum = 0; 361 SESTO_IF_ERR_RETURN( 362 _sesto_wait_mst_msgout(pm_acc, MSGOUT_DWNLD_DONE, 0)); 363 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_MST_RUNNING_CHKSUM, mst_running_chksum_val, checksum); 364 PHYMOD_DEBUG_VERBOSE(("Master CheckSum:%x\n",checksum)); 365 366 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_SLV_RUNNING_CHKSUM, slv_running_chksum_val, checksum); 367 PHYMOD_DEBUG_VERBOSE(("Slave CheckSum:%x\n",checksum)); 368 }*/ 369 /* Check serboot_busy and serboot_done_once*/ 370 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_busy, data1); 371 if (data1 != 0) { 372 PHYMOD_DEBUG_ERROR(("WARN:SERBOOT BUSY HAS UNEXPECTED VALUE\n")); 373 } 374 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_done_once, data1); 375 if (data1 != 1) { 376 PHYMOD_DEBUG_ERROR(("WARN:SERBOOT DONE ONCE HAS UNEXPECTED VALUE\n")); 377 } 378 379 /* check download_done flags again */ 380 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 381 if (boot_por.fields.mst_dwld_done != 1 || boot_por.fields.slv_dwld_done != 1) { 382 PHYMOD_DEBUG_ERROR(("WARN:Download Done got cleared\n")); 383 } 384 385 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 386 do { 387 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data1); 388 retry_cnt --; 389 } while ((data1 != 0) && (retry_cnt)); 390 if (retry_cnt == 0) { 391 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 392 (_PHYMOD_MSG("Fireware download failed, micro controller is busy.."))); 393 } 394 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_FIRMWARE_VERSION_ADR, 395 data1); 396 PHYMOD_DEBUG_VERBOSE(("FW Version:0x%x\n", data1)); 397 398 ERR: 399 return rv; 400 } 401 int _sesto_eeprom_firmware_download(const phymod_access_t *pm_acc , 402 unsigned char *sesto_ucode, unsigned int ucode_len, uint16_t master) 403 { 404 uint16_t data1 = 0, retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 405 uint16_t eeprom_num_of_pages = 0; 406 SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_TYPE_T spi_code_load; 407 SES_GEN_CNTRLS_GEN_CONTROL2_TYPE_T gen_ctrl2; 408 SES_MICRO_BOOT_BOOT_POR_TYPE_T boot_por; 409 uint16_t check_sum = 0; 410 int rv = PHYMOD_E_NONE; 411 412 PHYMOD_MEMSET(&spi_code_load, 0 , sizeof(SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_TYPE_T)); 413 PHYMOD_MEMSET(&gen_ctrl2, 0 , sizeof(SES_GEN_CNTRLS_GEN_CONTROL2_TYPE_T)); 414 PHYMOD_MEMSET(&boot_por, 0 , sizeof(SES_MICRO_BOOT_BOOT_POR_TYPE_T)); 415 416 /* Do chip hard reset and Resetting the Cores */ 417 SESTO_IF_ERR_RETURN( 418 _sesto_core_reset_set(pm_acc, phymodResetModeHard, phymodResetDirectionInOut)); 419 /* Put Master under Reset */ 420 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_rstb, 0); 421 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_ucp_rstb, 0); 422 423 /* Wait for any pending SPI download 424 * SPI download is not interrupted by Master Reset 425 * (this is a safety feature) so we need to wait its 426 * completion before starting the MDIO Download */ 427 428 do { 429 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_busy, data1); 430 retry_cnt--; 431 } while((data1 != 0) && (retry_cnt)); 432 if (retry_cnt == 0) { 433 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 434 (_PHYMOD_MSG("ERR:SERBOOT BUSY BIT SET"))); 435 } 436 437 /* Sesto always supports serial mode if Dload 438 * Master followed by slave 439 * Configure master_code_download_en, slave_code_download_en 440 * and broadcast enable */ 441 spi_code_load.fields.code_broadcast_en = 1; 442 spi_code_load.fields.master_code_download_en = 1; 443 spi_code_load.fields.slave_code_download_en = !master; 444 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_ADR, spi_code_load.data); 445 446 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_SPI_CODE_LOAD_EN_ADR, spi_code_load.data); 447 if (spi_code_load.fields.code_broadcast_en != 1) { 448 return PHYMOD_E_INTERNAL; 449 } 450 451 /* Configure GPREG for programming eeprom */ 452 eeprom_num_of_pages = (uint16_t)(ucode_len/SESTO_M0_EEPROM_PAGE_SIZE); 453 if (eeprom_num_of_pages > 0x1FF) { 454 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 455 (_PHYMOD_MSG("ERR:No of EEPROM pages more than Code ROM, Fusing does not support"))); 456 } 457 eeprom_num_of_pages = 0x1FF; 458 459 /* Start Page of EEPROM*/ 460 /* For master start page is "0" and slave start page is "0x200" in eeprom */ 461 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_GPREG14_ADR, (master ? 0 : 0x200)); 462 /* No of eeprom pages */ 463 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_GPREG15_ADR, eeprom_num_of_pages); 464 /* Select SPI Speed*/ 465 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL3, ucspi_slow, 1); 466 /* Reset spi */ 467 /* Assert Reset */ 468 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2_ADR, gen_ctrl2.data); 469 gen_ctrl2.fields.spi_rstb = 0; 470 gen_ctrl2.fields.spi2x_rstb = 0; 471 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2_ADR, gen_ctrl2.data); 472 473 /* Deassert Reset */ 474 gen_ctrl2.fields.spi_rstb = 1; 475 gen_ctrl2.fields.spi2x_rstb = 1; 476 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2_ADR, gen_ctrl2.data); 477 478 /* Check the not downloading branch of the flow digram 479 * before writing to serboot. 480 * wait_mst_msgout(chip_cfg, die, MSGOUT_NOT_DWNLD, 1, 0);*/ 481 /* Read / Write boot_por 482 * write to mst_dwld_done and slv_dwld_done. 483 * write to spi_port_used 484 * write to serboot */ 485 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 486 487 /* Force Master New Download */ 488 boot_por.fields.mst_dwld_done = 0; 489 /* Force Slave New Download */ 490 boot_por.fields.slv_dwld_done = 0; 491 boot_por.fields.serboot = 1; 492 boot_por.fields.spi_port_used = 0; 493 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, 494 boot_por.data); 495 496 /* RELEASE Master under Reset */ 497 498 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_ucp_rstb, 1); 499 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2, m0_mstr_rstb, 1); 500 501 /* MDI/I2C Download */ 502 /* Waiting for serboot_busy */ 503 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 504 do { 505 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_busy, data1); 506 retry_cnt--; 507 } while ((data1 == 0) && (retry_cnt)); 508 if (retry_cnt == 0) { 509 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 510 (_PHYMOD_MSG("ERR:SERBOOT BUSY BIT SET"))); 511 return PHYMOD_E_FAIL; 512 } 513 /* Start download sequence */ 514 /* master boot*/ 515 SESTO_IF_ERR_RETURN( 516 sesto_micro_download(pm_acc, sesto_ucode, 517 ucode_len, master, &check_sum)); 518 SESTO_IF_ERR_RETURN( 519 _sesto_wait_mst_msgout(pm_acc, MSGOUT_DWNLD_DONE, 0)); 520 521 /* Check serboot_busy and serboot_done_once*/ 522 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_busy, data1); 523 if (data1 != 0) { 524 PHYMOD_DEBUG_ERROR(("WARN:SERBOOT BUSY HAS UNEXPECTED VALUE\n")); 525 } 526 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_BOOT, serboot_done_once, data1); 527 if (data1 != 1) { 528 PHYMOD_DEBUG_ERROR(("WARN:SERBOOT DONE ONCE HAS UNEXPECTED VALUE\n")); 529 } 530 531 /* check download_done flags again */ 532 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 533 if (boot_por.fields.mst_dwld_done != 1 || boot_por.fields.slv_dwld_done != 1) { 534 PHYMOD_DEBUG_ERROR(("WARN:Download Done got cleared\n")); 535 } 536 /* Wait for Program EEPROM*/ 537 SESTO_IF_ERR_RETURN( 538 _sesto_wait_mst_msgout(pm_acc, MSGOUT_PRGRM_DONE,0)); 539 /* Assert SPI Reset*/ 540 gen_ctrl2.fields.spi_rstb = 0; 541 gen_ctrl2.fields.spi2x_rstb = 0; 542 WRITE_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_GEN_CONTROL2_ADR, gen_ctrl2.data); 543 544 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 545 do { 546 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data1); 547 retry_cnt --; 548 } while ((data1 != 0) && (retry_cnt)); 549 if (retry_cnt == 0) { 550 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 551 (_PHYMOD_MSG("Fireware download failed, micro controller is busy.."))); 552 } 553 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_FIRMWARE_VERSION_ADR, 554 data1); 555 PHYMOD_DEBUG_VERBOSE(("FW Version:0x%x\n", data1)); 556 557 ERR: 558 return rv; 559 } 560 561 int _sesto_core_init(const phymod_core_access_t* core, 562 const phymod_core_init_config_t* init_config) 563 { 564 int ret_val = 0; 565 uint16_t ip = 0; 566 uint16_t lane = 0, data = 0; 567 uint16_t max_lane = 0; 568 uint32_t rev = 0, chip_id = 0; 569 phymod_access_t pa; 570 int rv = PHYMOD_E_NONE; 571 uint16_t retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 572 const phymod_access_t *pm_acc = &core->access; 573 DP_FMON0_MAIN_CONTROL_TYPE_T fmon_main_ctrl; 574 DP_MMON0_MAIN_CONTROL_TYPE_T mmon_main_ctrl; 575 SES_MICRO_BOOT_BOOT_POR_TYPE_T boot_por; 576 uint32_t new_fm_version = 0; 577 phymod_core_firmware_info_t fw_info; 578 579 PHYMOD_MEMSET(&boot_por, 0 , sizeof(SES_MICRO_BOOT_BOOT_POR_TYPE_T)); 580 PHYMOD_MEMSET(&fmon_main_ctrl, 0 , sizeof(DP_FMON0_MAIN_CONTROL_TYPE_T)); 581 PHYMOD_MEMSET(&mmon_main_ctrl, 0 , sizeof(DP_MMON0_MAIN_CONTROL_TYPE_T)); 582 PHYMOD_MEMSET(&fw_info, 0, sizeof(phymod_core_firmware_info_t)); 583 584 SESTO_IF_ERR_RETURN( 585 sesto_core_firmware_info_get(core, &fw_info)); 586 new_fm_version = sesto_falcon_ucode[sesto_falcon_ucode_len - 3]; 587 588 switch(init_config->firmware_load_method) 589 { 590 case phymodFirmwareLoadMethodInternal: 591 PHYMOD_DEBUG_VERBOSE(( 592 "Starting Firmware download through MDIO, it takes few seconds...\n")); 593 594 /* In case of FW Download is only for second die i.e for odd address of the die 595 * To get the micro out of reset on even die(previous die); for MDIO only 596 * Applicable for only duel die chips; 597 * SESTO_CHIP_ID_82790 is 82790 is single die ingnore the micro out of reset 598 */ 599 SESTO_IF_ERR_RETURN(sesto_get_chipid(pm_acc, &chip_id, &rev)); 600 if (((pm_acc->addr & 0x1) == 0x1) && (chip_id != SESTO_CHIP_ID_82790)) { 601 PHYMOD_MEMCPY(&pa, pm_acc, sizeof(phymod_access_t)); 602 /* modify the mdio address to be even */ 603 pa.addr &= ~(0x1); 604 /* Set the 11th and 9th bit of even die to get the micro out of reset */ 605 SESTO_CHIP_FIELD_WRITE(&pa, SES_PAD_CTRL_EXT_UC_RSTB_OUT_CONTROL, ext_uc_rstb_out_out_frcval, 1); 606 SESTO_CHIP_FIELD_WRITE(&pa, SES_PAD_CTRL_EXT_UC_RSTB_OUT_CONTROL, ext_uc_rstb_out_ibof, 1); 607 } 608 609 if(PHYMOD_CORE_INIT_F_EXECUTE_PASS1_GET(init_config)) { 610 /*Dowdload firmware unicast when rev is 0xA0 that does not support broadcast*/ 611 if(rev == 0xA0){ 612 /* FW force method is force or Auto with different FW version then do chip reset */ 613 if (PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_GET(init_config) || 614 (PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_GET(init_config) && (new_fm_version != (fw_info.fw_version & 0xFF)))) { 615 /* Do chip hard reset and Resetting the Cores */ 616 SESTO_IF_ERR_RETURN( 617 _sesto_core_reset_set(pm_acc, phymodResetModeHard, phymodResetDirectionInOut)); 618 } 619 /* Download FW for one core in MDIO bus, This is called for all core if no broadcast */ 620 ret_val = _sesto_firmware_download(pm_acc, 621 sesto_falcon_ucode, sesto_falcon_ucode_len, 622 sesto_merlin_ucode, sesto_merlin_ucode_len); 623 if ((ret_val != PHYMOD_E_NONE) && (ret_val != SESTO_FW_ALREADY_DOWNLOADED)) { 624 SESTO_RETURN_WITH_ERR 625 (ret_val, (_PHYMOD_MSG("firmware download failed"))); 626 } else { 627 PHYMOD_DEBUG_VERBOSE(("Firmware download through MDIO success\n")); 628 } 629 } 630 } 631 632 /* Broadcast way of FW download sequence 633 * 1. Reset core for all cores 634 * 2. Enable the broadcast for all the cores 635 * 3. Download FW for one core in MDIO bus 636 * 4. Disable the broadcast and Verify the FW on all cores 637 */ 638 639 if (PHYMOD_CORE_INIT_F_RESET_CORE_FOR_FW_LOAD_GET(init_config)) { 640 /* FW force method is force or Auto with different FW version then do chip reset */ 641 if (PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_GET(init_config) || 642 (PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_GET(init_config) && (new_fm_version != (fw_info.fw_version & 0xFF)))) { 643 /* Do chip hard reset and Resetting the Cores */ 644 SESTO_IF_ERR_RETURN( 645 _sesto_core_reset_set(pm_acc, phymodResetModeHard, phymodResetDirectionInOut)); 646 } 647 } else if (PHYMOD_CORE_INIT_F_UNTIL_FW_LOAD_GET(init_config)) { 648 /* FW force method is force or Auto with different FW version then do enable broadcast */ 649 if (PHYMOD_CORE_INIT_F_FW_FORCE_DOWNLOAD_GET(init_config) || 650 (PHYMOD_CORE_INIT_F_FW_AUTO_DOWNLOAD_GET(init_config) && (new_fm_version != (fw_info.fw_version & 0xFF)))) { 651 /* Enable broadcast */ 652 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_MICRO_SYNC_7, brdcst_en, 1); 653 } 654 } else if (PHYMOD_CORE_INIT_F_EXECUTE_FW_LOAD_GET(init_config)) { 655 /* Download FW for one core in MDIO bus, This is called for all core if no broadcast */ 656 ret_val = _sesto_firmware_download(pm_acc, 657 sesto_falcon_ucode, sesto_falcon_ucode_len, 658 sesto_merlin_ucode, sesto_merlin_ucode_len); 659 if ((ret_val != PHYMOD_E_NONE) && (ret_val != SESTO_FW_ALREADY_DOWNLOADED)) { 660 SESTO_RETURN_WITH_ERR 661 (ret_val, (_PHYMOD_MSG("firmware download failed"))); 662 } else { 663 PHYMOD_DEBUG_VERBOSE(("Firmware download through MDIO success\n")); 664 } 665 } else if (PHYMOD_CORE_INIT_F_RESUME_AFTER_FW_LOAD_GET(init_config)) { 666 /* Disable broadcast */ 667 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_MICRO_SYNC_7, brdcst_en, 0); 668 /* check download_done flags again */ 669 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 670 if (boot_por.fields.mst_dwld_done != 1 || boot_por.fields.slv_dwld_done != 1) { 671 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 672 (_PHYMOD_MSG("ERR:Firmware Download Done got cleared"))); 673 } 674 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_FIRMWARE_VERSION_ADR, data); 675 if (data == 0x1) { 676 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 677 (_PHYMOD_MSG("ERR:Invalid Firmware version Downloaded"))); 678 } 679 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_MST_RUNNING_CHKSUM, mst_running_chksum_val, data); 680 if (0x600D != data) { 681 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 682 (_PHYMOD_MSG("Master Dload chksum Fail"))); 683 } 684 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_SLV_RUNNING_CHKSUM, slv_running_chksum_val, data); 685 if (0x600D != data) { 686 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 687 (_PHYMOD_MSG("Slave Dload chksum Fail"))); 688 } 689 } 690 break; 691 case phymodFirmwareLoadMethodExternal: 692 return PHYMOD_E_UNAVAIL; 693 break; 694 case phymodFirmwareLoadMethodNone: 695 /* Expected to download firmware from Flashed EEPROM */ 696 /* Firmware download works only when serboot pin is set on the chip */ 697 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 698 if (boot_por.fields.serboot) { 699 /* check download_done flags again */ 700 READ_SESTO_PMA_PMD_REG(pm_acc, SES_MICRO_BOOT_BOOT_POR_ADR, boot_por.data); 701 if (boot_por.fields.mst_dwld_done != 1 || boot_por.fields.slv_dwld_done != 1) { 702 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 703 (_PHYMOD_MSG("ERR:Firmware Download Done got cleared"))); 704 } 705 READ_SESTO_PMA_PMD_REG(pm_acc, SES_GEN_CNTRLS_FIRMWARE_VERSION_ADR, data); 706 if (data == 0x1) { 707 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 708 (_PHYMOD_MSG("ERR:Invalid Firmware version Downloaded"))); 709 } 710 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_MST_RUNNING_CHKSUM, mst_running_chksum_val, data); 711 if (0x600D != data) { 712 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 713 (_PHYMOD_MSG("Master Dload chksum Fail"))); 714 } 715 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_SLV_RUNNING_CHKSUM, slv_running_chksum_val, data); 716 if (0x600D != data) { 717 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 718 (_PHYMOD_MSG("Slave Dload chksum Fail"))); 719 } 720 /* This is required When FW is already downloaded(Phy-1956), It will not affect EEPROM 721 * Download*/ 722 ret_val = SESTO_FW_ALREADY_DOWNLOADED; 723 724 } else { 725 PHYMOD_DEBUG_ERROR(("WARN:SERBOOT PIN VALUE IS EXPECTED\n")); 726 } 727 break; 728 case phymodFirmwareLoadMethodProgEEPROM: 729 /* EEPROM fusing starts with master fallowed by slave ucode b/w hardreset of chip */ 730 /* Master f/w download using mdio and then fusing to eeprom */ 731 PHYMOD_DEBUG_VERBOSE(( 732 "Starting Firmware download through EEPROM, it takes few seconds...\n")); 733 /* Slave f/w download using mdio and then fusing to eeprom */ 734 ret_val = _sesto_eeprom_firmware_download(pm_acc, 735 sesto_merlin_ucode, sesto_merlin_ucode_len, 0); 736 if ((ret_val != PHYMOD_E_NONE) && (ret_val != SESTO_FW_ALREADY_DOWNLOADED)) { 737 SESTO_RETURN_WITH_ERR 738 (ret_val, 739 (_PHYMOD_MSG("Slave firmware download failed"))); 740 } else { 741 PHYMOD_DEBUG_VERBOSE(("Slave Firmware download through EEPROM success\n")); 742 } 743 744 ret_val = _sesto_eeprom_firmware_download(pm_acc, 745 sesto_falcon_ucode, sesto_falcon_ucode_len, 1); 746 if ((ret_val != PHYMOD_E_NONE) && (ret_val != SESTO_FW_ALREADY_DOWNLOADED)) { 747 SESTO_RETURN_WITH_ERR 748 (ret_val, 749 (_PHYMOD_MSG("Master firmware download failed"))); 750 } else { 751 PHYMOD_DEBUG_VERBOSE(("Master Firmware download through EEPROM success\n")); 752 } 753 break; 754 default: 755 SESTO_RETURN_WITH_ERR 756 (PHYMOD_E_CONFIG, 757 (_PHYMOD_MSG("illegal fw load method"))); 758 } 759 760 /* Disable PCS moniter at core_init as deafult is enable */ 761 for (ip = SESTO_MERLIN_CORE ; ip <= SESTO_FALCON_CORE ;ip++) { 762 max_lane = (ip == SESTO_FALCON_CORE) ? SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 763 for (lane = 0; lane < max_lane; lane ++) { 764 if (ip == SESTO_FALCON_CORE) { 765 READ_SESTO_PMA_PMD_REG(pm_acc, (DP_FMON0_MAIN_CONTROL_ADR + lane), fmon_main_ctrl.data); 766 fmon_main_ctrl.fields.fmon0_main_ctrl &= ~(0x1); 767 WRITE_SESTO_PMA_PMD_REG(pm_acc, (DP_FMON0_MAIN_CONTROL_ADR + lane), fmon_main_ctrl.data); 768 PHYMOD_DEBUG_VERBOSE(("Falcon Link monitor for Lane:%d Data:0x%x\n", 769 lane, fmon_main_ctrl.data)); 770 } else { 771 READ_SESTO_PMA_PMD_REG(pm_acc, (DP_MMON0_MAIN_CONTROL_ADR + lane), mmon_main_ctrl.data); 772 mmon_main_ctrl.fields.mmon0_main_ctrl &= ~(0x1); 773 WRITE_SESTO_PMA_PMD_REG(pm_acc, (DP_MMON0_MAIN_CONTROL_ADR + lane), mmon_main_ctrl.data); 774 PHYMOD_DEBUG_VERBOSE(("Merlin Link monitor for Lane:%d Data:0x%x\n", 775 lane, mmon_main_ctrl.data)); 776 } 777 } 778 } 779 /* This is WAR for chip limitation: Disable the AN during init 780 as we are not supposed to call interface set while AN is enabled */ 781 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_GPREG11, an_enable, data); 782 if (data) { 783 SESTO_CHIP_FIELD_WRITE(pm_acc, SES_GEN_CNTRLS_GPREG11, an_enable, 0x0); 784 785 /* Enable FW After configuring mode */ 786 SESTO_IF_ERR_RETURN( 787 _sesto_fw_enable(pm_acc, SESTO_ENABLE)); 788 do { 789 SESTO_CHIP_FIELD_READ(pm_acc, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data); 790 791 PHYMOD_DEBUG_VERBOSE(("FW Clear:%d\n",data)); 792 retry_cnt--; 793 } while((data != 0) && (retry_cnt)); 794 if (retry_cnt == 0) { 795 PHYMOD_RETURN_WITH_ERR(PHYMOD_E_INIT, 796 (_PHYMOD_MSG("WARN:: FW Enable not cleared\n"))); 797 } 798 } 799 800 ERR: 801 return rv; 802 } 803 804 int _sesto_set_slice_reg (const phymod_access_t* pm_acc, SESTO_SLICE_CAST_TYPE cast_type, uint16_t ip, uint16_t dev_type, 805 uint16_t mcast_val, uint16_t lane) 806 { 807 DEV1_SLICE_SLICE_TYPE_T slice_reg; 808 int rv = PHYMOD_E_NONE; 809 810 PHYMOD_MEMSET(&slice_reg, 0 , sizeof(DEV1_SLICE_SLICE_TYPE_T)); 811 812 if (dev_type == SESTO_DEV_PMA_PMD) { 813 READ_SESTO_PMA_PMD_REG(pm_acc, DEV1_SLICE_SLICE_ADR, slice_reg.data); 814 } else { 815 READ_SESTO_AN_REG(pm_acc, DEV7_SLICE_SLICE_ADR, slice_reg.data); 816 } 817 slice_reg.fields.ip = ip; 818 slice_reg.fields.lane = lane; 819 slice_reg.fields.dev = dev_type; 820 if (cast_type == SESTO_SLICE_UNICAST) { 821 slice_reg.fields.cast = 0; 822 } else if (cast_type == SESTO_SLICE_MULTICAST) { 823 slice_reg.fields.cast = mcast_val; 824 } else { 825 slice_reg.fields.cast = 8; 826 } 827 if (dev_type == SESTO_DEV_PMA_PMD) { 828 WRITE_SESTO_PMA_PMD_REG(pm_acc, DEV1_SLICE_SLICE_ADR, slice_reg.data); 829 } else { 830 WRITE_SESTO_AN_REG(pm_acc, DEV7_SLICE_SLICE_ADR, slice_reg.data); 831 } 832 833 ERR: 834 return rv; 835 } 836 837 void _sesto_lane_cast_get(const phymod_phy_access_t *phy, SESTO_CORE_TYPE ip, 838 uint16_t *cast_type, uint16_t *mcast_val) 839 { 840 const phymod_access_t *pa = &phy->access; 841 842 switch (pa->lane_mask) { 843 case 3: 844 *cast_type = SESTO_SLICE_MULTICAST; 845 *mcast_val = 1; 846 break; 847 case 0xc: 848 *cast_type = SESTO_SLICE_MULTICAST; 849 *mcast_val = 2; 850 break; 851 case 0x30: 852 if (ip == SESTO_MERLIN_CORE) { 853 *cast_type = SESTO_SLICE_MULTICAST; 854 *mcast_val = 3; 855 } else { 856 *cast_type = SESTO_CAST_INVALID; 857 } 858 break; 859 case 0xc0: 860 if (ip == SESTO_MERLIN_CORE) { 861 *cast_type = SESTO_SLICE_MULTICAST; 862 *mcast_val = 4; 863 } else { 864 *cast_type = SESTO_CAST_INVALID; 865 } 866 break; 867 case 0x300: 868 if (ip == SESTO_MERLIN_CORE) { 869 *cast_type = SESTO_SLICE_MULTICAST; 870 *mcast_val = 5; 871 } else { 872 *cast_type = SESTO_CAST_INVALID; 873 } 874 break; 875 case 0xf: 876 if (ip == SESTO_MERLIN_CORE) { 877 *cast_type = SESTO_SLICE_MULTICAST; 878 *mcast_val = 6; 879 } else { 880 *cast_type = SESTO_SLICE_BROADCAST; 881 } 882 break; 883 case 0xf0: 884 if (ip == SESTO_MERLIN_CORE) { 885 *cast_type = SESTO_SLICE_MULTICAST; 886 *mcast_val = 7; 887 } else { 888 *cast_type = SESTO_CAST_INVALID; 889 } 890 break; 891 case 0x3ff: 892 if (ip == SESTO_MERLIN_CORE) { 893 *cast_type =SESTO_SLICE_BROADCAST; 894 } else { 895 *cast_type = SESTO_CAST_INVALID; 896 } 897 break; 898 default: 899 *cast_type = SESTO_SLICE_UNICAST; 900 break; 901 } 902 } 903 904 int _sesto_rx_pmd_lock_get(const phymod_phy_access_t* phy, uint32_t* rx_pmd_locked) 905 { 906 phymod_phy_inf_config_t config; 907 uint16_t ip = 0; 908 uint16_t lane = 0; 909 uint16_t temp = 0; 910 uint16_t lane_mask = 0, max_lane = 0; 911 const phymod_access_t *pa = &phy->access; 912 int rv = PHYMOD_E_NONE; 913 914 if (rx_pmd_locked) { 915 *rx_pmd_locked = 0xffff; 916 } else { 917 return PHYMOD_E_PARAM; 918 } 919 920 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 921 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 922 SESTO_IF_ERR_RETURN( 923 _sesto_phy_interface_config_get(phy, 0, &config)); 924 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 925 SESTO_GET_IP(phy, config, ip); 926 927 max_lane = (ip == SESTO_FALCON_CORE) ? 928 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 929 930 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 931 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 932 933 for (lane = 0; lane < max_lane; lane ++) { 934 if (lane_mask & (1 << lane)) { 935 SESTO_IF_ERR_RETURN( 936 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 937 ip, SESTO_DEV_PMA_PMD, 0, lane)); 938 if (ip == SESTO_FALCON_CORE) { 939 SESTO_CHIP_FIELD_READ(pa, F25G_TLB_RX_PMD_RX_LOCK_STATUS, pmd_rx_lock, temp); 940 *rx_pmd_locked &= temp; 941 } else { 942 SESTO_CHIP_FIELD_READ(pa, M10G_TLB_RX_PMD_RX_LOCK_STATUS, pmd_rx_lock, temp); 943 *rx_pmd_locked &= temp; 944 } 945 } 946 } 947 948 ERR: 949 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 950 PHYMOD_FREE(config.device_aux_modes); 951 952 return rv; 953 } 954 955 int sesto_is_lane_mask_set(const phymod_phy_access_t *phy, uint16_t prt, 956 const phymod_phy_inf_config_t *config) 957 { 958 phymod_phy_inf_config_t cfg; 959 uint16_t core = 0; 960 uint32_t lane_mask = 0; 961 SESTO_DEVICE_AUX_MODE_T *aux; 962 963 lane_mask = phy->access.lane_mask; 964 PHYMOD_MEMCPY(&cfg, config, sizeof(phymod_phy_inf_config_t)); 965 aux = (SESTO_DEVICE_AUX_MODE_T*)config->device_aux_modes; 966 SESTO_GET_IP(phy, cfg, core) ; 967 PHYMOD_DEBUG_VERBOSE(("%s :: core:%d port:%d\n", __func__, core, prt)); 968 if (core == SESTO_MERLIN_CORE) { 969 if (cfg.data_rate == SESTO_SPD_40G || cfg.data_rate == SESTO_SPD_42G) { 970 if (prt == 0) { 971 if (aux->pass_thru) { 972 if (aux->BCM84793_capablity) { 973 return ((lane_mask & 0xf) == 0xF) ? 1 : 0 ; 974 } else { 975 return ((lane_mask & 0x33) == 0x33) ? 1 : 0 ; 976 } 977 } else { 978 return ((lane_mask & 0xF) == 0xF) ? 1 : 0; 979 } 980 } else { 981 if (aux->pass_thru) { 982 return 0; 983 } else { 984 return ((lane_mask & 0xF0) == 0xf0) ? 1 : 0; 985 } 986 } 987 } 988 if (cfg.data_rate == SESTO_SPD_20G || cfg.data_rate == SESTO_SPD_21G) { 989 /* For 20G PT and MUX we are using same lane MAP*/ 990 if (prt == 0) { 991 return ((lane_mask & 0x3) == 0x3) ? 1 :0; 992 } else { 993 return ((lane_mask & 0x30) == 0x30) ? 1 :0; 994 } 995 } 996 if (cfg.data_rate == SESTO_SPD_1G || cfg.data_rate == SESTO_SPD_10G || cfg.data_rate == SESTO_SPD_11G) { 997 /* For 10G PT and MUX we are using same lane MAP*/ 998 if (prt == 0) { 999 return (lane_mask & 0x1) ? 1 :0; 1000 } else if (prt == 1) { 1001 return (lane_mask & 0x2) ? 1 :0; 1002 } else if (prt == 2) { 1003 if (aux->BCM84793_capablity) { 1004 return (lane_mask & 0x4) ? 1 :0; 1005 } else { 1006 return (lane_mask & 0x10) ? 1 :0; 1007 } 1008 } else if (prt == 3) { 1009 if (aux->BCM84793_capablity) { 1010 return (lane_mask & 0x8) ? 1 :0; 1011 } else { 1012 return (lane_mask & 0x20) ? 1 :0; 1013 } 1014 } 1015 } 1016 } else { 1017 if (cfg.data_rate == SESTO_SPD_40G || cfg.data_rate == SESTO_SPD_42G) { 1018 if (prt == 0) { 1019 if (aux->pass_thru) { 1020 return ((lane_mask & 0xf) == 0xF) ? 1 : 0 ; 1021 } else { 1022 return ((lane_mask & 0x3) == 0x3) ? 1 : 0; 1023 } 1024 } else { 1025 if (aux->pass_thru) { 1026 return 0; 1027 } else { 1028 return ((lane_mask & 0xc) == 0xc) ? 1 : 0; 1029 } 1030 } 1031 } 1032 if (cfg.data_rate == SESTO_SPD_20G || cfg.data_rate == SESTO_SPD_21G) { 1033 if (prt == 0) { 1034 if (aux->pass_thru) { 1035 return ((lane_mask & 0x3) == 0x3) ? 1 :0; 1036 } else { 1037 return (lane_mask & 0x1) ? 1 :0; 1038 } 1039 } else { 1040 if (aux->pass_thru) { 1041 return ((lane_mask & 0xc) == 0xc) ? 1 :0; 1042 } else { 1043 return (lane_mask & 0x4) ? 1 :0; 1044 } 1045 } 1046 } 1047 if (cfg.data_rate == SESTO_SPD_1G || cfg.data_rate == SESTO_SPD_10G || cfg.data_rate == SESTO_SPD_11G) { 1048 /* For 10G PT and MUX we are using same lane MAP*/ 1049 if (prt == 0) { 1050 return (lane_mask & 0x1) ? 1 :0; 1051 } else if (prt == 1) { 1052 return (lane_mask & 0x2) ? 1 :0; 1053 } else if (prt == 2) { 1054 return (lane_mask & 0x4) ? 1 :0; 1055 } else if (prt == 3) { 1056 return (lane_mask & 0x8) ? 1 :0; 1057 } 1058 } 1059 } 1060 1061 return 0; 1062 } 1063 /** Configure Dut Mode Register 1064 */ 1065 int _sesto_config_dut_mode_reg(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t* config) 1066 { 1067 uint16_t no_of_ports = 0, port_idx = 0; 1068 SESTO_DEVICE_AUX_MODE_T *aux_mode; 1069 DP_SESTO_MODE_CTRL0_TYPE_T mode_ctrl0; 1070 uint16_t core = 0; 1071 uint16_t is_lane_used = 0; 1072 phymod_phy_inf_config_t cfg; 1073 int rv = PHYMOD_E_NONE; 1074 1075 PHYMOD_MEMSET(&mode_ctrl0, 0, sizeof(DP_SESTO_MODE_CTRL0_TYPE_T)); 1076 PHYMOD_MEMCPY(&cfg, config, sizeof(phymod_phy_inf_config_t)); 1077 SESTO_GET_IP(phy, cfg, core); 1078 1079 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)config->device_aux_modes; 1080 SESTO_GET_PORT_FROM_MODE(config, no_of_ports, aux_mode); 1081 1082 if (config->data_rate != SESTO_SPD_100G && config->data_rate != SESTO_SPD_106G) { 1083 READ_SESTO_PMA_PMD_REG(&phy->access, DP_SESTO_MODE_CTRL0_ADR, mode_ctrl0.data); 1084 for (port_idx=0; port_idx < no_of_ports; port_idx++) { 1085 if(config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || config->data_rate == SESTO_SPD_11G) { 1086 if ((aux_mode->BCM84793_capablity && core == SESTO_MERLIN_CORE) || core == SESTO_FALCON_CORE) { 1087 if (phy->access.lane_mask & (1 << port_idx)) { 1088 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1089 } else { 1090 continue; 1091 } 1092 } else { /* For non BCM84793 with Merlin*/ 1093 if (phy->access.lane_mask & (1 << ((port_idx < 2) ? port_idx : (port_idx + 2)))) { 1094 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1095 } else { 1096 continue; 1097 } 1098 } 1099 } else if((config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) && (!aux_mode->pass_thru)) { 1100 if (core == SESTO_MERLIN_CORE) { 1101 /* MUX Mode*/ 1102 if (phy->access.lane_mask & (0xF << (port_idx*4))) { 1103 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1104 } else { 1105 continue; 1106 } 1107 } else { 1108 if (phy->access.lane_mask & (0x3 << (port_idx * 2))) { 1109 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1110 } else { 1111 continue; 1112 } 1113 } 1114 } else if(config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G) { 1115 if (aux_mode->pass_thru) { 1116 if (core == SESTO_MERLIN_CORE) { 1117 if (phy->access.lane_mask & (0x3 << (port_idx * 4))) { 1118 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1119 } else { 1120 continue; 1121 } 1122 } else { 1123 if (phy->access.lane_mask & (0x3 << (port_idx * 2))) { 1124 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1125 } else { 1126 continue; 1127 } 1128 } 1129 } else { /* MUX mode*/ 1130 if (core == SESTO_MERLIN_CORE) { 1131 if (phy->access.lane_mask & (0x3 << (port_idx * 4))) { 1132 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1133 } else { 1134 continue; 1135 } 1136 } else { /* Falcon*/ 1137 if (phy->access.lane_mask & (0x1 << (port_idx * 2))) { 1138 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1139 } else { 1140 continue; 1141 } 1142 } 1143 } 1144 } else { 1145 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1146 } 1147 if (!is_lane_used) { 1148 return PHYMOD_E_PARAM; 1149 } 1150 1151 /* Program Modes */ 1152 if (((config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_20G || 1153 config->data_rate == SESTO_SPD_42G || config->data_rate == SESTO_SPD_21G) && (port_idx == 0)) || 1154 ((config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || 1155 config->data_rate == SESTO_SPD_11G) && (port_idx < 2))) { 1156 if (config->data_rate == SESTO_SPD_40G || (config->data_rate == SESTO_SPD_42G)) { 1157 mode_ctrl0.fields.mode_multiport1_40g_mux = !(aux_mode->pass_thru); 1158 /* Clearing the 20G PT & MUX bits and 10G bits*/ 1159 mode_ctrl0.fields.mode_multiport1_20g_passthru = 0; 1160 mode_ctrl0.fields.mode_multiport1_20g_mux = 0; 1161 mode_ctrl0.fields.mode_multiport1_10g1 = 0; 1162 mode_ctrl0.fields.mode_multiport1_10g2 = 0; 1163 } 1164 if (config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G) { 1165 if (aux_mode->pass_thru) { 1166 mode_ctrl0.fields.mode_multiport1_20g_passthru = aux_mode->pass_thru; 1167 mode_ctrl0.fields.mode_multiport1_20g_mux = 0; 1168 } else { 1169 mode_ctrl0.fields.mode_multiport1_20g_mux = 1; 1170 mode_ctrl0.fields.mode_multiport1_20g_passthru = 0; 1171 } 1172 /* Clearing the 40G Mux and 20G PT & MUX bits */ 1173 mode_ctrl0.fields.mode_multiport1_40g_mux = 0; 1174 mode_ctrl0.fields.mode_multiport1_10g1 = 0; 1175 mode_ctrl0.fields.mode_multiport1_10g2 = 0; 1176 } 1177 if (config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || config->data_rate == SESTO_SPD_11G) { 1178 if (phy->access.lane_mask & 0x1) { 1179 mode_ctrl0.fields.mode_multiport1_10g1 = 1; 1180 } if (phy->access.lane_mask & 0x2) { 1181 mode_ctrl0.fields.mode_multiport1_10g2 = 1; 1182 } 1183 /* Clearing the 40G Mux and 20G PT & MUX bits */ 1184 mode_ctrl0.fields.mode_multiport1_40g_mux = 0; 1185 mode_ctrl0.fields.mode_multiport1_20g_passthru = 0; 1186 mode_ctrl0.fields.mode_multiport1_20g_mux = 0; 1187 } 1188 } else { 1189 if (config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) { 1190 mode_ctrl0.fields.mode_multiport2_40g_mux = !(aux_mode->pass_thru); 1191 /* Clearing the 20G PT & MUX bits and 10G bits*/ 1192 mode_ctrl0.fields.mode_multiport2_20g_passthru = 0; 1193 mode_ctrl0.fields.mode_multiport2_20g_mux = 0; 1194 mode_ctrl0.fields.mode_multiport2_10g1 = 0; 1195 mode_ctrl0.fields.mode_multiport2_10g2 = 0; 1196 } 1197 if (config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G) { 1198 if (aux_mode->pass_thru) { 1199 mode_ctrl0.fields.mode_multiport2_20g_passthru = aux_mode->pass_thru; 1200 mode_ctrl0.fields.mode_multiport2_20g_mux = 0; 1201 } else { 1202 mode_ctrl0.fields.mode_multiport2_20g_mux = 1; 1203 mode_ctrl0.fields.mode_multiport2_20g_passthru = 0; 1204 } 1205 mode_ctrl0.fields.mode_multiport2_40g_mux = 0; 1206 mode_ctrl0.fields.mode_multiport2_10g1 = 0; 1207 mode_ctrl0.fields.mode_multiport2_10g2 = 0; 1208 } 1209 if (config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || config->data_rate == SESTO_SPD_11G) { 1210 if ((phy->access.lane_mask & 0x4) || (phy->access.lane_mask & 0x10)) { 1211 mode_ctrl0.fields.mode_multiport2_10g1 = 1; 1212 } if ((phy->access.lane_mask & 0x8) || (phy->access.lane_mask & 0x20)) { 1213 mode_ctrl0.fields.mode_multiport2_10g2 = 1; 1214 } 1215 /* Clearing the 40G Mux and 20G PT & MUX bits */ 1216 mode_ctrl0.fields.mode_multiport2_40g_mux = 0; 1217 mode_ctrl0.fields.mode_multiport2_20g_passthru = 0; 1218 mode_ctrl0.fields.mode_multiport2_20g_mux = 0; 1219 } 1220 } 1221 } 1222 } 1223 mode_ctrl0.fields.mode_falcon_line = (aux_mode->passthru_sys_side_core == SESTO_MERLIN_CORE) ? 1224 SESTO_FALCON_CORE : SESTO_MERLIN_CORE; 1225 1226 mode_ctrl0.fields.mode_enzo_combatible_en = aux_mode->BCM84793_capablity; 1227 mode_ctrl0.fields.mode_100g_gbox_en = (config->data_rate == SESTO_SPD_100G || config->data_rate == SESTO_SPD_106G) ? 1 : 0; 1228 mode_ctrl0.fields.mode_40g_passthru_en = (config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) && 1229 (aux_mode->pass_thru); 1230 1231 PHYMOD_DEBUG_VERBOSE(("MODE CTRL0 :0x%x\n", mode_ctrl0.data)); 1232 1233 WRITE_SESTO_PMA_PMD_REG(&phy->access, DP_SESTO_MODE_CTRL0_ADR, mode_ctrl0.data); 1234 1235 ERR: 1236 return rv; 1237 } 1238 1239 int _sesto_toggle_mer_fal_lane_reset(const phymod_access_t *pa) 1240 { 1241 int rv = PHYMOD_E_NONE; 1242 1243 SESTO_CHIP_FIELD_WRITE(pa, DP_FAL_MER_LINE_SIDE_RESET_CONTROL1, mer_ln_h_rstb, 0); 1244 SESTO_CHIP_FIELD_WRITE(pa, DP_FAL_MER_LINE_SIDE_RESET_CONTROL1, fal_ln_h_rstb, 0); 1245 1246 PHYMOD_USLEEP(100); 1247 SESTO_CHIP_FIELD_WRITE(pa, DP_FAL_MER_LINE_SIDE_RESET_CONTROL1, mer_ln_h_rstb, 0x3ff); 1248 SESTO_CHIP_FIELD_WRITE(pa, DP_FAL_MER_LINE_SIDE_RESET_CONTROL1, fal_ln_h_rstb, 0xf); 1249 1250 ERR: 1251 return rv; 1252 } 1253 1254 /** Configure Dut Mode Register 1255 */ 1256 int _sesto_udms_config(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t* config, 1257 SESTO_AN_MODE mode) 1258 { 1259 uint16_t no_of_ports = 0, port_idx = 0; 1260 SESTO_DEVICE_AUX_MODE_T *aux_mode; 1261 DP_SESTO_MODE_CTRL1_TYPE_T mode_ctrl1; 1262 phymod_phy_inf_config_t cfg; 1263 uint16_t core = 0; 1264 uint16_t is_lane_used = 0; 1265 int rv = PHYMOD_E_NONE; 1266 1267 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)config->device_aux_modes; 1268 PHYMOD_MEMSET(&mode_ctrl1, 0, sizeof(DP_SESTO_MODE_CTRL1_TYPE_T)); 1269 PHYMOD_MEMCPY(&cfg, config, sizeof(phymod_phy_inf_config_t)); 1270 SESTO_GET_PORT_FROM_MODE(config, no_of_ports, aux_mode); 1271 SESTO_GET_IP(phy, cfg, core); 1272 1273 if (config->data_rate != SESTO_SPD_100G && config->data_rate != SESTO_SPD_106G) { 1274 for (port_idx=0; port_idx < no_of_ports; port_idx++) { 1275 if(config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || config->data_rate == SESTO_SPD_11G) { 1276 if ((aux_mode->BCM84793_capablity && core == SESTO_MERLIN_CORE) || core == SESTO_FALCON_CORE) { 1277 if (phy->access.lane_mask & (1 << port_idx)) { 1278 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1279 } else { 1280 continue; 1281 } 1282 } else { /* For non BCM84793 with Merlin*/ 1283 if (phy->access.lane_mask & (1 << ((port_idx < 2) ? port_idx : (port_idx + 2)))) { 1284 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1285 } else { 1286 continue; 1287 } 1288 } 1289 } else if((config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) && (!aux_mode->pass_thru)) { 1290 if (core == SESTO_MERLIN_CORE) { 1291 /* MUX Mode*/ 1292 if (phy->access.lane_mask & (0xF << (port_idx*4))) { 1293 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1294 } else { 1295 continue; 1296 } 1297 } else { 1298 if (phy->access.lane_mask & (0x3 << (port_idx * 2))) { 1299 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1300 } else { 1301 continue; 1302 } 1303 } 1304 } else if(config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G) { 1305 if (aux_mode->pass_thru) { 1306 if (core == SESTO_MERLIN_CORE) { 1307 if (phy->access.lane_mask & (0x3 << (port_idx * 4))) { 1308 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1309 } else { 1310 continue; 1311 } 1312 } else { 1313 if (phy->access.lane_mask & (0x3 << (port_idx * 2))) { 1314 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1315 } else { 1316 continue; 1317 } 1318 } 1319 } else { /* MUX mode*/ 1320 if (core == SESTO_MERLIN_CORE) { 1321 if (phy->access.lane_mask & (0x3 << (port_idx * 4))) { 1322 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1323 } else { 1324 continue; 1325 } 1326 } else { /* Falcon*/ 1327 if (phy->access.lane_mask & (0x1 << (port_idx * 2))) { 1328 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1329 } else { 1330 continue; 1331 } 1332 } 1333 } 1334 } else { 1335 is_lane_used = sesto_is_lane_mask_set(phy, port_idx, config); 1336 } 1337 if (!is_lane_used) { 1338 return PHYMOD_E_PARAM; 1339 } 1340 1341 READ_SESTO_PMA_PMD_REG(&phy->access, DP_SESTO_MODE_CTRL1_ADR, mode_ctrl1.data); 1342 /* Program Modes */ 1343 if (((config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_20G || 1344 config->data_rate == SESTO_SPD_42G || config->data_rate == SESTO_SPD_21G) && (port_idx == 0)) || 1345 ((config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || 1346 config->data_rate == SESTO_SPD_11G) && (port_idx < 2))) { 1347 mode_ctrl1.fields.udms_en1 = (mode == SESTO_AN_NONE || mode == SESTO_AN_CL73) ? 1 : 0; 1348 if (config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G || 1349 config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) { 1350 mode_ctrl1.fields.mode_dmept1_en = (mode == SESTO_AN_PROP) ? 1 : 0; 1351 } else if(config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || config->data_rate == SESTO_SPD_11G) { 1352 if (phy->access.lane_mask & 0x1) { 1353 mode_ctrl1.fields.mode_dmept1_en = (mode == SESTO_AN_PROP) ? 1 : 0; 1354 } else if (phy->access.lane_mask & 0x2) { 1355 mode_ctrl1.fields.mode_dmept1b_en = (mode == SESTO_AN_PROP) ? 1 : 0; 1356 } 1357 } 1358 } else { 1359 mode_ctrl1.fields.udms_en2 = (mode == SESTO_AN_NONE || mode == SESTO_AN_CL73) ? 1 : 0; 1360 if (config->data_rate == SESTO_SPD_20G || config->data_rate == SESTO_SPD_21G || 1361 config->data_rate == SESTO_SPD_40G || config->data_rate == SESTO_SPD_42G) { 1362 mode_ctrl1.fields.mode_dmept2_en = (mode == SESTO_AN_PROP) ? 1 : 0; 1363 } else if(config->data_rate == SESTO_SPD_1G || config->data_rate == SESTO_SPD_10G || config->data_rate == SESTO_SPD_11G) { 1364 if (phy->access.lane_mask & 0x1) { 1365 mode_ctrl1.fields.mode_dmept2_en = (mode == SESTO_AN_PROP) ? 1 : 0; 1366 } else if (phy->access.lane_mask & 0x2) { 1367 mode_ctrl1.fields.mode_dmept2b_en = (mode == SESTO_AN_PROP) ? 1 : 0; 1368 } 1369 } 1370 } 1371 } 1372 } else { 1373 mode_ctrl1.fields.udms_en1 = (mode == SESTO_AN_NONE || mode == SESTO_AN_CL73) ? 1 : 0; 1374 } 1375 PHYMOD_DEBUG_VERBOSE(("MODE CTRL1 :0x%x\n", mode_ctrl1.data)); 1376 WRITE_SESTO_PMA_PMD_REG(&phy->access, DP_SESTO_MODE_CTRL1_ADR, mode_ctrl1.data); 1377 1378 ERR: 1379 return rv; 1380 } 1381 1382 int _sesto_interface_set(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t* config) 1383 { 1384 uint16_t phy_type = 0; 1385 uint16_t media_type = 2, ip = 0; /* Default to optical */ 1386 SESTO_DEVICE_AUX_MODE_T *aux_mode; 1387 SES_GEN_CNTRLS_GPREG11_TYPE_T gpreg11; 1388 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T intf_sel_spd; 1389 SES_GEN_CNTRLS_MICRO_SYNC_5_TYPE_T intf_sel_p0_p1; 1390 SES_GEN_CNTRLS_MICRO_SYNC_6_TYPE_T intf_sel_p2_p3; 1391 phymod_phy_inf_config_t cpy_config; 1392 uint16_t intf = config->interface_type; 1393 const phymod_access_t *pa = &phy->access; 1394 uint16_t dfe_en = 0, dfe_lp_en = 0; 1395 uint16_t port = 0, no_of_ports = 0; 1396 uint16_t scrambling_dis = 0; 1397 int rv = PHYMOD_E_NONE; 1398 1399 PHYMOD_MEMSET(&gpreg11, 0, sizeof(gpreg11)); 1400 PHYMOD_MEMSET(&intf_sel_spd, 0, sizeof(intf_sel_spd)); 1401 PHYMOD_MEMSET(&intf_sel_p0_p1, 0, sizeof(intf_sel_p0_p1)); 1402 PHYMOD_MEMSET(&intf_sel_p2_p3, 0, sizeof(intf_sel_p2_p3)); 1403 1404 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)config->device_aux_modes; 1405 PHYMOD_MEMCPY(&cpy_config, config, sizeof(phymod_phy_inf_config_t)); 1406 SESTO_GET_IP(phy, cpy_config, ip); 1407 SESTO_GET_PORT_FROM_MODE(config, no_of_ports, aux_mode); 1408 SESTO_IF_ERR_RETURN(_sesto_port_from_lane_map_get(phy, config, &port)); 1409 1410 if (intf == phymodInterfaceSR4 || intf == phymodInterfaceSR10 || 1411 intf == phymodInterfaceER4 || intf == phymodInterfaceLR10 || 1412 intf == phymodInterfaceSR2 || intf == phymodInterfaceLR2 || 1413 intf == phymodInterfaceER2 || intf == phymodInterfaceLR || 1414 intf == phymodInterfaceSR || intf == phymodInterfaceER || 1415 intf == phymodInterfaceSFI || intf == phymodInterfaceXLPPI) { 1416 media_type = 2; /*OPTICAL*/ 1417 dfe_en = 0; 1418 dfe_lp_en = 0; 1419 } else if (intf == phymodInterfaceCR4 || intf == phymodInterfaceCR || 1420 intf == phymodInterfaceCR2 || intf == phymodInterfaceCR10) { 1421 media_type = 1; /*Copper*/ 1422 dfe_en = 1; 1423 dfe_lp_en = 0; 1424 } else if (intf == phymodInterfaceKR4 || intf == phymodInterfaceKR || 1425 intf == phymodInterfaceKR2 || intf == phymodInterfaceKR10) { 1426 media_type = 0; /* Back plane */ 1427 dfe_en = 1; 1428 dfe_lp_en = 0; 1429 } else if (intf == phymodInterfaceCAUI4 || intf == phymodInterfaceVSR || 1430 intf == phymodInterfaceCAUI || intf == phymodInterfaceCAUI4_C2M || 1431 intf == phymodInterfaceCAUI4_C2C) { 1432 media_type = 0; /* Back plane */ 1433 dfe_en = 1; 1434 dfe_lp_en = 1; 1435 } else if (intf == phymodInterfaceXLAUI2 || intf == phymodInterfaceXLAUI || 1436 intf == phymodInterfaceXFI) { 1437 media_type = 0; /* Back plane */ 1438 dfe_en = 0; 1439 dfe_lp_en = 0; 1440 } else if (intf == phymodInterfaceLR4) { 1441 media_type = 2; /*OPTICAL*/ 1442 dfe_en = 0; 1443 dfe_lp_en = 0; 1444 if (config->data_rate == SESTO_SPD_100G || config->data_rate == SESTO_SPD_106G) { 1445 dfe_en = 1; 1446 } 1447 } else { 1448 SESTO_RETURN_WITH_ERR(PHYMOD_E_PARAM, 1449 (_PHYMOD_MSG("Invalid interface type.."))); 1450 } 1451 1452 /* For 1G support */ 1453 if (config->data_rate == SESTO_SPD_1G) { 1454 scrambling_dis = 1; 1455 } 1456 1457 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1458 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1459 if (no_of_ports == 1) { /* 100G/40GPT */ 1460 if (ip == SESTO_MERLIN_CORE) { 1461 intf_sel_p0_p1.fields.p0_10g_media_type = media_type; 1462 intf_sel_p0_p1.fields.p0_10g_dfe_on = dfe_en; 1463 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1464 /* 100G/40GPT has only one port clearing the MICRO_SYNC_6 */ 1465 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, 0x0); 1466 } else { 1467 intf_sel_p0_p1.fields.p0_20g_media_type = media_type; 1468 intf_sel_p0_p1.fields.p0_20g_dfe_on = dfe_en; 1469 intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode = dfe_lp_en; 1470 intf_sel_p0_p1.fields.p0_scrambling_dis = scrambling_dis; 1471 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1472 /* 100G/40GPT has only one port clearing the MICRO_SYNC_6 */ 1473 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, 0x0); 1474 } 1475 } else if (no_of_ports == 2) { /* 40GMUX/20GMUX/20PT */ 1476 if (port == 0) { 1477 if (ip == SESTO_MERLIN_CORE) { 1478 intf_sel_p0_p1.fields.p0_10g_media_type = media_type; 1479 intf_sel_p0_p1.fields.p0_10g_dfe_on = dfe_en; 1480 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1481 } else { 1482 intf_sel_p0_p1.fields.p0_20g_media_type = media_type; 1483 intf_sel_p0_p1.fields.p0_20g_dfe_on = dfe_en; 1484 intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode = dfe_lp_en; 1485 intf_sel_p0_p1.fields.p0_scrambling_dis = scrambling_dis; 1486 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1487 } 1488 } else { 1489 if (ip == SESTO_MERLIN_CORE) { 1490 intf_sel_p2_p3.fields.p2_10g_media_type = media_type; 1491 intf_sel_p2_p3.fields.p2_10g_dfe_on = dfe_en; 1492 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1493 } else { 1494 intf_sel_p2_p3.fields.p2_20g_media_type = media_type; 1495 intf_sel_p2_p3.fields.p2_20g_dfe_on = dfe_en; 1496 intf_sel_p2_p3.fields.p2_20g_dfe_lp_mode = dfe_lp_en; 1497 intf_sel_p2_p3.fields.p2_scrambling_dis = scrambling_dis; 1498 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1499 } 1500 } 1501 } else { /* 10G */ 1502 if (port == 0) { 1503 if (ip == SESTO_MERLIN_CORE) { 1504 intf_sel_p0_p1.fields.p0_10g_media_type = media_type; 1505 intf_sel_p0_p1.fields.p0_10g_dfe_on = dfe_en; 1506 intf_sel_p0_p1.fields.p0_scrambling_dis = scrambling_dis; 1507 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1508 } else { 1509 intf_sel_p0_p1.fields.p0_20g_media_type = media_type; 1510 intf_sel_p0_p1.fields.p0_20g_dfe_on = dfe_en; 1511 intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode = dfe_lp_en; 1512 intf_sel_p0_p1.fields.p0_scrambling_dis = scrambling_dis; 1513 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1514 } 1515 } else if (port == 1) { 1516 if (ip == SESTO_MERLIN_CORE) { 1517 intf_sel_p0_p1.fields.p1_10g_media_type = media_type; 1518 intf_sel_p0_p1.fields.p1_10g_dfe_on = dfe_en; 1519 intf_sel_p0_p1.fields.p1_scrambling_dis = scrambling_dis; 1520 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1521 } else { 1522 intf_sel_p0_p1.fields.p1_20g_media_type = media_type; 1523 intf_sel_p0_p1.fields.p1_20g_dfe_on = dfe_en; 1524 intf_sel_p0_p1.fields.p1_20g_dfe_lp_mode = dfe_lp_en; 1525 intf_sel_p0_p1.fields.p1_scrambling_dis = scrambling_dis; 1526 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 1527 } 1528 } else if (port == 2) { 1529 if (ip == SESTO_MERLIN_CORE) { 1530 intf_sel_p2_p3.fields.p2_10g_media_type = media_type; 1531 intf_sel_p2_p3.fields.p2_10g_dfe_on = dfe_en; 1532 intf_sel_p2_p3.fields.p2_scrambling_dis = scrambling_dis; 1533 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1534 } else { 1535 intf_sel_p2_p3.fields.p2_20g_media_type = media_type; 1536 intf_sel_p2_p3.fields.p2_20g_dfe_on = dfe_en; 1537 intf_sel_p2_p3.fields.p2_20g_dfe_lp_mode = dfe_lp_en; 1538 intf_sel_p2_p3.fields.p2_scrambling_dis = scrambling_dis; 1539 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1540 } 1541 } else { 1542 if (ip == SESTO_MERLIN_CORE) { 1543 intf_sel_p2_p3.fields.p3_10g_media_type = media_type; 1544 intf_sel_p2_p3.fields.p3_10g_dfe_on = dfe_en; 1545 intf_sel_p2_p3.fields.p3_scrambling_dis = scrambling_dis; 1546 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1547 } else { 1548 intf_sel_p2_p3.fields.p3_20g_media_type = media_type; 1549 intf_sel_p2_p3.fields.p3_20g_dfe_on = dfe_en; 1550 intf_sel_p2_p3.fields.p3_20g_dfe_lp_mode = dfe_lp_en; 1551 intf_sel_p2_p3.fields.p3_scrambling_dis = scrambling_dis; 1552 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 1553 } 1554 } 1555 } 1556 1557 if (PHYMOD_INTF_MODES_OTN_GET(config)) { 1558 phy_type = 1; 1559 } else if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 1560 phy_type = 2; 1561 } else { 1562 phy_type = 0; /* Default to ethernet mode*/ 1563 } 1564 /* Configure PHY Type*/ 1565 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 1566 gpreg11.fields.phy_type = phy_type; 1567 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 1568 1569 /* SES_GEN_CNTRLS_MICRO_SYNC_4_ADR: 12-15 bits are used as scratch register to configure the 1G support */ 1570 /* 12-15 bits also used to support speed change in HIGIG interface mode */ 1571 if ((config->data_rate == SESTO_SPD_1G) || (PHYMOD_INTF_MODES_HIGIG_GET(config) && ((config->data_rate == SESTO_SPD_10G) || 1572 (config->data_rate == SESTO_SPD_20G) || (config->data_rate == SESTO_SPD_40G) || (config->data_rate == SESTO_SPD_100G)))){ 1573 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, intf_sel_spd.data); 1574 intf_sel_spd.data |= (1 << (12 + port)); 1575 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, intf_sel_spd.data); 1576 } else { 1577 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, intf_sel_spd.data); 1578 intf_sel_spd.data &= ~(1 << (12 + port)); 1579 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, intf_sel_spd.data); 1580 } 1581 1582 PHYMOD_DEBUG_VERBOSE(("GPREG11 data:%x\n",gpreg11.data)); 1583 PHYMOD_DEBUG_VERBOSE(("SYNC_4 data:%x\n",intf_sel_spd.data)); 1584 PHYMOD_DEBUG_VERBOSE(("SYNC_5 data:%x\n",intf_sel_p0_p1.data)); 1585 PHYMOD_DEBUG_VERBOSE(("SYNC_6 data:%x\n",intf_sel_p2_p3.data)); 1586 1587 SESTO_IF_ERR_RETURN( 1588 _sesto_set_ieee_intf(phy, intf, config, ip)); 1589 1590 ERR: 1591 return rv; 1592 } 1593 1594 int _sesto_set_ieee_intf(const phymod_phy_access_t *phy, uint16_t intf, const phymod_phy_inf_config_t *config, uint16_t ip) 1595 { 1596 uint16_t port = 0; 1597 uint16_t intf_side = 0; 1598 int rv = PHYMOD_E_NONE; 1599 const phymod_access_t *pa = &phy->access; 1600 SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T mod_sel; 1601 1602 PHYMOD_MEMSET(&mod_sel, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T)); 1603 SESTO_IF_ERR_RETURN( 1604 _sesto_port_from_lane_map_get(phy, config, &port)); 1605 1606 READ_SESTO_PMA_PMD_REG(pa, (SES_GEN_CNTRLS_MICRO_SYNC_0_ADR + port), mod_sel.data); 1607 SESTO_GET_INTF_SIDE(phy, intf_side); 1608 mod_sel.data = intf_side ? (mod_sel.data & 0xFF) : (mod_sel.data & 0xFF00); 1609 mod_sel.data |= intf_side ? (intf << 8) : (intf); 1610 WRITE_SESTO_PMA_PMD_REG(pa, (SES_GEN_CNTRLS_MICRO_SYNC_0_ADR + port), mod_sel.data); 1611 1612 ERR: 1613 return rv; 1614 } 1615 1616 int _sesto_get_ieee_intf(const phymod_phy_access_t *phy, uint16_t ip, const phymod_phy_inf_config_t *config, uint16_t *intf) 1617 { 1618 uint16_t port = 0; 1619 uint16_t intf_side = 0; 1620 int rv = PHYMOD_E_NONE; 1621 const phymod_access_t *pa = &phy->access; 1622 SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T mod_sel; 1623 1624 PHYMOD_MEMSET(&mod_sel, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T)); 1625 SESTO_IF_ERR_RETURN( 1626 _sesto_port_from_lane_map_get(phy, config, &port)); 1627 1628 READ_SESTO_PMA_PMD_REG(pa, (SES_GEN_CNTRLS_MICRO_SYNC_0_ADR + port), mod_sel.data); 1629 SESTO_GET_INTF_SIDE(phy, intf_side); 1630 *intf = intf_side ? ((mod_sel.data >> 8) & 0xFF) : (mod_sel.data & 0x00FF); 1631 1632 ERR: 1633 return rv; 1634 } 1635 1636 int _sesto_pll_config_state_get(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t* config, uint16_t *pll_cfg_state) 1637 { 1638 phymod_phy_inf_config_t cfg; 1639 SESTO_DEVICE_AUX_MODE_T *aux_mode; 1640 uint16_t ip = 0; 1641 uint16_t no_of_ports = 0; 1642 DP_DECODED_MODE_STATUS0_TYPE_T mode_sts0; 1643 uint16_t fal_pll_lock = 0, mer_pll_lock = 0; 1644 const phymod_access_t *pa = &phy->access; 1645 int rv = PHYMOD_E_NONE; 1646 1647 PHYMOD_MEMSET(&cfg, 0, sizeof(phymod_phy_inf_config_t)); 1648 cfg.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 1649 aux_mode = (SESTO_DEVICE_AUX_MODE_T*) config->device_aux_modes; 1650 SESTO_IF_ERR_RETURN( 1651 _sesto_phy_interface_config_get(phy, 0, &cfg)); 1652 1653 READ_SESTO_PMA_PMD_REG(pa, DP_DECODED_MODE_STATUS0_ADR, mode_sts0.data); 1654 for (ip = SESTO_MERLIN_CORE; ip <= SESTO_FALCON_CORE; ip++) { 1655 SESTO_IF_ERR_RETURN( 1656 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, SESTO_DEV_PMA_PMD, 0, 0)); 1657 if (ip == SESTO_FALCON_CORE) { 1658 SESTO_CHIP_FIELD_READ(pa, FALCON_IF_PMD_PLL_STS, pmd_pll_lock, fal_pll_lock); 1659 } else { 1660 SESTO_CHIP_FIELD_READ(pa, MERLIN_IF_PMD_PLL_LOCK_STATUS, pmd_pll_lock, mer_pll_lock); 1661 } 1662 } 1663 /* 1664 * PLL div is per die and will be programed only when 1665 * 1. if there is no pll lock on merlin or falcon 1666 * 2. speed change b/w 100G to 40G/20G/10G 1667 * 3. if ref clock freq changes(pll lock lost) 1668 * 4. On interface_modes changes(IEEE/OTN/HIGIG) 1669 */ 1670 SESTO_GET_PORT_FROM_MODE(config, no_of_ports, aux_mode); 1671 if (((fal_pll_lock != 1) || (mer_pll_lock != 1)) || (config->ref_clock != cfg.ref_clock) || 1672 ((config->interface_modes & (PHYMOD_INTF_MODES_HIGIG | PHYMOD_INTF_MODES_OTN)) != (cfg.interface_modes & (PHYMOD_INTF_MODES_HIGIG | PHYMOD_INTF_MODES_OTN))) || 1673 ((no_of_ports == 1) && (config->data_rate != cfg.data_rate)) || (!mode_sts0.data) || 1674 ((no_of_ports > 1) && (cfg.data_rate == SESTO_SPD_100G) && (config->data_rate != SESTO_SPD_100G)) || 1675 ((no_of_ports > 1) && (cfg.data_rate == SESTO_SPD_106G) && (config->data_rate != SESTO_SPD_106G))) { 1676 *pll_cfg_state = 1; 1677 } 1678 /* HIGIG mode speed change */ 1679 if ((config->interface_modes == cfg.interface_modes) && (config->data_rate != cfg.data_rate)) { 1680 *pll_cfg_state = 1; 1681 } 1682 1683 ERR: 1684 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 1685 PHYMOD_FREE(cfg.device_aux_modes); 1686 1687 return rv; 1688 } 1689 1690 1691 int _sesto_phy_interface_config_set(const phymod_phy_access_t* phy, uint32_t flags, const phymod_phy_inf_config_t* config) 1692 { 1693 uint16_t pll_cfg_state = 0; 1694 int rv = PHYMOD_E_NONE; 1695 1696 /* Get the pll config state */ 1697 SESTO_IF_ERR_RETURN( 1698 _sesto_pll_config_state_get(phy, config, &pll_cfg_state)); 1699 1700 /* Configure Ref Clock*/ 1701 PHYMOD_DEBUG_VERBOSE(("Configuring REF clock\n")); 1702 SESTO_IF_ERR_RETURN( 1703 _sesto_configure_ref_clock(&phy->access, config->ref_clock)); 1704 1705 /* Configure DUT MODE */ 1706 SESTO_IF_ERR_RETURN( 1707 _sesto_config_dut_mode_reg(phy, config)); 1708 1709 /* Enable UDMS for non-an MODE */ 1710 PHYMOD_DEBUG_VERBOSE(("Configuring UDMS\n")); 1711 SESTO_IF_ERR_RETURN( 1712 _sesto_udms_config(phy, config, SESTO_AN_NONE)); 1713 1714 /* Configure PLL Divider*/ 1715 if (pll_cfg_state) { 1716 PHYMOD_DEBUG_VERBOSE(("Configuring PLL divider\n")); 1717 SESTO_IF_ERR_RETURN( 1718 _sesto_config_pll_div(&phy->access, config)); 1719 } 1720 1721 /* Configure Interface */ 1722 SESTO_IF_ERR_RETURN( 1723 _sesto_interface_set(phy, config)); 1724 1725 ERR: 1726 return rv; 1727 } 1728 1729 int _sesto_phy_interface_config_get(const phymod_phy_access_t *phy, uint32_t flags, phymod_phy_inf_config_t *config) 1730 { 1731 uint16_t ip = 0, intf_side = 0; 1732 SESTO_DEVICE_AUX_MODE_T *aux_mode; 1733 DP_DECODED_MODE_STATUS0_TYPE_T mode_sts0; 1734 SES_GEN_CNTRLS_GPREG11_TYPE_T gpreg11; 1735 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T ref_clk_freq; 1736 int rv = PHYMOD_E_NONE; 1737 uint16_t clock = 0, port = 0; 1738 const phymod_access_t *pa = &phy->access; 1739 uint16_t lane_mask = pa->lane_mask; 1740 1741 PHYMOD_MEMSET(&mode_sts0, 0, sizeof(DP_DECODED_MODE_STATUS0_TYPE_T)); 1742 PHYMOD_MEMSET(&gpreg11, 0, sizeof(SES_GEN_CNTRLS_GPREG11_TYPE_T)); 1743 PHYMOD_MEMSET(&ref_clk_freq, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T)); 1744 aux_mode = (SESTO_DEVICE_AUX_MODE_T*) config->device_aux_modes; 1745 if (aux_mode == NULL) { 1746 PHYMOD_DEBUG_VERBOSE(("AUX MODE MEM NOT ALLOC\n")); 1747 return PHYMOD_E_PARAM; 1748 } 1749 PHYMOD_MEMSET(aux_mode, 0, sizeof(SESTO_DEVICE_AUX_MODE_T)); 1750 1751 if (!lane_mask) { 1752 PHYMOD_DEBUG_VERBOSE(("Invalid Lanemask\n")); 1753 return PHYMOD_E_PARAM; 1754 } 1755 SESTO_GET_INTF_SIDE(phy, intf_side); 1756 READ_SESTO_PMA_PMD_REG(pa, DP_DECODED_MODE_STATUS0_ADR, mode_sts0.data); 1757 PHYMOD_DEBUG_VERBOSE(("MODE STS:%x\n", mode_sts0.data)); 1758 if (intf_side == SESTO_IF_LINE) { 1759 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_FALCON_CORE : SESTO_MERLIN_CORE; 1760 } else { 1761 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_MERLIN_CORE : SESTO_FALCON_CORE; 1762 } 1763 if (ip == SESTO_FALCON_CORE) { 1764 if (mode_sts0.fields.decoded_mode_100g_gbox) { 1765 config->data_rate = SESTO_SPD_100G; 1766 aux_mode->gearbox_100g_inverse_mode = (mode_sts0.fields.decoded_mode_falcon_line) ? 0 : 1; 1767 } else if (lane_mask & 0x3) { 1768 if (mode_sts0.fields.decoded_mode_40g_mux_p1) { 1769 config->data_rate = SESTO_SPD_40G; 1770 aux_mode->pass_thru = 0; 1771 } else if (mode_sts0.fields.decoded_mode_40g_passthru) { 1772 config->data_rate = SESTO_SPD_40G; 1773 aux_mode->pass_thru = 1; 1774 aux_mode->BCM84793_capablity = 0; 1775 if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1776 aux_mode->BCM84793_capablity = 1; 1777 } 1778 } else if (mode_sts0.fields.decoded_mode_20g_mux_p1) { 1779 config->data_rate = SESTO_SPD_20G; 1780 aux_mode->pass_thru = 0; 1781 } else if (mode_sts0.fields.decoded_mode_20g_passthru_p1) { 1782 config->data_rate = SESTO_SPD_20G; 1783 aux_mode->pass_thru = 1; 1784 } else if (mode_sts0.fields.decoded_mode_10g_p1) { 1785 config->data_rate = SESTO_SPD_10G; 1786 aux_mode->pass_thru = 1; 1787 } else if (mode_sts0.fields.decoded_mode_10g_p2) { 1788 config->data_rate = SESTO_SPD_10G; 1789 aux_mode->pass_thru = 1; 1790 } 1791 } else if (lane_mask & 0xc) { 1792 if (mode_sts0.fields.decoded_mode_40g_mux_p2) { 1793 config->data_rate = SESTO_SPD_40G; 1794 aux_mode->pass_thru = 0; 1795 } else if (mode_sts0.fields.decoded_mode_40g_passthru) { 1796 config->data_rate = SESTO_SPD_40G; 1797 aux_mode->pass_thru = 1; 1798 aux_mode->BCM84793_capablity = 0; 1799 if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1800 aux_mode->BCM84793_capablity = 1; 1801 } 1802 } else if (mode_sts0.fields.decoded_mode_20g_passthru_p2) { 1803 config->data_rate = SESTO_SPD_20G; 1804 aux_mode->pass_thru = 1; 1805 } else if (mode_sts0.fields.decoded_mode_20g_mux_p2) { 1806 config->data_rate = SESTO_SPD_20G; 1807 aux_mode->pass_thru = 0; 1808 } else if (mode_sts0.fields.decoded_mode_10g_p3) { 1809 config->data_rate = SESTO_SPD_10G; 1810 aux_mode->pass_thru = 1; 1811 if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1812 aux_mode->BCM84793_capablity = 1; 1813 } 1814 } else if (mode_sts0.fields.decoded_mode_10g_p4) { 1815 config->data_rate = SESTO_SPD_10G; 1816 aux_mode->pass_thru = 1; 1817 if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1818 aux_mode->BCM84793_capablity = 1; 1819 } 1820 } 1821 } 1822 } else { 1823 if (mode_sts0.fields.decoded_mode_100g_gbox) { 1824 config->data_rate = SESTO_SPD_100G; 1825 aux_mode->gearbox_100g_inverse_mode = (mode_sts0.fields.decoded_mode_falcon_line) ? 0 : 1; 1826 } else if (lane_mask & 0xF) { 1827 if ((mode_sts0.fields.decoded_mode_10g_p1) && (lane_mask & 0x1)) { 1828 config->data_rate = SESTO_SPD_10G; 1829 aux_mode->pass_thru = 1; 1830 } else if ((mode_sts0.fields.decoded_mode_10g_p2) && (lane_mask & 0x2)) { 1831 config->data_rate = SESTO_SPD_10G; 1832 aux_mode->pass_thru = 1; 1833 } else if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1834 if ((mode_sts0.fields.decoded_mode_10g_p3) && (lane_mask & 0x4)) { 1835 config->data_rate = SESTO_SPD_10G; 1836 aux_mode->pass_thru = 1; 1837 aux_mode->BCM84793_capablity = 1; 1838 } else if ((mode_sts0.fields.decoded_mode_10g_p4) && (lane_mask & 0x8)) { 1839 config->data_rate = SESTO_SPD_10G; 1840 aux_mode->pass_thru = 1; 1841 aux_mode->BCM84793_capablity = 1; 1842 } else if (mode_sts0.fields.decoded_mode_40g_passthru) { 1843 config->data_rate = SESTO_SPD_40G; 1844 aux_mode->pass_thru = 1; 1845 aux_mode->BCM84793_capablity = 1; 1846 } 1847 } else if (mode_sts0.fields.decoded_mode_20g_mux_p1) { 1848 config->data_rate = SESTO_SPD_20G; 1849 aux_mode->pass_thru = 0; 1850 } else if (mode_sts0.fields.decoded_mode_20g_passthru_p1) { 1851 config->data_rate = SESTO_SPD_20G; 1852 aux_mode->pass_thru = 1; 1853 } else if (mode_sts0.fields.decoded_mode_40g_mux_p1) { 1854 config->data_rate = SESTO_SPD_40G; 1855 aux_mode->pass_thru = 0; 1856 } else if (mode_sts0.fields.decoded_mode_40g_passthru) { 1857 config->data_rate = SESTO_SPD_40G; 1858 aux_mode->pass_thru = 1; 1859 aux_mode->BCM84793_capablity = 0; 1860 if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1861 aux_mode->BCM84793_capablity = 1; 1862 } 1863 } 1864 } else if (lane_mask & 0xF0) { 1865 if (mode_sts0.fields.decoded_mode_10g_p3) { 1866 config->data_rate = SESTO_SPD_10G; 1867 aux_mode->pass_thru = 1; 1868 } else if (mode_sts0.fields.decoded_mode_10g_p4) { 1869 config->data_rate = SESTO_SPD_10G; 1870 aux_mode->pass_thru = 1; 1871 } else if (mode_sts0.fields.decoded_mode_20g_mux_p2) { 1872 config->data_rate = SESTO_SPD_20G; 1873 aux_mode->pass_thru = 0; 1874 } else if (mode_sts0.fields.decoded_mode_20g_passthru_p2) { 1875 config->data_rate = SESTO_SPD_20G; 1876 aux_mode->pass_thru = 1; 1877 } else if (mode_sts0.fields.decoded_mode_40g_mux_p2) { 1878 config->data_rate = SESTO_SPD_40G; 1879 aux_mode->pass_thru = 0; 1880 } else if (mode_sts0.fields.decoded_mode_40g_passthru) { 1881 config->data_rate = SESTO_SPD_40G; 1882 aux_mode->pass_thru = 1; 1883 if (mode_sts0.fields.decoded_mode_enzo_compatible) { 1884 aux_mode->BCM84793_capablity = 1; 1885 } 1886 } 1887 } 1888 } 1889 aux_mode->passthru_sys_side_core = 1890 (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_MERLIN_CORE : SESTO_FALCON_CORE; 1891 1892 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 1893 if (gpreg11.fields.phy_type == 1) { 1894 PHYMOD_INTF_MODES_OTN_SET(config); 1895 } else if (gpreg11.fields.phy_type == 2) { 1896 PHYMOD_INTF_MODES_HIGIG_SET(config); 1897 if (config->data_rate == SESTO_SPD_10G) { 1898 config->data_rate = SESTO_SPD_11G; 1899 } else if (config->data_rate == SESTO_SPD_20G) { 1900 config->data_rate = SESTO_SPD_21G; 1901 } else if (config->data_rate == SESTO_SPD_40G) { 1902 config->data_rate = SESTO_SPD_42G; 1903 } else if (config->data_rate == SESTO_SPD_100G) { 1904 config->data_rate = SESTO_SPD_106G; 1905 } 1906 } else { 1907 config->interface_modes = 0; /*Ethernet*/ 1908 } 1909 SESTO_CHIP_FIELD_READ(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, clock); 1910 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 1911 if (clock <= 0x2) { 1912 config->ref_clock = ((ref_clk_freq.data >> 8) & 0xF); 1913 } 1914 /*SES_GEN_CNTRLS_MICRO_SYNC_4_ADR 12-15 bits are defined for 1G support */ 1915 /* 12-15 bits also used to support speed change in HIGIG interface mode */ 1916 SESTO_IF_ERR_RETURN(_sesto_port_from_lane_map_get(phy, config, &port)); 1917 if ((ref_clk_freq.data >> (12 + port)) & 0x1) { 1918 if (gpreg11.fields.phy_type == 2) { 1919 PHYMOD_INTF_MODES_HIGIG_SET(config); 1920 if (config->data_rate == SESTO_SPD_11G) { 1921 config->data_rate = SESTO_SPD_10G; 1922 } else if (config->data_rate == SESTO_SPD_21G) { 1923 config->data_rate = SESTO_SPD_20G; 1924 } else if (config->data_rate == SESTO_SPD_42G) { 1925 config->data_rate = SESTO_SPD_40G; 1926 } else if (config->data_rate == SESTO_SPD_106G) { 1927 config->data_rate = SESTO_SPD_100G; 1928 } 1929 } else { 1930 config->data_rate = SESTO_SPD_1G; 1931 } 1932 } 1933 1934 SESTO_IF_ERR_RETURN( 1935 _sesto_get_ieee_intf(phy, ip, config, &intf_side)); 1936 config->interface_type = intf_side; 1937 1938 ERR: 1939 return rv; 1940 } 1941 1942 int _sesto_phy_pcs_link_get(const phymod_phy_access_t *phy, uint32_t *pcs_link) 1943 { 1944 int rv = PHYMOD_E_NONE; 1945 uint32_t lock_lost_lh = 0, error_count = 0; 1946 1947 if (pcs_link) { 1948 *pcs_link = 0xffff; 1949 } else { 1950 return PHYMOD_E_PARAM; 1951 } 1952 SESTO_IF_ERR_RETURN( 1953 _sesto_get_pcs_link_status(phy, pcs_link, &lock_lost_lh, &error_count)); 1954 1955 ERR: 1956 return rv; 1957 } 1958 1959 int _sesto_configure_ref_clock(const phymod_access_t *pa, phymod_ref_clk_t ref_clk) 1960 { 1961 int rv = PHYMOD_E_NONE; 1962 uint16_t clk_scalar_code = 0x0; 1963 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T ref_clk_freq; 1964 1965 PHYMOD_MEMSET(&ref_clk_freq, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T)); 1966 /* SES_GEN_CNTRLS_MICRO_SYNC_4_ADR: 8-11 bits are used as scratch register to configure the ref_clk_freq */ 1967 1968 switch (ref_clk) { 1969 case phymodRefClk156Mhz: 1970 case phymodRefClk312Mhz: 1971 /* Writing to scratch reg to save in chip */ 1972 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 1973 ref_clk_freq.data &= 0xF0FF; 1974 ref_clk_freq.data |= (ref_clk << 8); 1975 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 1976 SESTO_CHIP_FIELD_READ(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, clk_scalar_code); 1977 if (clk_scalar_code != 0x02) { 1978 SESTO_CHIP_FIELD_WRITE(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, 0x02); 1979 } 1980 break; 1981 case phymodRefClk161Mhz: 1982 case phymodRefClk322Mhz: 1983 case phymodRefClk644Mhz: 1984 /* Writing to scratch reg to save in chip */ 1985 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 1986 ref_clk_freq.data &= 0xF0FF; 1987 ref_clk_freq.data |= (ref_clk << 8); 1988 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 1989 SESTO_CHIP_FIELD_READ(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, clk_scalar_code); 1990 if (clk_scalar_code != 0x01) { 1991 SESTO_CHIP_FIELD_WRITE(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, 0x01); 1992 } 1993 break; 1994 case phymodRefClk174Mhz: 1995 case phymodRefClk349Mhz: 1996 case phymodRefClk698Mhz: 1997 /* Writing to scratch reg to save in chip */ 1998 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 1999 ref_clk_freq.data &= 0xF0FF; 2000 ref_clk_freq.data |= (ref_clk << 8); 2001 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, ref_clk_freq.data); 2002 SESTO_CHIP_FIELD_READ(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, clk_scalar_code); 2003 if (clk_scalar_code != 0x0) { 2004 SESTO_CHIP_FIELD_WRITE(pa, SES_CTRL_CLOCK_SCALER_CTRL, clock_scaler_code, 0x0); 2005 } 2006 break; 2007 default: 2008 PHYMOD_DEBUG_ERROR((" This Ref Clock (%d) is not supported\n", ref_clk)); 2009 return PHYMOD_E_PARAM; 2010 } 2011 2012 ERR: 2013 return rv; 2014 } 2015 2016 int _sesto_get_pll_modes(phymod_ref_clk_t ref_clk,const phymod_phy_inf_config_t *config, uint16_t *fal_pll_mode, uint16_t *mer_pll_mode) 2017 { 2018 uint32_t speed = config->data_rate; 2019 2020 switch (ref_clk) { 2021 case phymodRefClk156Mhz: 2022 case phymodRefClk312Mhz: 2023 /* No OTN support on 156 and 312 */ 2024 if (PHYMOD_INTF_MODES_OTN_GET(config)) { 2025 return PHYMOD_E_PARAM; 2026 } 2027 if ((speed == SESTO_SPD_100G) || (speed == SESTO_SPD_106G)) { 2028 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 2029 *fal_pll_mode = SESTO_PLL_MODE_175; 2030 *mer_pll_mode = SESTO_PLL_MODE_70; 2031 if (speed == SESTO_SPD_100G) { 2032 *fal_pll_mode = SESTO_PLL_MODE_165; 2033 *mer_pll_mode = SESTO_PLL_MODE_66; 2034 } 2035 } else { 2036 *fal_pll_mode = SESTO_PLL_MODE_165; 2037 *mer_pll_mode = SESTO_PLL_MODE_66; 2038 } 2039 } else { 2040 /*-- Falcon Line Rate is 10G/20G*/ 2041 if (PHYMOD_INTF_MODES_HIGIG_GET(config)) { 2042 *fal_pll_mode = SESTO_PLL_MODE_140; 2043 *mer_pll_mode = SESTO_PLL_MODE_70; 2044 if ((speed == SESTO_SPD_40G) || (speed == SESTO_SPD_20G) || (speed == SESTO_SPD_10G)) { 2045 *fal_pll_mode = SESTO_PLL_MODE_132; 2046 *mer_pll_mode = SESTO_PLL_MODE_66; 2047 } 2048 } else { /*IEEE MODE*/ 2049 *fal_pll_mode = SESTO_PLL_MODE_132; 2050 *mer_pll_mode = SESTO_PLL_MODE_66; 2051 } 2052 } 2053 break; 2054 case phymodRefClk161Mhz: 2055 case phymodRefClk322Mhz: 2056 case phymodRefClk644Mhz: 2057 /* No OTN or HIGIG Support on 161/322/644 */ 2058 if ((PHYMOD_INTF_MODES_HIGIG_GET(config)) || (PHYMOD_INTF_MODES_OTN_GET(config))) { 2059 return PHYMOD_E_PARAM; 2060 } 2061 if (speed == SESTO_SPD_100G) { 2062 /*IEEE MODE*/ 2063 *fal_pll_mode = SESTO_PLL_MODE_160; 2064 *mer_pll_mode = SESTO_PLL_MODE_64; 2065 } else { 2066 *fal_pll_mode = SESTO_PLL_MODE_128; 2067 *mer_pll_mode = SESTO_PLL_MODE_64; 2068 } 2069 break; 2070 case phymodRefClk174Mhz: 2071 case phymodRefClk349Mhz: 2072 case phymodRefClk698Mhz: 2073 if (speed == SESTO_SPD_100G) { 2074 if (PHYMOD_INTF_MODES_OTN_GET(config)) { 2075 *fal_pll_mode = SESTO_PLL_MODE_160; 2076 *mer_pll_mode = SESTO_PLL_MODE_64; 2077 } else { 2078 return PHYMOD_E_PARAM; 2079 } 2080 } else { 2081 if (PHYMOD_INTF_MODES_OTN_GET(config)) { 2082 *fal_pll_mode = SESTO_PLL_MODE_128; 2083 *mer_pll_mode = SESTO_PLL_MODE_64; 2084 } else { 2085 return PHYMOD_E_PARAM; 2086 } 2087 } 2088 break; 2089 default: 2090 return PHYMOD_E_PARAM; 2091 } 2092 2093 return PHYMOD_E_NONE; 2094 } 2095 2096 /** Map Merlin PLL Division 2097 * @param PLL Mode 2098 * @return Merlin PLL mode mapped value 2099 */ 2100 int _sesto_map_mer_pll_div(SESTO_PLL_MODE_E pll_mode) 2101 { 2102 switch (pll_mode) { 2103 case SESTO_PLL_MODE_64: 2104 return 1; 2105 case SESTO_PLL_MODE_66: 2106 return 2; 2107 case SESTO_PLL_MODE_70: 2108 return 3; 2109 default: 2110 PHYMOD_DEBUG_VERBOSE(("PLLMODE %d not supported\n", pll_mode)); 2111 return PHYMOD_E_PARAM; 2112 } 2113 } 2114 2115 int _sesto_config_pll_div(const phymod_access_t *pa, const phymod_phy_inf_config_t *config) 2116 { 2117 uint16_t ip = 0, merlin_pll_mode = 0, falcon_pll_mode = 0; 2118 phymod_ref_clk_t ref_clk = config->ref_clock; 2119 uint16_t lock = 0, retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 2120 int rv = PHYMOD_E_NONE; 2121 2122 /*Program PLL div of all dies*/ 2123 /* Set pll_mode */ 2124 SESTO_IF_ERR_RETURN( 2125 _sesto_get_pll_modes(ref_clk, config, &falcon_pll_mode, &merlin_pll_mode)); 2126 for (ip = SESTO_MERLIN_CORE; ip <= SESTO_FALCON_CORE; ip++) { 2127 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s Max_lane:%d lanemask:0x%x\n", 2128 __func__, (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", 1, 0x1)); 2129 SESTO_IF_ERR_RETURN( 2130 _sesto_set_slice_reg(pa, SESTO_SLICE_UNICAST, ip, SESTO_DEV_PMA_PMD, 0, 0)); 2131 if (ip == SESTO_FALCON_CORE) { 2132 /* write 0 to core_dp_s_rstb while pll config*/ 2133 wrc_falcon_furia_sesto_core_dp_s_rstb(0); 2134 /* default values for falcon pll */ 2135 wrc_falcon_furia_sesto_ams_pll_vco2_15g(0x0); 2136 wrc_falcon_furia_sesto_ams_pll_force_kvh_bw(0); 2137 wrc_falcon_furia_sesto_ams_pll_kvh_force(0); 2138 wrc_falcon_furia_sesto_ams_pll_vco_indicator(0); 2139 2140 /* Set PLL div */ 2141 switch (falcon_pll_mode) { 2142 case SESTO_PLL_MODE_160: 2143 if (PHYMOD_INTF_MODES_OTN_GET(config)) { 2144 SESTO_IF_ERR_RETURN( 2145 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_160x_refc174)); 2146 } else { 2147 SESTO_IF_ERR_RETURN( 2148 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_160x)); 2149 } 2150 break; 2151 case SESTO_PLL_MODE_132: 2152 SESTO_IF_ERR_RETURN( 2153 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_132x)); 2154 break; 2155 case SESTO_PLL_MODE_128: 2156 SESTO_IF_ERR_RETURN( 2157 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_128x)); 2158 break; 2159 case SESTO_PLL_MODE_140: 2160 SESTO_IF_ERR_RETURN( 2161 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_140x)); 2162 break; 2163 case SESTO_PLL_MODE_165: 2164 SESTO_IF_ERR_RETURN( 2165 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_165x)); 2166 break; 2167 case SESTO_PLL_MODE_175: 2168 SESTO_IF_ERR_RETURN( 2169 falcon_furia_sesto_configure_pll(pa, FALCON_FURIA_pll_div_175x)); 2170 break; 2171 } 2172 /* write 1 to core_dp_s_rstb after pll config*/ 2173 wrc_falcon_furia_sesto_core_dp_s_rstb(1); 2174 } else { 2175 /* write 0 to core_dp_s_rstb while pll config*/ 2176 wrc_core_dp_s_rstb(0); 2177 if (_sesto_map_mer_pll_div(merlin_pll_mode) == 1) { 2178 /*-- PLL Mode 64*/ 2179 SESTO_IF_ERR_RETURN( 2180 merlin_sesto_configure_pll(pa, MERLIN_SESTO_pll_10p3125GHz_161p132MHz)); 2181 } else if (_sesto_map_mer_pll_div(merlin_pll_mode) == 0x2) { 2182 /* PLL Mode 66*/ 2183 SESTO_IF_ERR_RETURN( 2184 merlin_sesto_configure_pll(pa, MERLIN_SESTO_pll_10p3125GHz_156p25MHz)); 2185 } else if (_sesto_map_mer_pll_div(merlin_pll_mode) == 0x3) { 2186 /* PLL Mode 70*/ 2187 SESTO_IF_ERR_RETURN( 2188 merlin_sesto_configure_pll(pa, MERLIN_SESTO_pll_10p9375GHz_156p25MHz)); 2189 } else { 2190 return PHYMOD_E_PARAM; 2191 } 2192 /* write 1 to core_dp_s_rstb after pll config*/ 2193 wrc_core_dp_s_rstb(1); 2194 } 2195 } 2196 2197 /*check for the pll lock and get the lanes out of reset*/ 2198 do { 2199 if (ip == SESTO_FALCON_CORE) { 2200 SESTO_CHIP_FIELD_READ(pa, F25G_PLL_CAL_COM_CTL_STATUS_0, pll_lock, lock); 2201 } else { 2202 SESTO_CHIP_FIELD_READ(pa, M10G_PLL_CAL_PLL_CALSTS_0, pll_lock, lock); 2203 } 2204 PHYMOD_DEBUG_VERBOSE(("PLL LOCK STS:%d\n", lock)); 2205 retry_cnt--; 2206 } while((lock != 1) && (retry_cnt)); 2207 if (retry_cnt == 0) { 2208 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 2209 (_PHYMOD_MSG("ERR:PLL NOT LOCKED"))); 2210 return PHYMOD_E_FAIL; 2211 } 2212 2213 ERR: 2214 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2215 return rv; 2216 } 2217 2218 int _sesto_core_dp_rstb(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t config) 2219 { 2220 uint16_t lane = 0, ip = 0, lock = 0; 2221 uint16_t max_lane = 0, lane_mask=0; 2222 uint16_t cast_type = 0, mcast_val=0; 2223 uint16_t retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 2224 const phymod_access_t *pa = &phy->access; 2225 int rv = PHYMOD_E_NONE; 2226 2227 SESTO_GET_IP(phy, config, ip); 2228 2229 lane_mask = (pa->lane_mask) ? pa->lane_mask : 0x3ff; 2230 max_lane = (ip == SESTO_FALCON_CORE) ? SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 2231 2232 SESTO_GET_CORE_SLICE_INFO(phy, ip, config, &cast_type, &mcast_val); 2233 PHYMOD_DEBUG_VERBOSE(("%s: IP:%s Max_lane:%d lanemask:0x%x cast_type:%d\n", 2234 __func__, (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask, 2235 cast_type)); 2236 2237 if (cast_type != SESTO_CAST_INVALID) { 2238 for (lane = 0; lane < max_lane; lane ++) { 2239 if (lane_mask & (1 << lane)) { 2240 SESTO_IF_ERR_RETURN( 2241 _sesto_set_slice_reg (pa, cast_type, ip, 2242 SESTO_DEV_PMA_PMD, mcast_val, lane)); 2243 if (ip == SESTO_FALCON_CORE) { 2244 SESTO_IF_ERR_RETURN( 2245 wrc_falcon_furia_sesto_core_dp_s_rstb(1)); 2246 } else { 2247 SESTO_IF_ERR_RETURN( 2248 wrc_core_dp_s_rstb(1)); 2249 } 2250 if (SESTO_IS_MULTI_BROAD_CAST_SET(cast_type)) { 2251 break; 2252 } 2253 } 2254 } 2255 } 2256 2257 /*check for the pll lock and get the lanes out of reset*/ 2258 do { 2259 if (ip == SESTO_FALCON_CORE) { 2260 SESTO_CHIP_FIELD_READ(pa, F25G_PLL_CAL_COM_CTL_STATUS_0, pll_lock, lock); 2261 } else { 2262 SESTO_CHIP_FIELD_READ(pa, M10G_PLL_CAL_PLL_CALSTS_0, pll_lock, lock); 2263 } 2264 PHYMOD_DEBUG_VERBOSE(("PLL LOCK STS:%d\n", lock)); 2265 retry_cnt--; 2266 } while((lock != 1) && (retry_cnt)); 2267 if (retry_cnt == 0) { 2268 SESTO_RETURN_WITH_ERR(PHYMOD_E_FAIL, 2269 (_PHYMOD_MSG("ERR:PLL NOT LOCKED"))); 2270 return PHYMOD_E_FAIL; 2271 } 2272 2273 ERR: 2274 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2275 return rv; 2276 } 2277 2278 int _sesto_core_reset_set(const phymod_access_t *pa, phymod_reset_mode_t reset_mode, phymod_reset_direction_t direction) 2279 { 2280 SES_GEN_CNTRLS_GEN_CONTROL1_TYPE_T gen_ctrl; 2281 FALCON_IF_COMMON_CONTROL_TYPE_T fal_cmn_ctrl; 2282 MERLIN_IF_COMMON_CONTROL_TYPE_T mer_cmn_ctrl; 2283 int rv = PHYMOD_E_NONE; 2284 2285 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL1_ADR, gen_ctrl.data); 2286 if (reset_mode == phymodResetModeHard) { 2287 gen_ctrl.fields.resetb = 0; 2288 gen_ctrl.fields.reg_rstb = 0; 2289 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL1_ADR, gen_ctrl.data); 2290 2291 /* -- Resetting the Cores*/ 2292 READ_SESTO_PMA_PMD_REG(pa, FALCON_IF_COMMON_CONTROL_ADR, fal_cmn_ctrl.data); 2293 fal_cmn_ctrl.fields.pmd_por_h_rstb_frcval = 0; 2294 fal_cmn_ctrl.fields.pmd_por_h_rstb_frc = 1; 2295 WRITE_SESTO_PMA_PMD_REG(pa, FALCON_IF_COMMON_CONTROL_ADR, fal_cmn_ctrl.data); 2296 2297 READ_SESTO_PMA_PMD_REG(pa, MERLIN_IF_COMMON_CONTROL_ADR, mer_cmn_ctrl.data); 2298 mer_cmn_ctrl.fields.pmd_por_h_rstb_frcval = 0; 2299 mer_cmn_ctrl.fields.pmd_por_h_rstb_frc = 1; 2300 WRITE_SESTO_PMA_PMD_REG(pa, MERLIN_IF_COMMON_CONTROL_ADR, mer_cmn_ctrl.data); 2301 2302 /* -- Releasing the Core resets*/ 2303 SESTO_CHIP_FIELD_WRITE(pa, FALCON_IF_COMMON_CONTROL, pmd_por_h_rstb_frc,0); 2304 SESTO_CHIP_FIELD_WRITE(pa, MERLIN_IF_COMMON_CONTROL, pmd_por_h_rstb_frc,0); 2305 PHYMOD_USLEEP(100); 2306 } else { 2307 gen_ctrl.fields.reg_rstb = 0; 2308 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL1_ADR, gen_ctrl.data); 2309 2310 /* Reset the Merlin */ 2311 SESTO_IF_ERR_RETURN( 2312 _sesto_set_slice_reg (pa, SESTO_SLICE_BROADCAST, 2313 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 2314 0, 0)); 2315 SESTO_CHIP_FIELD_WRITE(pa, M10G_CKRST_CTRL_LANE_CLK_RESET_N_POWERDOWN_CONTROL, 2316 ln_s_rstb, 0); 2317 PHYMOD_USLEEP(100); 2318 SESTO_CHIP_FIELD_WRITE(pa, M10G_CKRST_CTRL_LANE_CLK_RESET_N_POWERDOWN_CONTROL, 2319 ln_s_rstb, 1); 2320 /* Reset the Falcon */ 2321 SESTO_IF_ERR_RETURN( 2322 _sesto_set_slice_reg (pa, SESTO_SLICE_BROADCAST, 2323 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 2324 0, 0)); 2325 SESTO_CHIP_FIELD_WRITE(pa, F25G_CKRST_CTRL_RPTR_LN_S_RSTB_CONTROL, 2326 ln_s_rstb, 0); 2327 PHYMOD_USLEEP(100); 2328 SESTO_CHIP_FIELD_WRITE(pa, F25G_CKRST_CTRL_RPTR_LN_S_RSTB_CONTROL, 2329 ln_s_rstb, 1); 2330 } 2331 2332 ERR: 2333 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2334 return rv; 2335 } 2336 2337 int _sesto_pcs_link_monitor_enable_set(const phymod_phy_access_t *phy, uint16_t en_dis) 2338 { 2339 uint16_t lane = 0; 2340 uint16_t ip = 0; 2341 phymod_phy_inf_config_t config; 2342 uint16_t max_lane = 0, lane_mask=0; 2343 uint16_t reg_addr = 0; 2344 int rv = PHYMOD_E_NONE; 2345 const phymod_access_t *pa = &phy->access; 2346 DP_FMON0_MAIN_CONTROL_TYPE_T fmon_main_ctrl; 2347 DP_MMON0_MAIN_CONTROL_TYPE_T mmon_main_ctrl; 2348 2349 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 2350 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 2351 PHYMOD_MEMSET(&fmon_main_ctrl, 0, sizeof(DP_FMON0_MAIN_CONTROL_TYPE_T)); 2352 PHYMOD_MEMSET(&mmon_main_ctrl, 0, sizeof(DP_MMON0_MAIN_CONTROL_TYPE_T)); 2353 SESTO_IF_ERR_RETURN( 2354 _sesto_phy_interface_config_get(phy, 0, &config)); 2355 2356 SESTO_GET_IP(phy, config, ip); 2357 2358 lane_mask = (pa->lane_mask) ? pa->lane_mask : 0x3ff; 2359 max_lane = (ip == SESTO_FALCON_CORE) ? SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 2360 2361 PHYMOD_DEBUG_VERBOSE(("%s :: IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 2362 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 2363 for (lane = 0; lane < max_lane; lane ++) { 2364 if ((lane_mask & (1 << lane))) { 2365 if (ip == SESTO_FALCON_CORE) { 2366 reg_addr = DP_FMON0_MAIN_CONTROL_ADR + lane; 2367 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fmon_main_ctrl.data); 2368 fmon_main_ctrl.fields.fmon0_main_ctrl &= ~(0x1); 2369 fmon_main_ctrl.fields.fmon0_main_ctrl |= (en_dis ? 0x1 : 0); 2370 WRITE_SESTO_PMA_PMD_REG(pa, reg_addr, fmon_main_ctrl.data); 2371 PHYMOD_DEBUG_VERBOSE(("Falcon Link monitor for Lane:%d Data:0x%x\n", 2372 lane, fmon_main_ctrl.data)); 2373 } else { 2374 reg_addr = DP_MMON0_MAIN_CONTROL_ADR + lane; 2375 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mmon_main_ctrl.data); 2376 mmon_main_ctrl.fields.mmon0_main_ctrl &= ~(0x1); 2377 mmon_main_ctrl.fields.mmon0_main_ctrl |= (en_dis ? 0x1 : 0); 2378 WRITE_SESTO_PMA_PMD_REG(pa, reg_addr, mmon_main_ctrl.data); 2379 PHYMOD_DEBUG_VERBOSE(("Merlin Link monitor for Lane:%d Data:0x%x\n", 2380 lane, mmon_main_ctrl.data)); 2381 } 2382 } 2383 } 2384 2385 ERR: 2386 PHYMOD_FREE(config.device_aux_modes); 2387 return rv; 2388 } 2389 2390 int _sesto_pcs_link_monitor_enable_get(const phymod_phy_access_t *phy, uint32_t *get_pcs) 2391 { 2392 uint16_t lane = 0; 2393 uint16_t ip = 0; 2394 phymod_phy_inf_config_t config; 2395 uint16_t max_lane = 0, lane_mask=0; 2396 uint16_t reg_addr = 0; 2397 int rv = PHYMOD_E_NONE; 2398 const phymod_access_t *pa = &phy->access; 2399 DP_FMON0_MAIN_CONTROL_TYPE_T fmon_main_ctrl; 2400 DP_MMON0_MAIN_CONTROL_TYPE_T mmon_main_ctrl; 2401 2402 *get_pcs = 0xffff; 2403 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 2404 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 2405 PHYMOD_MEMSET(&fmon_main_ctrl, 0, sizeof(DP_FMON0_MAIN_CONTROL_TYPE_T)); 2406 PHYMOD_MEMSET(&mmon_main_ctrl, 0, sizeof(DP_MMON0_MAIN_CONTROL_TYPE_T)); 2407 SESTO_IF_ERR_RETURN( 2408 _sesto_phy_interface_config_get(phy, 0, &config)); 2409 2410 SESTO_GET_IP(phy, config, ip); 2411 2412 lane_mask = (pa->lane_mask) ? pa->lane_mask : 0x3ff; 2413 max_lane = (ip == SESTO_FALCON_CORE) ? SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 2414 2415 PHYMOD_DEBUG_VERBOSE(("%s :: IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 2416 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 2417 for (lane = 0; lane < max_lane; lane ++) { 2418 if ((lane_mask & (1 << lane))) { 2419 if (ip == SESTO_FALCON_CORE) { 2420 reg_addr = DP_FMON0_MAIN_CONTROL_ADR + lane; 2421 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fmon_main_ctrl.data); 2422 *get_pcs &= fmon_main_ctrl.fields.fmon0_main_ctrl & (0x1); 2423 PHYMOD_DEBUG_VERBOSE(("Falcon Get Link monitor for Lane:%d Data:0x%x\n", 2424 lane, *get_pcs)); 2425 } else { 2426 reg_addr = DP_MMON0_MAIN_CONTROL_ADR + lane; 2427 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mmon_main_ctrl.data); 2428 *get_pcs &= mmon_main_ctrl.fields.mmon0_main_ctrl & (0x1); 2429 PHYMOD_DEBUG_VERBOSE(("Merlin Get Link monitor for Lane:%d Data:0x%x\n", 2430 lane, *get_pcs)); 2431 } 2432 } 2433 } 2434 2435 ERR: 2436 PHYMOD_FREE(config.device_aux_modes); 2437 2438 return rv; 2439 } 2440 2441 int _sesto_get_pcs_link_status(const phymod_phy_access_t *phy, uint32_t *link_sts, uint32_t* lock_lost_lh, uint32_t* error_count) 2442 { 2443 uint16_t lane = 0; 2444 uint16_t ip = 0; 2445 phymod_phy_inf_config_t config; 2446 uint16_t max_lane = 0, lane_mask=0, count_msb = 0; 2447 uint16_t reg_addr = 0; 2448 uint32_t err_cnt = 0, get_pcs = 0; 2449 int rv = PHYMOD_E_NONE; 2450 const phymod_access_t *pa = &phy->access; 2451 DP_FMON0_MAIN_STATUS_TYPE_T fmon_main_sts; 2452 DP_MMON0_MAIN_STATUS_TYPE_T mmon_main_sts; 2453 DP_FMON0_LIVE_STATUS_TYPE_T fmon_live_link; 2454 DP_MMON0_LIVE_STATUS_TYPE_T mmon_live_link; 2455 2456 *link_sts = 0xffff; 2457 2458 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 2459 SESTO_IF_ERR_RETURN( 2460 _sesto_pcs_link_monitor_enable_get(phy, &get_pcs)); 2461 2462 if (get_pcs) { 2463 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 2464 SESTO_IF_ERR_RETURN( 2465 _sesto_phy_interface_config_get(phy, 0, &config)); 2466 2467 SESTO_GET_IP(phy, config, ip); 2468 2469 lane_mask = (pa->lane_mask) ? pa->lane_mask : 0x3ff; 2470 max_lane = (ip == SESTO_FALCON_CORE) ? SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 2471 2472 PHYMOD_DEBUG_VERBOSE(("IP:%s Max_lane:%d lanemask:0x%x\n", 2473 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 2474 2475 PHYMOD_DEBUG_VERBOSE(("Getting PCS Status\n")); 2476 for (lane = 0; lane < max_lane; lane ++) { 2477 if ((lane_mask & (1 << lane))) { 2478 if (ip == SESTO_FALCON_CORE) { 2479 reg_addr = (DP_FMON0_LIVE_STATUS_ADR + lane); 2480 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fmon_live_link.data); 2481 if (fmon_live_link.fields.fmon0_live_stat & 1) { 2482 *link_sts &= 1; 2483 /* PCS lock, Now check Loss of lock*/ 2484 reg_addr = DP_FMON0_MAIN_STATUS_ADR + lane; 2485 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fmon_main_sts.data); 2486 if (!(fmon_main_sts.fields.fmon0_main_stat & 0x4)) { 2487 /* Loss of link : read error cntr*/ 2488 reg_addr = (DP_FMON0_CL49_BER_STATUS_ADR + lane); 2489 READ_SESTO_PMA_PMD_REG(pa, reg_addr, err_cnt); 2490 err_cnt &= 0x7F; 2491 err_cnt >>= 1; 2492 reg_addr = (DP_FMON0_BER_COUNT_MSB_ADR + lane); 2493 READ_SESTO_PMA_PMD_REG(pa, reg_addr, count_msb); 2494 err_cnt |= (count_msb) << 6; 2495 *link_sts &= 0; 2496 PHYMOD_DEBUG_VERBOSE(("Lane:%d Loss of lock: 1 Error Cnt:0x%x\n", 2497 lane, err_cnt)); 2498 } 2499 } else { 2500 *link_sts &= 0; 2501 } 2502 } else { 2503 reg_addr = (DP_MMON0_LIVE_STATUS_ADR + lane); 2504 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mmon_live_link.data); 2505 if (mmon_live_link.fields.mmon0_live_stat & 1) { 2506 *link_sts &= 1; 2507 /* PCS lock, Now check Loss of lock*/ 2508 reg_addr = (DP_MMON0_MAIN_STATUS_ADR + lane); 2509 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mmon_main_sts.data); 2510 if (!(mmon_main_sts.fields.mmon0_main_stat & 0x4)) { 2511 /* Loss of link : read error cntr*/ 2512 reg_addr = (DP_MMON0_CL49_BER_STATUS_ADR + lane); 2513 READ_SESTO_PMA_PMD_REG(pa, reg_addr, err_cnt); 2514 err_cnt &= 0x7F; 2515 err_cnt >>= 1; 2516 reg_addr = (DP_MMON0_BER_COUNT_MSB_ADR + lane); 2517 READ_SESTO_PMA_PMD_REG(pa, reg_addr, count_msb); 2518 err_cnt |= (count_msb) << 6; 2519 *link_sts &= 0; 2520 PHYMOD_DEBUG_VERBOSE(("Lane:%d Loss of lock: 1 Error Cnt:0x%x\n", 2521 lane, err_cnt)); 2522 } 2523 } else { 2524 *link_sts &= 0; 2525 } 2526 } 2527 } 2528 } 2529 } else { 2530 PHYMOD_DEBUG_VERBOSE(("PCS MON not Enabled, Reading PMD Status\n")); 2531 SESTO_IF_ERR_RETURN( 2532 _sesto_rx_pmd_lock_get(phy, link_sts)); 2533 } 2534 ERR: 2535 if (get_pcs) { 2536 PHYMOD_FREE(config.device_aux_modes); 2537 } 2538 2539 return rv; 2540 } 2541 int _sesto_merlin_falcon_lane_map_get(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t *cfg, 2542 uint32_t* mer_lane_map, uint32_t* fal_lane_map) 2543 { 2544 phymod_phy_inf_config_t config; 2545 uint16_t core = 0; 2546 uint32_t lane_mask = 0; 2547 SESTO_DEVICE_AUX_MODE_T *aux_mode; 2548 const phymod_access_t *pa = &phy->access; 2549 2550 lane_mask = (pa->lane_mask) ? pa->lane_mask : 0x3ff; 2551 PHYMOD_MEMCPY(&config, cfg, sizeof(phymod_phy_inf_config_t)); 2552 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)cfg->device_aux_modes; 2553 SESTO_GET_IP(phy, config, core); 2554 PHYMOD_DEBUG_VERBOSE(("%s :: core:%d\n", __func__, core)); 2555 2556 if (config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) { 2557 *mer_lane_map = 0x3FF; 2558 *fal_lane_map = 0xF; 2559 } else if (core == SESTO_MERLIN_CORE) { 2560 if (config.data_rate == SESTO_SPD_40G || config.data_rate == SESTO_SPD_42G) { 2561 if ((aux_mode->pass_thru) && (!aux_mode->BCM84793_capablity)) { 2562 *mer_lane_map = 0x33; 2563 *fal_lane_map = 0xF; 2564 } else if (aux_mode->BCM84793_capablity) { 2565 *mer_lane_map = 0xF; 2566 *fal_lane_map = 0xF; 2567 } 2568 else { 2569 *mer_lane_map = lane_mask; 2570 if (lane_mask == 0xF) 2571 *fal_lane_map = 0x3; 2572 else if(lane_mask == 0xF0) 2573 *fal_lane_map = 0xC; 2574 else 2575 *fal_lane_map = 0xF; 2576 } 2577 } else if (config.data_rate == SESTO_SPD_20G || config.data_rate == SESTO_SPD_21G) { 2578 if (aux_mode->pass_thru) { 2579 *mer_lane_map = lane_mask; 2580 if (lane_mask == 0x3) 2581 *fal_lane_map = 0x3; 2582 else if(lane_mask == 0x30) 2583 *fal_lane_map = 0xC; 2584 else 2585 *fal_lane_map = 0xF; 2586 } else { 2587 *mer_lane_map = lane_mask; 2588 if (lane_mask == 0x3) 2589 *fal_lane_map = 0x1; 2590 else if(lane_mask == 0x30) 2591 *fal_lane_map = 0x4; 2592 else 2593 *fal_lane_map = 0x5; 2594 } 2595 } else { /* 10G */ 2596 if (aux_mode->BCM84793_capablity) { 2597 *mer_lane_map = lane_mask; 2598 *fal_lane_map = lane_mask; 2599 } else { 2600 *mer_lane_map = lane_mask; 2601 if ((lane_mask == 0x1) || (lane_mask == 0x2)) 2602 *fal_lane_map = lane_mask; 2603 else if((lane_mask == 0x10) || (lane_mask == 0x20)) 2604 *fal_lane_map = (lane_mask >> 2); 2605 else 2606 *fal_lane_map = 0xF; 2607 } 2608 } 2609 } else { 2610 if (config.data_rate == SESTO_SPD_40G || config.data_rate == SESTO_SPD_42G) { 2611 if ((aux_mode->pass_thru) && (!aux_mode->BCM84793_capablity)) { 2612 *mer_lane_map = 0x33; 2613 *fal_lane_map = 0xF; 2614 } else if (aux_mode->BCM84793_capablity) { 2615 *mer_lane_map = 0xF; 2616 *fal_lane_map = 0xF; 2617 } 2618 else { 2619 *fal_lane_map = lane_mask; 2620 if (lane_mask == 0x3) 2621 *mer_lane_map = 0xF; 2622 else if(lane_mask == 0xC) 2623 *mer_lane_map = 0xF0; 2624 else 2625 *mer_lane_map = 0xFF; 2626 } 2627 } else if (config.data_rate == SESTO_SPD_20G || config.data_rate == SESTO_SPD_21G) { 2628 if (aux_mode->pass_thru) { 2629 *fal_lane_map = lane_mask; 2630 if (lane_mask == 0x3) 2631 *mer_lane_map = 0x3; 2632 else if(lane_mask == 0xC) 2633 *mer_lane_map = 0x30; 2634 else 2635 *mer_lane_map = 0x33; 2636 } else { 2637 *fal_lane_map = lane_mask; 2638 if (lane_mask == 0x1) 2639 *mer_lane_map = 0x3; 2640 else if(lane_mask == 0x4) 2641 *mer_lane_map = 0x30; 2642 else 2643 *mer_lane_map = 0x33; 2644 } 2645 } else { /* 10G */ 2646 if (aux_mode->BCM84793_capablity) { 2647 *mer_lane_map = lane_mask; 2648 *fal_lane_map = lane_mask; 2649 } else { 2650 *fal_lane_map = lane_mask; 2651 if ((lane_mask == 0x1) || (lane_mask == 0x2)) 2652 *mer_lane_map = lane_mask; 2653 else if((lane_mask == 0x4) || (lane_mask == 0x8)) 2654 *mer_lane_map = (lane_mask << 2); 2655 else 2656 *mer_lane_map = 0x33; 2657 } 2658 } 2659 } 2660 2661 return PHYMOD_E_NONE; 2662 } 2663 2664 int _sesto_merlin_lpbk_get(const phymod_access_t *pa, phymod_loopback_mode_t loopback, uint32_t* enable) 2665 { 2666 int rv = PHYMOD_E_NONE; 2667 2668 switch (loopback) { 2669 case phymodLoopbackGlobal: 2670 case phymodLoopbackGlobalPMD: 2671 /* Merlin Digital loopback get */ 2672 SESTO_CHIP_FIELD_READ(pa, M10G_TLB_RX_DIG_LPBK_CONFIG, 2673 dig_lpbk_en, (*enable)); 2674 break; 2675 case phymodLoopbackRemotePMD: /* Merlin Remote loopback get */ 2676 SESTO_CHIP_FIELD_READ(pa, M10G_TLB_TX_RMT_LPBK_CONFIG, 2677 rmt_lpbk_en, (*enable)); 2678 break; 2679 case phymodLoopbackRemotePCS: 2680 return PHYMOD_E_UNAVAIL; 2681 default: 2682 break; 2683 } 2684 2685 ERR: 2686 return rv; 2687 } 2688 2689 int _sesto_falcon_lpbk_get(const phymod_access_t *pa, phymod_loopback_mode_t loopback, uint32_t* enable) 2690 { 2691 int rv = PHYMOD_E_NONE; 2692 2693 switch (loopback) { 2694 case phymodLoopbackGlobal: 2695 case phymodLoopbackGlobalPMD: 2696 /* Falcon Digital loopback get */ 2697 SESTO_CHIP_FIELD_READ(pa, F25G_TLB_RX_DIG_LPBK_CONFIG, 2698 dig_lpbk_en, (*enable)); 2699 break; 2700 case phymodLoopbackRemotePMD: /* Falcon Remote loopback get */ 2701 SESTO_CHIP_FIELD_READ(pa, F25G_TLB_TX_RMT_LPBK_CONFIG, 2702 rmt_lpbk_en, (*enable)); 2703 break; 2704 case phymodLoopbackRemotePCS: 2705 return PHYMOD_E_UNAVAIL; 2706 default: 2707 break; 2708 } 2709 2710 ERR: 2711 return rv; 2712 } 2713 2714 int _sesto_loopback_get(const phymod_phy_access_t *phy, phymod_loopback_mode_t loopback, uint32_t* enable) 2715 { 2716 phymod_phy_inf_config_t config; 2717 uint16_t ip = 0; 2718 uint16_t lane = 0; 2719 uint16_t lane_mask = 0, max_lane = 0; 2720 const phymod_access_t *pa = &phy->access; 2721 int rv = PHYMOD_E_NONE; 2722 2723 *enable = 0; 2724 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 2725 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 2726 SESTO_IF_ERR_RETURN( 2727 _sesto_phy_interface_config_get(phy, 0, &config)); 2728 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 2729 SESTO_GET_IP(phy, config, ip); 2730 2731 max_lane = (ip == SESTO_FALCON_CORE) ? 2732 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 2733 2734 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 2735 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 2736 2737 for (lane = 0; lane < max_lane; lane ++) { 2738 if (lane_mask & (1 << lane)) { 2739 SESTO_IF_ERR_RETURN( 2740 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2741 ip, SESTO_DEV_PMA_PMD, 0, lane)); 2742 if (ip == SESTO_FALCON_CORE) { 2743 /* FALCON core loopback set */ 2744 PHYMOD_DEBUG_VERBOSE(("Falcon loopback get\n")); 2745 SESTO_IF_ERR_RETURN( 2746 _sesto_falcon_lpbk_get(pa, loopback, enable)); 2747 break; 2748 } else { 2749 /* MERLIN core loopback get */ 2750 PHYMOD_DEBUG_VERBOSE(("Merlin loopback get\n")); 2751 SESTO_IF_ERR_RETURN( 2752 _sesto_merlin_lpbk_get(pa, loopback, enable)); 2753 break; 2754 } 2755 } 2756 } 2757 2758 ERR: 2759 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2760 PHYMOD_FREE(config.device_aux_modes); 2761 2762 return rv; 2763 } 2764 2765 int _sesto_falcon_lpbk_set(const phymod_phy_access_t* phy, const phymod_phy_inf_config_t *config, 2766 phymod_loopback_mode_t loopback, uint32_t enable) 2767 { 2768 uint16_t lane = 0, data = 0; 2769 uint32_t mer_lane_mask = 0; 2770 uint32_t fal_lane_mask = 0; 2771 const phymod_access_t *pa = &phy->access; 2772 uint16_t lane_mask = PHYMOD_ACC_LANE_MASK(pa); 2773 int rv = PHYMOD_E_NONE; 2774 2775 SESTO_IF_ERR_RETURN( 2776 _sesto_merlin_falcon_lane_map_get(phy, config, &mer_lane_mask, &fal_lane_mask)); 2777 2778 PHYMOD_DEBUG_VERBOSE(("Falcon loopback set\n")); 2779 2780 switch (loopback) { 2781 case phymodLoopbackRemotePMD: /* Falcon remote loopback set */ 2782 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 2783 if (lane_mask & (1 << lane)) { 2784 SESTO_IF_ERR_RETURN( 2785 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2786 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 2787 0, lane)); 2788 SESTO_IF_ERR_RETURN(falcon_furia_sesto_rmt_lpbk(pa, enable)); 2789 /* Work around for RMT LOOPBACK issue */ 2790 if (!enable) { 2791 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_tx_pi_loop_timing_src_sel(0x1)); 2792 } 2793 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_ln_dp_s_rstb(0)); 2794 PHYMOD_USLEEP(10); 2795 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_ln_dp_s_rstb(1)); 2796 } 2797 } 2798 break; 2799 case phymodLoopbackRemotePCS: 2800 return PHYMOD_E_UNAVAIL; 2801 break; 2802 case phymodLoopbackGlobal: 2803 case phymodLoopbackGlobalPMD: /* Falcon digital loopback set */ 2804 { 2805 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 2806 if (mer_lane_mask & (1 << lane)) { 2807 SESTO_IF_ERR_RETURN( 2808 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2809 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 2810 0, lane)); 2811 SESTO_IF_ERR_RETURN(merlin_sesto_dig_lpbk_rptr(pa, enable, DATA_IN_SIDE)); 2812 } 2813 } 2814 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2815 2816 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 2817 if (fal_lane_mask & (1 << lane)) { 2818 SESTO_IF_ERR_RETURN( 2819 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2820 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 2821 0, lane)); 2822 SESTO_IF_ERR_RETURN(falcon_furia_sesto_dig_lpbk_rptr(pa, enable, DIG_LPBK_SIDE)); 2823 /* Disable the prbs_chk_en_auto_mode while seting digital loopback */ 2824 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_prbs_chk_en_auto_mode((!enable))); 2825 /* TX disable while enabling digital loopback if falcon is on line side PHY-1912 */ 2826 SESTO_CHIP_FIELD_READ(pa, DP_DECODED_MODE_STATUS0, decoded_mode_falcon_line, data); 2827 if (data) { 2828 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_sdk_tx_disable(enable)); 2829 } 2830 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_ln_dp_s_rstb(0)); 2831 PHYMOD_USLEEP(10); 2832 SESTO_IF_ERR_RETURN(wr_falcon_furia_sesto_ln_dp_s_rstb(1)); 2833 } 2834 } 2835 PHYMOD_USLEEP(50); 2836 } 2837 break; 2838 default : 2839 break; 2840 } 2841 2842 ERR: 2843 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2844 return rv; 2845 } 2846 2847 int _sesto_merlin_lpbk_set(const phymod_phy_access_t* phy, const phymod_phy_inf_config_t *config, 2848 phymod_loopback_mode_t loopback, uint32_t enable) 2849 { 2850 uint16_t lane = 0, data = 0; 2851 uint32_t mer_lane_mask = 0; 2852 uint32_t fal_lane_mask = 0; 2853 const phymod_access_t *pa = &phy->access; 2854 uint16_t lane_mask = PHYMOD_ACC_LANE_MASK(pa); 2855 int rv = PHYMOD_E_NONE; 2856 2857 SESTO_IF_ERR_RETURN( 2858 _sesto_merlin_falcon_lane_map_get(phy, config, &mer_lane_mask, &fal_lane_mask)); 2859 PHYMOD_DEBUG_VERBOSE(("Merlin loopback set\n")); 2860 2861 switch (loopback) { 2862 case phymodLoopbackRemotePMD: /* Merlin remote loopback set */ 2863 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 2864 if (lane_mask & (1 << lane)) { 2865 SESTO_IF_ERR_RETURN( 2866 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2867 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 2868 0, lane)); 2869 SESTO_IF_ERR_RETURN(merlin_sesto_rmt_lpbk(pa, enable)); 2870 SESTO_IF_ERR_RETURN(wr_ln_dp_s_rstb(0)); 2871 PHYMOD_USLEEP(10); 2872 SESTO_IF_ERR_RETURN(wr_ln_dp_s_rstb(1)); 2873 2874 } 2875 } 2876 break; 2877 case phymodLoopbackRemotePCS: 2878 return PHYMOD_E_UNAVAIL; 2879 break; 2880 case phymodLoopbackGlobal: 2881 case phymodLoopbackGlobalPMD: /* Merlin digital loopack set */ 2882 { 2883 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 2884 if (fal_lane_mask & (1 << lane)) { 2885 SESTO_IF_ERR_RETURN( 2886 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2887 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 2888 0, lane)); 2889 SESTO_IF_ERR_RETURN(falcon_furia_sesto_dig_lpbk_rptr(pa, enable, DATA_IN_SIDE)); 2890 } 2891 } 2892 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2893 2894 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 2895 if (mer_lane_mask & (1 << lane)) { 2896 SESTO_IF_ERR_RETURN( 2897 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 2898 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 2899 0, lane)); 2900 SESTO_IF_ERR_RETURN(merlin_sesto_dig_lpbk_rptr(pa, enable, DIG_LPBK_SIDE)); 2901 /* Disable the prbs_chk_en_auto_mode while seting digital loopback */ 2902 SESTO_IF_ERR_RETURN(wr_prbs_chk_en_auto_mode((!enable))); 2903 /* TX disable while enabling digital loopback if Merlin is on line side PHY-2086 */ 2904 SESTO_CHIP_FIELD_READ(pa, DP_DECODED_MODE_STATUS0, decoded_mode_falcon_line, data); 2905 if (!data) { 2906 SESTO_IF_ERR_RETURN(wr_sdk_tx_disable(enable)); 2907 } 2908 SESTO_IF_ERR_RETURN(wr_ln_dp_s_rstb(0)); 2909 PHYMOD_USLEEP(10); 2910 SESTO_IF_ERR_RETURN(wr_ln_dp_s_rstb(1)); 2911 } 2912 } 2913 PHYMOD_USLEEP(50); 2914 } 2915 break; 2916 default : 2917 break; 2918 } 2919 2920 ERR: 2921 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 2922 return rv; 2923 } 2924 int _sesto_if_ctrl_frc_tx_disable(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t *config, 2925 uint32_t enable) 2926 { 2927 uint16_t lane = 0; 2928 uint32_t mer_lane_mask = 0; 2929 uint32_t fal_lane_mask = 0; 2930 int rv = PHYMOD_E_NONE; 2931 const phymod_access_t *pa = &phy->access; 2932 MERLIN_IF_CONTROL1_LANE0_TYPE_T mer_ctrl_lane; 2933 FALCON_IF_CONTROL1_LANE0_TYPE_T fal_ctrl_lane; 2934 2935 SESTO_IF_ERR_RETURN( 2936 _sesto_merlin_falcon_lane_map_get(phy, config, &mer_lane_mask, &fal_lane_mask)); 2937 2938 /* Falcon Force clear any Tx disables set by HW */ 2939 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 2940 if (fal_lane_mask & (1 << lane)) { 2941 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL1_LANE0_ADR + lane), 2942 fal_ctrl_lane.data); 2943 fal_ctrl_lane.fields.pmd_tx_disable_0_frc = (enable ? 1 : 0); 2944 fal_ctrl_lane.fields.pmd_tx_disable_0_frcval = 0; 2945 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL1_LANE0_ADR + lane), 2946 fal_ctrl_lane.data); 2947 } 2948 } 2949 /* Merlin Force clear any Tx disables set by HW */ 2950 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 2951 if (mer_lane_mask & (1 << lane)) { 2952 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL1_LANE0_ADR + lane), 2953 mer_ctrl_lane.data); 2954 mer_ctrl_lane.fields.pmd_tx_disable_0_frc = (enable ? 1 : 0); 2955 mer_ctrl_lane.fields.pmd_tx_disable_0_frcval = 0; 2956 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL1_LANE0_ADR + lane), 2957 mer_ctrl_lane.data); 2958 } 2959 } 2960 2961 ERR: 2962 return rv; 2963 } 2964 2965 int _sesto_loopback_set(const phymod_phy_access_t *phy, phymod_loopback_mode_t loopback, uint32_t enable) 2966 { 2967 phymod_phy_inf_config_t config; 2968 uint16_t ip = 0; 2969 uint32_t temp = 0; 2970 uint16_t data = 0, retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 2971 SESTO_DEVICE_AUX_MODE_T aux_mode; 2972 const phymod_access_t *pa = &phy->access; 2973 int rv = PHYMOD_E_NONE; 2974 2975 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 2976 config.device_aux_modes = &aux_mode; 2977 SESTO_IF_ERR_RETURN( 2978 _sesto_phy_interface_config_get(phy, 0, &config)); 2979 SESTO_GET_IP(phy, config, ip); 2980 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 2981 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 2982 2983 PHYMOD_DEBUG_VERBOSE(("sesto looopback set\n")); 2984 do { 2985 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data); 2986 } while ((data != 0) && (retry_cnt --)); 2987 if (retry_cnt == 0) { 2988 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 2989 (_PHYMOD_MSG("loopback config failed, micro controller is busy.."))); 2990 } 2991 /*Work around for loopback call without enable loopback */ 2992 SESTO_IF_ERR_RETURN( 2993 _sesto_loopback_get(phy, loopback, &temp)); 2994 2995 if(enable || temp) { 2996 if (ip == SESTO_FALCON_CORE) { 2997 /* FALCON core loopback set */ 2998 SESTO_IF_ERR_RETURN( 2999 _sesto_falcon_lpbk_set(phy, &config, loopback, enable)); 3000 } else { 3001 /* MERLIN core loopback set */ 3002 SESTO_IF_ERR_RETURN( 3003 _sesto_merlin_lpbk_set(phy, &config, loopback, enable)); 3004 } 3005 3006 /* Set bit 13 in GPREG11 for loopback change */ 3007 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GPREG11, lpbk_change, 1); 3008 /* Clear any forces on Tx disables set by HW while disable */ 3009 SESTO_IF_ERR_RETURN(_sesto_if_ctrl_frc_tx_disable(phy, &config, enable)); 3010 3011 /* Set FW_ENABLE = 1 */ 3012 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, 1); 3013 do { 3014 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data); 3015 } while ((data != 0) && (retry_cnt --)); 3016 if (retry_cnt == 0) { 3017 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 3018 (_PHYMOD_MSG("loopback config failed, micro controller is busy.."))); 3019 } 3020 if (enable) { 3021 /* Clear any forces on Tx disables set by HW */ 3022 SESTO_IF_ERR_RETURN(_sesto_if_ctrl_frc_tx_disable(phy, &config, enable)); 3023 3024 if (ip == SESTO_FALCON_CORE) { 3025 /* FALCON core loopback set */ 3026 SESTO_IF_ERR_RETURN( 3027 _sesto_falcon_lpbk_set(phy, &config, loopback, enable)); 3028 } else { 3029 /* MERLIN core loopback set */ 3030 SESTO_IF_ERR_RETURN( 3031 _sesto_merlin_lpbk_set(phy, &config, loopback, enable)); 3032 } 3033 } 3034 } 3035 3036 ERR: 3037 return rv; 3038 } 3039 3040 int _sesto_tx_rx_polarity_set(const phymod_phy_access_t *phy, uint32_t tx_polarity, uint32_t rx_polarity) 3041 { 3042 phymod_phy_inf_config_t config; 3043 uint16_t ip = 0; 3044 uint16_t lane = 0; 3045 uint16_t lane_mask = 0, max_lane = 0; 3046 const phymod_access_t *pa = &phy->access; 3047 int rv = PHYMOD_E_NONE; 3048 3049 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3050 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3051 SESTO_IF_ERR_RETURN( 3052 _sesto_phy_interface_config_get(phy, 0, &config)); 3053 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3054 SESTO_GET_IP(phy, config, ip); 3055 3056 max_lane = (ip == SESTO_FALCON_CORE) ? 3057 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3058 3059 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3060 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3061 3062 for (lane = 0; lane < max_lane; lane ++) { 3063 if (lane_mask & (1 << lane)) { 3064 SESTO_IF_ERR_RETURN( 3065 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3066 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3067 if (ip == SESTO_FALCON_CORE) { 3068 /* FALCON polarity inversion */ 3069 PHYMOD_DEBUG_VERBOSE(("Falcon polarity inversion set\n")); 3070 /* Write to Tx misc config register */ 3071 SESTO_CHIP_FIELD_WRITE(pa, F25G_TLB_TX_TLB_TX_MISC_CONFIG, 3072 tx_pmd_dp_invert, tx_polarity); 3073 /* Write to Rx misc config register */ 3074 SESTO_CHIP_FIELD_WRITE(pa, F25G_TLB_RX_TLB_RX_MISC_CONFIG, 3075 rx_pmd_dp_invert, rx_polarity); 3076 } else { 3077 /* MERLIN polarity inversion */ 3078 PHYMOD_DEBUG_VERBOSE(("Merlin polarity inversion set\n")); 3079 /* Write to Tx misc config register */ 3080 SESTO_CHIP_FIELD_WRITE(pa, M10G_TLB_TX_TLB_TX_MISC_CONFIG, 3081 tx_pmd_dp_invert, tx_polarity); 3082 /* Write to Rx misc config register */ 3083 SESTO_CHIP_FIELD_WRITE(pa, M10G_TLB_RX_TLB_RX_MISC_CONFIG, 3084 rx_pmd_dp_invert, rx_polarity); 3085 } 3086 } 3087 } 3088 3089 ERR: 3090 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3091 PHYMOD_FREE(config.device_aux_modes); 3092 3093 return rv; 3094 } 3095 3096 int _sesto_tx_rx_polarity_get(const phymod_phy_access_t *phy, uint32_t *tx_polarity, uint32_t *rx_polarity) 3097 { 3098 phymod_phy_inf_config_t config; 3099 uint16_t ip = 0; 3100 uint16_t lane = 0; 3101 uint16_t lane_mask = 0, max_lane = 0; 3102 const phymod_access_t *pa = &phy->access; 3103 int rv = PHYMOD_E_NONE; 3104 3105 *tx_polarity = 1; 3106 *rx_polarity = 1; 3107 3108 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3109 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3110 SESTO_IF_ERR_RETURN( 3111 _sesto_phy_interface_config_get(phy, 0, &config)); 3112 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3113 SESTO_GET_IP(phy, config, ip); 3114 3115 max_lane = (ip == SESTO_FALCON_CORE) ? 3116 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3117 3118 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3119 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3120 3121 for (lane = 0; lane < max_lane; lane ++) { 3122 if (lane_mask & (1 << lane)) { 3123 SESTO_IF_ERR_RETURN( 3124 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3125 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3126 if (ip == SESTO_FALCON_CORE) { 3127 /* FALCON polarity */ 3128 PHYMOD_DEBUG_VERBOSE(("Falcon polarity get\n")); 3129 /* Read to Tx misc config register */ 3130 SESTO_CHIP_FIELD_READ(pa, F25G_TLB_TX_TLB_TX_MISC_CONFIG, 3131 tx_pmd_dp_invert, (*tx_polarity)); 3132 /* Read to Rx misc config register */ 3133 SESTO_CHIP_FIELD_READ(pa, F25G_TLB_RX_TLB_RX_MISC_CONFIG, 3134 rx_pmd_dp_invert, (*rx_polarity)); 3135 break; 3136 } else { 3137 /* MERLIN polarity */ 3138 PHYMOD_DEBUG_VERBOSE(("Merlin polarity get\n")); 3139 /* Read to Tx misc config register */ 3140 SESTO_CHIP_FIELD_READ(pa, M10G_TLB_TX_TLB_TX_MISC_CONFIG, 3141 tx_pmd_dp_invert, (*tx_polarity)); 3142 /* Read to Rx misc config register */ 3143 SESTO_CHIP_FIELD_READ(pa, M10G_TLB_RX_TLB_RX_MISC_CONFIG, 3144 rx_pmd_dp_invert, (*rx_polarity)); 3145 break; 3146 } 3147 } 3148 } 3149 3150 ERR: 3151 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3152 PHYMOD_FREE(config.device_aux_modes); 3153 3154 return rv; 3155 } 3156 3157 int _sesto_tx_set(const phymod_phy_access_t *phy, const phymod_tx_t* tx) 3158 { 3159 phymod_phy_inf_config_t config; 3160 uint16_t ip = 0; 3161 uint16_t lane = 0; 3162 uint16_t lane_mask = 0, max_lane = 0; 3163 const phymod_access_t *pa = &phy->access; 3164 int rv = PHYMOD_E_NONE; 3165 3166 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3167 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3168 SESTO_IF_ERR_RETURN( 3169 _sesto_phy_interface_config_get(phy, 0, &config)); 3170 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3171 SESTO_GET_IP(phy, config, ip); 3172 3173 max_lane = (ip == SESTO_FALCON_CORE) ? 3174 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3175 3176 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3177 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3178 3179 for (lane = 0; lane < max_lane; lane ++) { 3180 if (lane_mask & (1 << lane)) { 3181 SESTO_IF_ERR_RETURN( 3182 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3183 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3184 if (ip == SESTO_FALCON_CORE) { 3185 /* FALCON TXFIR */ 3186 PHYMOD_DEBUG_VERBOSE(("Falcon TXFIR set\n")); 3187 SESTO_IF_ERR_RETURN 3188 (falcon_furia_sesto_write_tx_afe(pa, TX_AFE_PRE, (int8_t)tx->pre)); 3189 SESTO_IF_ERR_RETURN 3190 (falcon_furia_sesto_write_tx_afe(pa, TX_AFE_MAIN, (int8_t)tx->main)); 3191 SESTO_IF_ERR_RETURN 3192 (falcon_furia_sesto_write_tx_afe(pa, TX_AFE_POST1, (int8_t)tx->post)); 3193 SESTO_IF_ERR_RETURN 3194 (falcon_furia_sesto_write_tx_afe(pa, TX_AFE_POST2, (int8_t)tx->post2)); 3195 SESTO_IF_ERR_RETURN 3196 (falcon_furia_sesto_write_tx_afe(pa, TX_AFE_POST3, (int8_t)tx->post3)); 3197 SESTO_IF_ERR_RETURN 3198 (falcon_furia_sesto_write_tx_afe(pa, TX_AFE_AMP, (int8_t)tx->amp)); 3199 } else { 3200 /* MERLIN TXFIR */ 3201 PHYMOD_DEBUG_VERBOSE(("Merlin TXFIR set\n")); 3202 SESTO_IF_ERR_RETURN 3203 (merlin_sesto_apply_txfir_cfg(pa, (int8_t)tx->pre, (int8_t)tx->main, (int8_t)tx->post, (int8_t)tx->post2)); 3204 } 3205 } 3206 } 3207 3208 ERR: 3209 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3210 PHYMOD_FREE(config.device_aux_modes); 3211 3212 return rv; 3213 } 3214 3215 int _sesto_tx_get(const phymod_phy_access_t *phy, phymod_tx_t* tx) 3216 { 3217 phymod_phy_inf_config_t config; 3218 uint16_t ip = 0; 3219 uint16_t lane = 0; 3220 uint16_t lane_mask = 0, max_lane = 0; 3221 const phymod_access_t *pa = &phy->access; 3222 int rv = PHYMOD_E_NONE; 3223 int8_t value = 0; 3224 3225 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3226 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3227 SESTO_IF_ERR_RETURN( 3228 _sesto_phy_interface_config_get(phy, 0, &config)); 3229 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3230 SESTO_GET_IP(phy, config, ip); 3231 3232 max_lane = (ip == SESTO_FALCON_CORE) ? 3233 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3234 3235 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3236 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3237 3238 for (lane = 0; lane < max_lane; lane ++) { 3239 if (lane_mask & (1 << lane)) { 3240 SESTO_IF_ERR_RETURN( 3241 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3242 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3243 if (ip == SESTO_FALCON_CORE) { 3244 /* FALCON TXFIR */ 3245 PHYMOD_DEBUG_VERBOSE(("Falcon TXFIR get\n")); 3246 SESTO_IF_ERR_RETURN 3247 (falcon_furia_sesto_read_tx_afe(pa, TX_AFE_PRE, &value)); 3248 tx->pre = value; 3249 SESTO_IF_ERR_RETURN 3250 (falcon_furia_sesto_read_tx_afe(pa, TX_AFE_MAIN, &value)); 3251 tx->main = value; 3252 SESTO_IF_ERR_RETURN 3253 (falcon_furia_sesto_read_tx_afe(pa, TX_AFE_POST1, &value)); 3254 tx->post = value; 3255 SESTO_IF_ERR_RETURN 3256 (falcon_furia_sesto_read_tx_afe(pa, TX_AFE_POST2, &value)); 3257 tx->post2 = value; 3258 SESTO_IF_ERR_RETURN 3259 (falcon_furia_sesto_read_tx_afe(pa, TX_AFE_POST3, &value)); 3260 tx->post3 = value; 3261 SESTO_IF_ERR_RETURN 3262 (falcon_furia_sesto_read_tx_afe(pa, TX_AFE_AMP, &value)); 3263 tx->amp = value; 3264 break; 3265 } else { 3266 /* MERLIN TXFIR */ 3267 PHYMOD_DEBUG_VERBOSE(("Merlin TXFIR get\n")); 3268 SESTO_IF_ERR_RETURN 3269 (merlin_sesto_read_tx_afe(pa, TX_AFE_PRE, &value)); 3270 tx->pre = value; 3271 SESTO_IF_ERR_RETURN 3272 (merlin_sesto_read_tx_afe(pa, TX_AFE_MAIN, &value)); 3273 tx->main = value; 3274 SESTO_IF_ERR_RETURN 3275 (merlin_sesto_read_tx_afe(pa, TX_AFE_POST1, &value)); 3276 tx->post = value; 3277 SESTO_IF_ERR_RETURN 3278 (merlin_sesto_read_tx_afe(pa, TX_AFE_POST2, &value)); 3279 tx->post2 = value; 3280 break; 3281 } 3282 } 3283 } 3284 3285 ERR: 3286 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3287 PHYMOD_FREE(config.device_aux_modes); 3288 3289 return rv; 3290 } 3291 3292 int _sesto_rx_set(const phymod_phy_access_t* phy, const phymod_rx_t* rx) 3293 { 3294 phymod_phy_inf_config_t config; 3295 uint16_t ip = 0; 3296 uint16_t lane = 0; 3297 uint16_t lane_mask = 0, max_lane = 0; 3298 uint16_t indx = 0; 3299 uint8_t MAX_MERLIN_DFES_TAPS = 5; 3300 const phymod_access_t *pa = &phy->access; 3301 int rv = PHYMOD_E_NONE; 3302 3303 3304 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3305 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3306 SESTO_IF_ERR_RETURN( 3307 _sesto_phy_interface_config_get(phy, 0, &config)); 3308 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3309 SESTO_GET_IP(phy, config, ip); 3310 3311 max_lane = (ip == SESTO_FALCON_CORE) ? 3312 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3313 3314 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3315 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3316 3317 for (lane = 0; lane < max_lane; lane ++) { 3318 if (lane_mask & (1 << lane)) { 3319 SESTO_IF_ERR_RETURN( 3320 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3321 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3322 if (ip == SESTO_FALCON_CORE) { 3323 /* FALCON RXFIR set */ 3324 PHYMOD_DEBUG_VERBOSE(("Falcon RXFIR set\n")); 3325 3326 /*params check*/ 3327 for (indx = 0 ; indx < PHYMOD_NUM_DFE_TAPS; indx++){ 3328 if(rx->dfe[indx].enable && (rx->num_of_dfe_taps > PHYMOD_NUM_DFE_TAPS)) { 3329 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal number of DFEs to set"))); 3330 } 3331 } 3332 3333 /*vga set*/ 3334 /* first stop the rx adaption */ 3335 SESTO_IF_ERR_RETURN(falcon_furia_sesto_stop_rx_adaptation(pa, 1)); 3336 if (rx->vga.enable) { 3337 SESTO_IF_ERR_RETURN(falcon_furia_sesto_write_rx_afe(pa, RX_AFE_VGA, rx->vga.value)); 3338 } 3339 /*dfe set*/ 3340 for (indx = 0 ; indx < PHYMOD_NUM_DFE_TAPS; indx++){ 3341 if(rx->dfe[indx].enable){ 3342 SESTO_IF_ERR_RETURN(falcon_furia_sesto_write_rx_afe(pa, RX_AFE_DFE1+indx, rx->dfe[indx].value)); 3343 } 3344 } 3345 3346 /*peaking filter set*/ 3347 if(rx->peaking_filter.enable){ 3348 SESTO_IF_ERR_RETURN(falcon_furia_sesto_write_rx_afe(pa, RX_AFE_PF, rx->peaking_filter.value)); 3349 } 3350 3351 if(rx->low_freq_peaking_filter.enable){ 3352 SESTO_IF_ERR_RETURN(falcon_furia_sesto_write_rx_afe(pa, RX_AFE_PF2, rx->low_freq_peaking_filter.value)); 3353 } 3354 } else { 3355 /* MERLIN RXFIR set*/ 3356 PHYMOD_DEBUG_VERBOSE(("Merlin RXFIR set\n")); 3357 3358 /*params check*/ 3359 for (indx = 0 ; indx < MAX_MERLIN_DFES_TAPS; indx++){ 3360 if(rx->dfe[indx].enable && (rx->num_of_dfe_taps > MAX_MERLIN_DFES_TAPS)) { 3361 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("illegal number of DFEs to set"))); 3362 } 3363 } 3364 3365 /* first stop the rx adaption */ 3366 SESTO_IF_ERR_RETURN(merlin_sesto_stop_rx_adaptation(pa, 1)); 3367 /*vga set*/ 3368 if (rx->vga.enable) { 3369 SESTO_IF_ERR_RETURN(merlin_sesto_write_rx_afe(pa, RX_AFE_VGA, rx->vga.value)); 3370 } 3371 /*dfe set*/ 3372 /* PHYMOD_NUM_DFE_TAPS are 14 but MERLING core has 5 only DFEs */ 3373 for (indx = 0 ; indx < MAX_MERLIN_DFES_TAPS; indx++){ 3374 if(rx->dfe[indx].enable){ 3375 SESTO_IF_ERR_RETURN(merlin_sesto_write_rx_afe(pa, RX_AFE_DFE1+indx, rx->dfe[indx].value)); 3376 } 3377 } 3378 3379 /*peaking filter set*/ 3380 if(rx->peaking_filter.enable){ 3381 SESTO_IF_ERR_RETURN(merlin_sesto_write_rx_afe(pa, RX_AFE_PF, rx->peaking_filter.value)); 3382 } 3383 3384 if(rx->low_freq_peaking_filter.enable){ 3385 SESTO_IF_ERR_RETURN(merlin_sesto_write_rx_afe(pa, RX_AFE_PF2, rx->low_freq_peaking_filter.value)); 3386 } 3387 } 3388 } 3389 } 3390 3391 ERR: 3392 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3393 PHYMOD_FREE(config.device_aux_modes); 3394 3395 return rv; 3396 } 3397 int _sesto_rx_adaptation_resume(const phymod_phy_access_t* phy) 3398 { 3399 phymod_phy_inf_config_t config; 3400 uint16_t ip = 0; 3401 uint16_t lane = 0; 3402 uint16_t lane_mask = 0, max_lane = 0; 3403 const phymod_access_t *pa = &phy->access; 3404 int rv = PHYMOD_E_NONE; 3405 3406 3407 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3408 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3409 SESTO_IF_ERR_RETURN( 3410 _sesto_phy_interface_config_get(phy, 0, &config)); 3411 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3412 SESTO_GET_IP(phy, config, ip); 3413 3414 max_lane = (ip == SESTO_FALCON_CORE) ? 3415 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3416 3417 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3418 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3419 3420 for (lane = 0; lane < max_lane; lane ++) { 3421 if (lane_mask & (1 << lane)) { 3422 SESTO_IF_ERR_RETURN( 3423 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3424 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3425 if (ip == SESTO_FALCON_CORE) { 3426 PHYMOD_DEBUG_VERBOSE(("Falcon RX RESUME set\n")); 3427 SESTO_IF_ERR_RETURN(falcon_furia_sesto_stop_rx_adaptation(pa, 0)); 3428 } else { 3429 PHYMOD_DEBUG_VERBOSE(("Merlin RX RESUME set\n")); 3430 SESTO_IF_ERR_RETURN(merlin_sesto_stop_rx_adaptation(pa, 0)); 3431 } 3432 } 3433 } 3434 3435 ERR: 3436 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3437 PHYMOD_FREE(config.device_aux_modes); 3438 3439 return rv; 3440 } 3441 3442 int _sesto_rx_get(const phymod_phy_access_t *phy, phymod_rx_t* rx) 3443 { 3444 phymod_phy_inf_config_t config; 3445 uint16_t ip = 0; 3446 uint16_t lane = 0; 3447 uint16_t indx = 0; 3448 int8_t dfe = 0; 3449 int8_t vga = 0; 3450 int8_t pf = 0; 3451 int8_t low_freq_pf = 0; 3452 uint32_t rx_adaptation; 3453 uint16_t lane_mask = 0, max_lane = 0; 3454 int8_t MAX_MERLIN_DFES_TAPS = 5; 3455 const phymod_access_t *pa = &phy->access; 3456 int rv = PHYMOD_E_NONE; 3457 3458 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3459 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3460 SESTO_IF_ERR_RETURN( 3461 _sesto_phy_interface_config_get(phy, 0, &config)); 3462 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3463 SESTO_GET_IP(phy, config, ip); 3464 3465 max_lane = (ip == SESTO_FALCON_CORE) ? 3466 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3467 3468 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3469 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3470 3471 for (lane = 0; lane < max_lane; lane ++) { 3472 if (lane_mask & (1 << lane)) { 3473 SESTO_IF_ERR_RETURN( 3474 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3475 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3476 if (ip == SESTO_FALCON_CORE) { 3477 /* FALCON RXFIR get */ 3478 PHYMOD_DEBUG_VERBOSE(("Falcon RXFIR get\n")); 3479 3480 rx_adaptation = PHYMOD_RX_ADAPTATION_ON_GET(rx); 3481 SESTO_IF_ERR_RETURN(falcon_furia_sesto_stop_rx_adaptation(&phy->access, 1)); 3482 3483 /*vga get*/ 3484 rx->num_of_dfe_taps = PHYMOD_NUM_DFE_TAPS; 3485 SESTO_IF_ERR_RETURN(falcon_furia_sesto_read_rx_afe(pa, RX_AFE_VGA, &vga)); 3486 rx->vga.value = vga; 3487 rx->vga.enable = 1; 3488 3489 /*dfe get*/ 3490 for (indx = 0 ; indx < PHYMOD_NUM_DFE_TAPS; indx++){ 3491 SESTO_IF_ERR_RETURN(falcon_furia_sesto_read_rx_afe(pa, (RX_AFE_DFE1+indx), &dfe)); 3492 rx->dfe[indx].value = dfe; 3493 rx->dfe[indx].enable = 1; 3494 } 3495 3496 /*peaking filter get*/ 3497 SESTO_IF_ERR_RETURN(falcon_furia_sesto_read_rx_afe(pa, RX_AFE_PF, &pf)); 3498 rx->peaking_filter.value = pf; 3499 rx->peaking_filter.enable = 1; 3500 SESTO_IF_ERR_RETURN(falcon_furia_sesto_read_rx_afe(pa, RX_AFE_PF2, &low_freq_pf)); 3501 rx->low_freq_peaking_filter.value = low_freq_pf; 3502 rx->low_freq_peaking_filter.enable = 1; 3503 3504 if (rx_adaptation) { 3505 SESTO_IF_ERR_RETURN(falcon_furia_sesto_stop_rx_adaptation(&phy->access, 0)); 3506 } 3507 3508 break; 3509 } else { 3510 /* MERLIN RXFIR get */ 3511 PHYMOD_DEBUG_VERBOSE(("Merlin RXFIR get\n")); 3512 3513 rx_adaptation = PHYMOD_RX_ADAPTATION_ON_GET(rx); 3514 SESTO_IF_ERR_RETURN(merlin_sesto_stop_rx_adaptation(&phy->access, 1)); 3515 3516 /*vga get*/ 3517 /* PHYMOD_NUM_DFE_TAPS are 14 but MERLING has only 5 DFEs */ 3518 rx->num_of_dfe_taps = MAX_MERLIN_DFES_TAPS; 3519 SESTO_IF_ERR_RETURN(merlin_sesto_read_rx_afe(pa, RX_AFE_VGA, &vga)); 3520 rx->vga.value = vga; 3521 rx->vga.enable = 1; 3522 3523 /*dfe get*/ 3524 for (indx = 0 ; indx < MAX_MERLIN_DFES_TAPS; indx++){ 3525 SESTO_IF_ERR_RETURN(merlin_sesto_read_rx_afe(pa, (RX_AFE_DFE1+indx), &dfe)); 3526 rx->dfe[indx].value = dfe; 3527 rx->dfe[indx].enable = 1; 3528 } 3529 3530 /*peaking filter get*/ 3531 SESTO_IF_ERR_RETURN(merlin_sesto_read_rx_afe(pa, RX_AFE_PF, &pf)); 3532 rx->peaking_filter.value = pf; 3533 rx->peaking_filter.enable = 1; 3534 SESTO_IF_ERR_RETURN(merlin_sesto_read_rx_afe(pa, RX_AFE_PF2, &low_freq_pf)); 3535 rx->low_freq_peaking_filter.value = low_freq_pf; 3536 rx->low_freq_peaking_filter.enable = 1; 3537 3538 if (rx_adaptation) { 3539 SESTO_IF_ERR_RETURN(merlin_sesto_stop_rx_adaptation(&phy->access, 0)); 3540 } 3541 3542 break; 3543 } 3544 } 3545 } 3546 3547 ERR: 3548 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3549 PHYMOD_FREE(config.device_aux_modes); 3550 3551 return rv; 3552 } 3553 int _sesto_falcon_phy_reset_set(const phymod_access_t *pa, const phymod_phy_reset_t* reset) 3554 { 3555 int rv = PHYMOD_E_NONE; 3556 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_TYPE_T pwrdwn_ctrl; 3557 3558 /* TX AFE Lane Reset */ 3559 switch (reset->tx) { 3560 /* In Reset */ 3561 case phymodResetDirectionIn: 3562 READ_SESTO_PMA_PMD_REG(pa, 3563 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3564 pwrdwn_ctrl.data); 3565 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 1; 3566 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3567 WRITE_SESTO_PMA_PMD_REG(pa, 3568 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3569 pwrdwn_ctrl.data); 3570 3571 break; 3572 /* Out Reset */ 3573 case phymodResetDirectionOut: 3574 READ_SESTO_PMA_PMD_REG(pa, 3575 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3576 pwrdwn_ctrl.data); 3577 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 0; 3578 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3579 WRITE_SESTO_PMA_PMD_REG(pa, 3580 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3581 pwrdwn_ctrl.data); 3582 /* -- Releasing forces -- */ 3583 READ_SESTO_PMA_PMD_REG(pa, 3584 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3585 pwrdwn_ctrl.data); 3586 pwrdwn_ctrl.fields.afe_tx_reset_frc = 0; 3587 WRITE_SESTO_PMA_PMD_REG(pa, 3588 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3589 pwrdwn_ctrl.data); 3590 break; 3591 /* Toggle Reset */ 3592 case phymodResetDirectionInOut: 3593 READ_SESTO_PMA_PMD_REG(pa, 3594 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3595 pwrdwn_ctrl.data); 3596 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 1; 3597 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3598 WRITE_SESTO_PMA_PMD_REG(pa, 3599 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3600 pwrdwn_ctrl.data); 3601 PHYMOD_USLEEP(10); 3602 READ_SESTO_PMA_PMD_REG(pa, 3603 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3604 pwrdwn_ctrl.data); 3605 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 0; 3606 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3607 WRITE_SESTO_PMA_PMD_REG(pa, 3608 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3609 pwrdwn_ctrl.data); 3610 /* -- Releasing forces -- */ 3611 READ_SESTO_PMA_PMD_REG(pa, 3612 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3613 pwrdwn_ctrl.data); 3614 pwrdwn_ctrl.fields.afe_tx_reset_frc = 0; 3615 WRITE_SESTO_PMA_PMD_REG(pa, 3616 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3617 pwrdwn_ctrl.data); 3618 break; 3619 default: 3620 break; 3621 } 3622 /* RX AFE Lane Reset */ 3623 switch (reset->rx) { 3624 /* In Reset */ 3625 case phymodResetDirectionIn: 3626 READ_SESTO_PMA_PMD_REG(pa, 3627 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3628 pwrdwn_ctrl.data); 3629 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 1; 3630 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3631 WRITE_SESTO_PMA_PMD_REG(pa, 3632 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3633 pwrdwn_ctrl.data); 3634 3635 break; 3636 /* Out Reset */ 3637 case phymodResetDirectionOut: 3638 READ_SESTO_PMA_PMD_REG(pa, 3639 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3640 pwrdwn_ctrl.data); 3641 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 0; 3642 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3643 WRITE_SESTO_PMA_PMD_REG(pa, 3644 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3645 pwrdwn_ctrl.data); 3646 /* -- Releasing forces -- */ 3647 READ_SESTO_PMA_PMD_REG(pa, 3648 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3649 pwrdwn_ctrl.data); 3650 pwrdwn_ctrl.fields.afe_rx_reset_frc = 0; 3651 WRITE_SESTO_PMA_PMD_REG(pa, 3652 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3653 pwrdwn_ctrl.data); 3654 break; 3655 /* Toggle Reset */ 3656 case phymodResetDirectionInOut: 3657 READ_SESTO_PMA_PMD_REG(pa, 3658 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3659 pwrdwn_ctrl.data); 3660 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 1; 3661 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3662 WRITE_SESTO_PMA_PMD_REG(pa, 3663 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3664 pwrdwn_ctrl.data); 3665 PHYMOD_USLEEP(10); 3666 READ_SESTO_PMA_PMD_REG(pa, 3667 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3668 pwrdwn_ctrl.data); 3669 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 0; 3670 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3671 WRITE_SESTO_PMA_PMD_REG(pa, 3672 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3673 pwrdwn_ctrl.data); 3674 /* -- Releasing forces -- */ 3675 READ_SESTO_PMA_PMD_REG(pa, 3676 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3677 pwrdwn_ctrl.data); 3678 pwrdwn_ctrl.fields.afe_rx_reset_frc = 0; 3679 WRITE_SESTO_PMA_PMD_REG(pa, 3680 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3681 pwrdwn_ctrl.data); 3682 break; 3683 default: 3684 break; 3685 } 3686 3687 ERR: 3688 return rv; 3689 } 3690 3691 int _sesto_merlin_phy_reset_set(const phymod_access_t *pa, const phymod_phy_reset_t* reset) 3692 { 3693 int rv = PHYMOD_E_NONE; 3694 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_TYPE_T pwrdwn_ctrl; 3695 3696 /* TX AFE Lane Reset */ 3697 switch (reset->tx) { 3698 /* In Reset */ 3699 case phymodResetDirectionIn: 3700 READ_SESTO_PMA_PMD_REG(pa, 3701 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3702 pwrdwn_ctrl.data); 3703 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 1; 3704 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3705 WRITE_SESTO_PMA_PMD_REG(pa, 3706 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3707 pwrdwn_ctrl.data); 3708 3709 break; 3710 /* Out Reset */ 3711 case phymodResetDirectionOut: 3712 READ_SESTO_PMA_PMD_REG(pa, 3713 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3714 pwrdwn_ctrl.data); 3715 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 0; 3716 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3717 WRITE_SESTO_PMA_PMD_REG(pa, 3718 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3719 pwrdwn_ctrl.data); 3720 /* -- Releasing forces -- */ 3721 READ_SESTO_PMA_PMD_REG(pa, 3722 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3723 pwrdwn_ctrl.data); 3724 pwrdwn_ctrl.fields.afe_tx_reset_frc = 0; 3725 WRITE_SESTO_PMA_PMD_REG(pa, 3726 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3727 pwrdwn_ctrl.data); 3728 break; 3729 /* Toggle Reset */ 3730 case phymodResetDirectionInOut: 3731 READ_SESTO_PMA_PMD_REG(pa, 3732 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3733 pwrdwn_ctrl.data); 3734 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 1; 3735 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3736 WRITE_SESTO_PMA_PMD_REG(pa, 3737 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3738 pwrdwn_ctrl.data); 3739 PHYMOD_USLEEP(10); 3740 READ_SESTO_PMA_PMD_REG(pa, 3741 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3742 pwrdwn_ctrl.data); 3743 pwrdwn_ctrl.fields.afe_tx_reset_frc_val = 0; 3744 pwrdwn_ctrl.fields.afe_tx_reset_frc = 1; 3745 WRITE_SESTO_PMA_PMD_REG(pa, 3746 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3747 pwrdwn_ctrl.data); 3748 /* -- Releasing forces -- */ 3749 READ_SESTO_PMA_PMD_REG(pa, 3750 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3751 pwrdwn_ctrl.data); 3752 pwrdwn_ctrl.fields.afe_tx_reset_frc = 0; 3753 WRITE_SESTO_PMA_PMD_REG(pa, 3754 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3755 pwrdwn_ctrl.data); 3756 break; 3757 default: 3758 break; 3759 } 3760 3761 /* RX AFE Lane Reset */ 3762 switch (reset->rx) { 3763 /* In Reset */ 3764 case phymodResetDirectionIn: 3765 READ_SESTO_PMA_PMD_REG(pa, 3766 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3767 pwrdwn_ctrl.data); 3768 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 1; 3769 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3770 WRITE_SESTO_PMA_PMD_REG(pa, 3771 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3772 pwrdwn_ctrl.data); 3773 break; 3774 /* Out Reset */ 3775 case phymodResetDirectionOut: 3776 READ_SESTO_PMA_PMD_REG(pa, 3777 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3778 pwrdwn_ctrl.data); 3779 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 0; 3780 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3781 WRITE_SESTO_PMA_PMD_REG(pa, 3782 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3783 pwrdwn_ctrl.data); 3784 /* -- Releasing forces -- */ 3785 READ_SESTO_PMA_PMD_REG(pa, 3786 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3787 pwrdwn_ctrl.data); 3788 pwrdwn_ctrl.fields.afe_rx_reset_frc = 0; 3789 WRITE_SESTO_PMA_PMD_REG(pa, 3790 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3791 pwrdwn_ctrl.data); 3792 break; 3793 /* Toggle Reset */ 3794 case phymodResetDirectionInOut: 3795 READ_SESTO_PMA_PMD_REG(pa, 3796 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3797 pwrdwn_ctrl.data); 3798 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 1; 3799 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3800 WRITE_SESTO_PMA_PMD_REG(pa, 3801 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3802 pwrdwn_ctrl.data); 3803 PHYMOD_USLEEP(10); 3804 READ_SESTO_PMA_PMD_REG(pa, 3805 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3806 pwrdwn_ctrl.data); 3807 pwrdwn_ctrl.fields.afe_rx_reset_frc_val = 0; 3808 pwrdwn_ctrl.fields.afe_rx_reset_frc = 1; 3809 WRITE_SESTO_PMA_PMD_REG(pa, 3810 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3811 pwrdwn_ctrl.data); 3812 /* -- Releasing forces -- */ 3813 READ_SESTO_PMA_PMD_REG(pa, 3814 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3815 pwrdwn_ctrl.data); 3816 pwrdwn_ctrl.fields.afe_rx_reset_frc = 0; 3817 WRITE_SESTO_PMA_PMD_REG(pa, 3818 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL_ADR, 3819 pwrdwn_ctrl.data); 3820 break; 3821 default: 3822 break; 3823 } 3824 3825 ERR: 3826 return rv; 3827 } 3828 int _sesto_phy_reset_set(const phymod_phy_access_t *phy, const phymod_phy_reset_t* reset) 3829 { 3830 phymod_phy_inf_config_t config; 3831 uint16_t ip = 0; 3832 uint16_t lane = 0; 3833 uint16_t lane_mask = 0, max_lane = 0; 3834 const phymod_access_t *pa = &phy->access; 3835 int rv = PHYMOD_E_NONE; 3836 3837 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3838 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3839 SESTO_IF_ERR_RETURN( 3840 _sesto_phy_interface_config_get(phy, 0, &config)); 3841 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3842 SESTO_GET_IP(phy, config, ip); 3843 3844 max_lane = (ip == SESTO_FALCON_CORE) ? 3845 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3846 3847 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3848 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3849 3850 3851 for (lane = 0; lane < max_lane; lane ++) { 3852 if (lane_mask & (1 << lane)) { 3853 SESTO_IF_ERR_RETURN( 3854 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3855 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3856 if (ip == SESTO_FALCON_CORE) { 3857 /* FALCON TX/RX Reset */ 3858 PHYMOD_DEBUG_VERBOSE(("Falcon TX/RX Reset set\n")); 3859 SESTO_IF_ERR_RETURN( 3860 _sesto_falcon_phy_reset_set(pa, reset)); 3861 } else { 3862 /* MERLIN TX/RX Reset */ 3863 PHYMOD_DEBUG_VERBOSE(("Merlin TX/RX Reset set\n")); 3864 SESTO_IF_ERR_RETURN( 3865 _sesto_merlin_phy_reset_set(pa, reset)); 3866 } 3867 } 3868 } 3869 3870 ERR: 3871 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3872 PHYMOD_FREE(config.device_aux_modes); 3873 3874 return rv; 3875 } 3876 int _sesto_phy_reset_get(const phymod_phy_access_t *phy, phymod_phy_reset_t* reset) 3877 { 3878 phymod_phy_inf_config_t config; 3879 uint16_t ip = 0; 3880 uint16_t rst = 0; 3881 uint16_t lane = 0; 3882 uint16_t lane_mask = 0, max_lane = 0; 3883 const phymod_access_t *pa = &phy->access; 3884 int rv = PHYMOD_E_NONE; 3885 3886 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3887 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3888 SESTO_IF_ERR_RETURN( 3889 _sesto_phy_interface_config_get(phy, 0, &config)); 3890 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3891 SESTO_GET_IP(phy, config, ip); 3892 3893 max_lane = (ip == SESTO_FALCON_CORE) ? 3894 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 3895 3896 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 3897 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 3898 3899 3900 for (lane = 0; lane < max_lane; lane ++) { 3901 if (lane_mask & (1 << lane)) { 3902 SESTO_IF_ERR_RETURN( 3903 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 3904 ip, SESTO_DEV_PMA_PMD, 0, lane)); 3905 if (ip == SESTO_FALCON_CORE) { 3906 /* FALCON TX/RX Reset */ 3907 PHYMOD_DEBUG_VERBOSE(("Falcon TX/RX Reset get\n")); 3908 SESTO_CHIP_FIELD_READ(pa, 3909 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL, 3910 afe_tx_reset_frc_val, rst); 3911 if(rst == 0) { 3912 /* Out of Reset */ 3913 reset->tx = phymodResetDirectionOut; 3914 } else { 3915 /* In Reset */ 3916 reset->tx = phymodResetDirectionIn; 3917 } 3918 3919 SESTO_CHIP_FIELD_READ(pa, 3920 F25G_CKRST_CTRL_RPTR_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL, 3921 afe_rx_reset_frc_val, rst); 3922 if(rst == 0) { 3923 /* Out of Reset */ 3924 reset->rx = phymodResetDirectionOut; 3925 } else { 3926 /* In Reset */ 3927 reset->rx = phymodResetDirectionIn; 3928 } 3929 } else { 3930 /* MERLIN TX/RX Reset */ 3931 PHYMOD_DEBUG_VERBOSE(("Merlin TXF/RX Reset get\n")); 3932 SESTO_CHIP_FIELD_READ(pa, 3933 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL, 3934 afe_tx_reset_frc_val, rst); 3935 if(rst == 0) { 3936 /* Out of Reset */ 3937 reset->tx = phymodResetDirectionOut; 3938 } else { 3939 /* In Reset */ 3940 reset->tx = phymodResetDirectionIn; 3941 } 3942 3943 SESTO_CHIP_FIELD_READ(pa, 3944 M10G_CKRST_CTRL_LANE_AFE_RESET_PWRDWN_CONTROL_CONTROL, 3945 afe_rx_reset_frc_val, rst); 3946 if(rst == 0) { 3947 /* Out of Reset */ 3948 reset->rx = phymodResetDirectionOut; 3949 } else { 3950 /* In Reset */ 3951 reset->rx = phymodResetDirectionIn; 3952 } 3953 } 3954 } 3955 } 3956 3957 ERR: 3958 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 3959 PHYMOD_FREE(config.device_aux_modes); 3960 3961 return rv; 3962 } 3963 int _sesto_tx_power_set(const phymod_phy_access_t *phy, uint32_t power_tx) 3964 { 3965 phymod_phy_inf_config_t config; 3966 uint16_t ip = 0; 3967 uint16_t lane = 0; 3968 uint16_t lane_mask = 0; 3969 int rv = PHYMOD_E_NONE; 3970 const phymod_access_t *pa = &phy->access; 3971 MERLIN_IF_CONTROL2_LANE0_TYPE_T merlin_ctrl2_lane; 3972 FALCON_IF_CONTROL2_LANE0_TYPE_T falcon_ctrl2_lane; 3973 3974 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 3975 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 3976 SESTO_IF_ERR_RETURN( 3977 _sesto_phy_interface_config_get(phy, 0, &config)); 3978 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 3979 SESTO_GET_IP(phy, config, ip); 3980 3981 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s lanemask:0x%x\n", __func__, 3982 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", lane_mask)); 3983 3984 if (ip == SESTO_FALCON_CORE) { 3985 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 3986 if (lane_mask & (1 << lane)) { 3987 /* FALCON TX Power Set */ 3988 PHYMOD_DEBUG_VERBOSE(("Falcon TX Power set\n")); 3989 switch (power_tx) { 3990 case phymodPowerOff: /* Turn off power */ 3991 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 3992 falcon_ctrl2_lane.data); 3993 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 3994 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 1; 3995 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 3996 falcon_ctrl2_lane.data); 3997 break; 3998 case phymodPowerOn: /* Turn on power */ 3999 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4000 falcon_ctrl2_lane.data); 4001 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4002 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 0; 4003 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4004 falcon_ctrl2_lane.data); 4005 /* -- Releasing forces -- */ 4006 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4007 falcon_ctrl2_lane.data); 4008 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 0; 4009 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4010 falcon_ctrl2_lane.data); 4011 break; 4012 case phymodPowerOffOn: /* Toggle power */ 4013 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4014 falcon_ctrl2_lane.data); 4015 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4016 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 1; 4017 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4018 falcon_ctrl2_lane.data); 4019 PHYMOD_USLEEP(10000); 4020 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4021 falcon_ctrl2_lane.data); 4022 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4023 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 0; 4024 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4025 falcon_ctrl2_lane.data); 4026 /* -- Releasing forces -- */ 4027 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4028 falcon_ctrl2_lane.data); 4029 falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 0; 4030 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4031 falcon_ctrl2_lane.data); 4032 break; 4033 case phymodPowerNoChange: /* Stay where you are */ 4034 break; 4035 default: 4036 break; 4037 } 4038 } 4039 } 4040 } else { 4041 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 4042 if (lane_mask & (1 << lane)) { 4043 /* MERLIN TX Power set */ 4044 PHYMOD_DEBUG_VERBOSE(("Merlin TX Power set\n")); 4045 switch (power_tx) { 4046 case phymodPowerOff: /* Turn off power */ 4047 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4048 merlin_ctrl2_lane.data); 4049 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4050 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 1; 4051 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4052 merlin_ctrl2_lane.data); 4053 break; 4054 case phymodPowerOn: /* Turn on power */ 4055 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4056 merlin_ctrl2_lane.data); 4057 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4058 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 0; 4059 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4060 merlin_ctrl2_lane.data); 4061 /* -- Releasing forces -- */ 4062 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4063 merlin_ctrl2_lane.data); 4064 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 0; 4065 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4066 merlin_ctrl2_lane.data); 4067 break; 4068 case phymodPowerOffOn: /* Toggle power */ 4069 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4070 merlin_ctrl2_lane.data); 4071 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4072 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 1; 4073 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4074 merlin_ctrl2_lane.data); 4075 PHYMOD_USLEEP(10000); 4076 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4077 merlin_ctrl2_lane.data); 4078 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 1; 4079 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval = 0; 4080 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4081 merlin_ctrl2_lane.data); 4082 /* -- Releasing forces -- */ 4083 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4084 merlin_ctrl2_lane.data); 4085 merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frc = 0; 4086 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4087 merlin_ctrl2_lane.data); 4088 break; 4089 case phymodPowerNoChange: /* Stay where you are */ 4090 break; 4091 default: 4092 break; 4093 } 4094 } 4095 } 4096 } 4097 4098 ERR: 4099 PHYMOD_FREE(config.device_aux_modes); 4100 4101 return rv; 4102 } 4103 int _sesto_rx_power_set(const phymod_phy_access_t *phy, uint32_t power_rx) 4104 { 4105 phymod_phy_inf_config_t config; 4106 uint16_t ip = 0; 4107 uint16_t lane = 0; 4108 uint16_t lane_mask = 0; 4109 int rv = PHYMOD_E_NONE; 4110 const phymod_access_t *pa = &phy->access; 4111 MERLIN_IF_CONTROL2_LANE0_TYPE_T merlin_ctrl2_lane; 4112 FALCON_IF_CONTROL2_LANE0_TYPE_T falcon_ctrl2_lane; 4113 4114 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4115 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4116 SESTO_IF_ERR_RETURN( 4117 _sesto_phy_interface_config_get(phy, 0, &config)); 4118 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4119 4120 SESTO_GET_IP(phy, config, ip); 4121 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 4122 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 4123 4124 if (ip == SESTO_FALCON_CORE) { 4125 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 4126 if (lane_mask & (1 << lane)) { 4127 /* FALCON RX Power Set */ 4128 PHYMOD_DEBUG_VERBOSE(("Falcon RX Power set\n")); 4129 switch (power_rx) { 4130 case phymodPowerOff: /* Turn off power */ 4131 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4132 falcon_ctrl2_lane.data); 4133 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4134 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 1; 4135 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4136 falcon_ctrl2_lane.data); 4137 break; 4138 case phymodPowerOn: /* Turn on power */ 4139 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4140 falcon_ctrl2_lane.data); 4141 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4142 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 0; 4143 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4144 falcon_ctrl2_lane.data); 4145 /* -- Releasing forces -- */ 4146 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4147 falcon_ctrl2_lane.data); 4148 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 0; 4149 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4150 falcon_ctrl2_lane.data); 4151 break; 4152 case phymodPowerOffOn: /* Toggle power */ 4153 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4154 falcon_ctrl2_lane.data); 4155 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4156 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 1; 4157 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4158 falcon_ctrl2_lane.data); 4159 PHYMOD_USLEEP(10000); 4160 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4161 falcon_ctrl2_lane.data); 4162 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4163 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 0; 4164 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4165 falcon_ctrl2_lane.data); 4166 /* -- Releasing forces -- */ 4167 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4168 falcon_ctrl2_lane.data); 4169 falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 0; 4170 WRITE_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4171 falcon_ctrl2_lane.data); 4172 break; 4173 case phymodPowerNoChange: /* Stay where you are */ 4174 break; 4175 default: 4176 break; 4177 } 4178 } 4179 } 4180 } else { 4181 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 4182 if (lane_mask & (1 << lane)) { 4183 /* MERLIN RX Power set */ 4184 PHYMOD_DEBUG_VERBOSE(("Merlin RX Power set\n")); 4185 switch (power_rx) { 4186 case phymodPowerOff: /* Turn off power */ 4187 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4188 merlin_ctrl2_lane.data); 4189 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4190 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 1; 4191 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4192 merlin_ctrl2_lane.data); 4193 break; 4194 case phymodPowerOn: /* Turn on power */ 4195 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4196 merlin_ctrl2_lane.data); 4197 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4198 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 0; 4199 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4200 merlin_ctrl2_lane.data); 4201 /* -- Releasing forces -- */ 4202 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4203 merlin_ctrl2_lane.data); 4204 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 0; 4205 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4206 merlin_ctrl2_lane.data); 4207 break; 4208 case phymodPowerOffOn: /* Toggle power */ 4209 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4210 merlin_ctrl2_lane.data); 4211 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4212 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 1; 4213 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4214 merlin_ctrl2_lane.data); 4215 PHYMOD_USLEEP(10000); 4216 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4217 merlin_ctrl2_lane.data); 4218 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 1; 4219 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval = 0; 4220 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4221 merlin_ctrl2_lane.data); 4222 /* -- Releasing forces -- */ 4223 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4224 merlin_ctrl2_lane.data); 4225 merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frc = 0; 4226 WRITE_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4227 merlin_ctrl2_lane.data); 4228 break; 4229 case phymodPowerNoChange: /* Stay where you are */ 4230 break; 4231 default: 4232 break; 4233 } 4234 } 4235 } 4236 } 4237 4238 ERR: 4239 PHYMOD_FREE(config.device_aux_modes); 4240 4241 return rv; 4242 } 4243 4244 int _sesto_tx_rx_power_get(const phymod_phy_access_t *phy, phymod_phy_power_t* power) 4245 { 4246 phymod_phy_inf_config_t config; 4247 uint16_t ip = 0; 4248 uint16_t lane = 0; 4249 uint16_t lane_mask = 0, max_lane = 0; 4250 int rv = PHYMOD_E_NONE; 4251 const phymod_access_t *pa = &phy->access; 4252 MERLIN_IF_CONTROL2_LANE0_TYPE_T merlin_ctrl2_lane; 4253 FALCON_IF_CONTROL2_LANE0_TYPE_T falcon_ctrl2_lane; 4254 4255 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4256 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4257 SESTO_IF_ERR_RETURN( 4258 _sesto_phy_interface_config_get(phy, 0, &config)); 4259 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4260 SESTO_GET_IP(phy, config, ip); 4261 4262 max_lane = (ip == SESTO_FALCON_CORE) ? 4263 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4264 4265 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4266 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4267 4268 for (lane = 0; lane < max_lane; lane ++) { 4269 if (lane_mask & (1 << lane)) { 4270 if (ip == SESTO_FALCON_CORE) { 4271 /* FALCON TX/RX Power Get */ 4272 PHYMOD_DEBUG_VERBOSE(("Falcon TX/RX Power get\n")); 4273 READ_SESTO_PMA_PMD_REG(pa, (FALCON_IF_CONTROL2_LANE0_ADR + lane), 4274 falcon_ctrl2_lane.data); 4275 power->tx = !falcon_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval; 4276 power->rx = !falcon_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval; 4277 } else { 4278 /* MERLIN TX/RX Power Get */ 4279 PHYMOD_DEBUG_VERBOSE(("Merlin TX/RX Power get\n")); 4280 READ_SESTO_PMA_PMD_REG(pa, (MERLIN_IF_CONTROL2_LANE0_ADR + lane), 4281 merlin_ctrl2_lane.data); 4282 power->tx = !merlin_ctrl2_lane.fields.pmd_ln_tx_h_pwrdn_0_frcval; 4283 power->rx = !merlin_ctrl2_lane.fields.pmd_ln_rx_h_pwrdn_0_frcval; 4284 } 4285 } 4286 } 4287 4288 ERR: 4289 PHYMOD_FREE(config.device_aux_modes); 4290 4291 return rv; 4292 } 4293 4294 int _sesto_force_tx_training_set(const phymod_phy_access_t *phy, uint32_t enable) 4295 { 4296 phymod_phy_inf_config_t config; 4297 uint16_t ip = 0; 4298 uint16_t lane = 0; 4299 uint16_t lane_mask = 0, max_lane = 0; 4300 uint16_t data = 0, retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 4301 const phymod_access_t *pa = &phy->access; 4302 int rv = PHYMOD_E_NONE; 4303 4304 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4305 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4306 SESTO_IF_ERR_RETURN( 4307 _sesto_phy_interface_config_get(phy, 0, &config)); 4308 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4309 SESTO_GET_IP(phy, config, ip); 4310 4311 max_lane = (ip == SESTO_FALCON_CORE) ? 4312 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4313 4314 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4315 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4316 4317 for (lane = 0; lane < max_lane; lane ++) { 4318 if (lane_mask & (1 << lane)) { 4319 if (ip == SESTO_FALCON_CORE) { /* Falcon TX Training set on GPREG13 Regs */ 4320 PHYMOD_DEBUG_VERBOSE(("Falcon TX Training set\n")); 4321 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_GPREG13, tx_trng_20g_ln, data); 4322 enable ? (data |= (0x1 << lane)): (data &= (~(0x1 << lane))); 4323 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GPREG13, tx_trng_20g_ln, data); 4324 } else { /* Merlin TX Training set on GPREG12 Regs */ 4325 PHYMOD_DEBUG_VERBOSE(("Merlin TX Training set\n")); 4326 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_GPREG12, tx_trng_10g_ln, data); 4327 enable ? (data |= (0x1 << lane)): (data &= (~(0x1 << lane))); 4328 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GPREG12, tx_trng_10g_ln, data); 4329 } 4330 } 4331 } 4332 4333 /* Set FW_ENABLE = 1 */ 4334 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, 1); 4335 do { 4336 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data); 4337 retry_cnt--; 4338 } while ((data != 0) && (retry_cnt)); 4339 if (retry_cnt == 0) { 4340 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 4341 (_PHYMOD_MSG("Training set failed, micro controller is busy.."))); 4342 } 4343 4344 ERR: 4345 PHYMOD_FREE(config.device_aux_modes); 4346 4347 return rv; 4348 } 4349 4350 int _sesto_force_tx_training_get(const phymod_phy_access_t *phy, uint32_t *enable) 4351 { 4352 phymod_phy_inf_config_t config; 4353 uint16_t ip = 0; 4354 uint16_t lane = 0; 4355 uint16_t lane_mask = 0, max_lane = 0; 4356 uint16_t training_en = 0; 4357 const phymod_access_t *pa = &phy->access; 4358 int rv = PHYMOD_E_NONE; 4359 4360 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4361 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4362 SESTO_IF_ERR_RETURN( 4363 _sesto_phy_interface_config_get(phy, 0, &config)); 4364 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4365 SESTO_GET_IP(phy, config, ip); 4366 4367 max_lane = (ip == SESTO_FALCON_CORE) ? 4368 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4369 4370 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4371 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4372 4373 for (lane = 0; lane < max_lane; lane ++) { 4374 if (lane_mask & (1 << lane)) { 4375 if (ip == SESTO_FALCON_CORE) { /* Falcon TX Training get on GPREG13 Regs */ 4376 PHYMOD_DEBUG_VERBOSE(("Falcon TX Training get\n")); 4377 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_GPREG13, tx_trng_20g_ln, training_en); 4378 *enable = ((training_en >> lane) & 0x1); 4379 } else { /* Merlin TX Training get on GPREG12 Regs */ 4380 PHYMOD_DEBUG_VERBOSE(("Merlin TX Training get\n")); 4381 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_GPREG12, tx_trng_10g_ln, training_en); 4382 *enable = ((training_en >> lane) & 0x1); 4383 } 4384 } 4385 } 4386 4387 ERR: 4388 PHYMOD_FREE(config.device_aux_modes); 4389 4390 return rv; 4391 } 4392 4393 int _sesto_force_tx_training_status_get(const phymod_phy_access_t *phy, phymod_cl72_status_t* status) 4394 { 4395 phymod_phy_inf_config_t config; 4396 uint16_t ip = 0; 4397 uint16_t lane = 0; 4398 uint16_t lane_mask = 0, max_lane = 0; 4399 uint16_t training_en = 0; 4400 uint16_t training_failure = 1; 4401 uint16_t trained = 1; 4402 const phymod_access_t *pa = &phy->access; 4403 int rv = PHYMOD_E_NONE; 4404 4405 status->enabled = 0x1; 4406 status->locked = 0x1; 4407 4408 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4409 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4410 SESTO_IF_ERR_RETURN( 4411 _sesto_phy_interface_config_get(phy, 0, &config)); 4412 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4413 SESTO_GET_IP(phy, config, ip); 4414 4415 max_lane = (ip == SESTO_FALCON_CORE) ? 4416 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4417 4418 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4419 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4420 4421 for (lane = 0; lane < max_lane; lane ++) { 4422 if (lane_mask & (1 << lane)) { 4423 SESTO_IF_ERR_RETURN( 4424 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4425 ip, SESTO_DEV_PMA_PMD, 0, lane)); 4426 if (ip == SESTO_FALCON_CORE) { /* Falcon TX Training status Reading from IEEE Regs */ 4427 PHYMOD_DEBUG_VERBOSE(("Falcon TX Training Status get\n")); 4428 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_GPREG13, tx_trng_20g_ln, training_en); 4429 status->enabled &= ((training_en >> lane) & 0x1); 4430 SESTO_CHIP_FIELD_READ(pa, F25G_CL93N72_IEEE_TX_CL93N72IT_BASE_R_PMD_STATUS_REGISTER_151, 4431 cl93n72_ieee_receiver_status, trained); 4432 SESTO_CHIP_FIELD_READ(pa, F25G_CL93N72_IEEE_TX_CL93N72IT_BASE_R_PMD_STATUS_REGISTER_151, 4433 cl93n72_ieee_training_failure, training_failure); 4434 status->locked &= ((!training_failure) && (trained)); 4435 } else { /* Merlin TX Training status Reading from IEEE Regs */ 4436 PHYMOD_DEBUG_VERBOSE(("Merlin TX Training Status get\n")); 4437 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_GPREG12, tx_trng_10g_ln, training_en); 4438 status->enabled &= ((training_en >> lane) & 0x1); 4439 SESTO_CHIP_FIELD_READ(pa, M10G_CL72_IEEE_TX_BASE_R_PMD_STATUS_REGISTER_151, 4440 receiver_status, trained); 4441 SESTO_CHIP_FIELD_READ(pa, M10G_CL72_IEEE_TX_BASE_R_PMD_STATUS_REGISTER_151, 4442 training_failure, training_failure); 4443 status->locked &= ((!training_failure) && (trained)); 4444 } 4445 } 4446 } 4447 4448 ERR: 4449 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 4450 PHYMOD_FREE(config.device_aux_modes); 4451 4452 return rv; 4453 } 4454 int _sesto_phy_status_dump(const phymod_phy_access_t *phy) 4455 { 4456 phymod_phy_inf_config_t config; 4457 uint16_t ip = 0, intf_side = 0; 4458 uint16_t lane = 0, lane_mask = 0; 4459 const phymod_access_t *pa = &phy->access; 4460 int rv = PHYMOD_E_NONE; 4461 4462 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4463 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4464 SESTO_IF_ERR_RETURN( 4465 _sesto_phy_interface_config_get(phy, 0, &config)); 4466 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4467 SESTO_GET_IP(phy, config, ip); 4468 SESTO_GET_INTF_SIDE(phy, intf_side); 4469 4470 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s lanemask:0x%x\n", __func__, 4471 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", lane_mask)); 4472 4473 USR_PRINTF(("**********************************************\n")); 4474 USR_PRINTF(("******* PHY status dump for PHY ID: 0x%x ********\n",pa->addr)); 4475 USR_PRINTF(("**********************************************\n")); 4476 USR_PRINTF(("**** PHY status dump for interface side:%d ****\n",intf_side)); 4477 USR_PRINTF(("***********************************************\n")); 4478 if (ip == SESTO_FALCON_CORE) { /* Falcon core status dump */ 4479 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 4480 if (lane_mask & (1 << lane)) { 4481 SESTO_IF_ERR_RETURN( 4482 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4483 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 0, lane)); 4484 SESTO_IF_ERR_RETURN(falcon_furia_sesto_display_core_config(pa)); 4485 SESTO_IF_ERR_RETURN(falcon_furia_sesto_display_core_state(pa)); 4486 break; 4487 } 4488 } 4489 } else { /* Merlin core status dump */ 4490 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 4491 if (lane_mask & (1 << lane)) { 4492 SESTO_IF_ERR_RETURN( 4493 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4494 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 0, lane)); 4495 SESTO_IF_ERR_RETURN(merlin_sesto_display_core_config(pa)); 4496 SESTO_IF_ERR_RETURN(merlin_sesto_display_core_state(pa)); 4497 break; 4498 } 4499 } 4500 } 4501 if (ip == SESTO_FALCON_CORE) { /* Falcon lanes status dump */ 4502 for(lane = 0; lane < SESTO_MAX_FALCON_LANE; lane ++) { 4503 if (lane_mask & (1 << lane)) { 4504 SESTO_IF_ERR_RETURN( 4505 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4506 SESTO_FALCON_CORE, SESTO_DEV_PMA_PMD, 4507 0, lane)); 4508 PHYMOD_DEBUG_VERBOSE(("Falcon Status dump\n")); 4509 SESTO_IF_ERR_RETURN(falcon_furia_sesto_display_lane_state_hdr(pa)); 4510 SESTO_IF_ERR_RETURN(falcon_furia_sesto_display_lane_state(pa)); 4511 SESTO_IF_ERR_RETURN(falcon_furia_sesto_display_lane_config(pa)); 4512 } 4513 } 4514 } else { /* Merlin lanes status dump */ 4515 for(lane = 0; lane < SESTO_MAX_MERLIN_LANE; lane ++) { 4516 if (lane_mask & (1 << lane)) { 4517 SESTO_IF_ERR_RETURN( 4518 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4519 SESTO_MERLIN_CORE, SESTO_DEV_PMA_PMD, 4520 0, lane)); 4521 PHYMOD_DEBUG_VERBOSE(("Merlin Status dump\n")); 4522 SESTO_IF_ERR_RETURN(merlin_sesto_display_lane_state_hdr(pa)); 4523 SESTO_IF_ERR_RETURN(merlin_sesto_display_lane_state(pa)); 4524 SESTO_IF_ERR_RETURN(merlin_sesto_display_lane_config(pa)); 4525 } 4526 } 4527 } 4528 4529 ERR: 4530 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 4531 PHYMOD_FREE(config.device_aux_modes); 4532 4533 return rv; 4534 } 4535 4536 int _sesto_tx_enable_set(const phymod_phy_access_t *phy, int16_t enable) 4537 { 4538 phymod_phy_inf_config_t config; 4539 uint16_t ip = 0; 4540 uint16_t lane = 0, max_lane = 0, reg_addr = 0; 4541 uint16_t lane_mask = 0; 4542 int rv = PHYMOD_E_NONE; 4543 const phymod_access_t *pa = &phy->access; 4544 MERLIN_IF_CONTROL1_LANE0_TYPE_T mer_ctrl1; 4545 FALCON_IF_CONTROL1_LANE0_TYPE_T fal_ctrl1; 4546 4547 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4548 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4549 SESTO_IF_ERR_RETURN( 4550 _sesto_phy_interface_config_get(phy, 0, &config)); 4551 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4552 SESTO_GET_IP(phy, config, ip); 4553 4554 max_lane = (ip == SESTO_FALCON_CORE) ? 4555 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4556 4557 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4558 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4559 4560 /* TX squelch set with pmd_tx_disable_0_frcval */ 4561 for (lane = 0; lane < max_lane; lane ++) { 4562 if (lane_mask & (1 << lane)) { 4563 if (ip == SESTO_FALCON_CORE) { 4564 reg_addr = FALCON_IF_CONTROL1_LANE0_ADR + lane; 4565 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fal_ctrl1.data); 4566 fal_ctrl1.fields.pmd_tx_disable_0_frc = 1; 4567 fal_ctrl1.fields.pmd_tx_disable_0_frcval = (!enable); 4568 WRITE_SESTO_PMA_PMD_REG(pa, reg_addr, fal_ctrl1.data); 4569 /* -- Releasing forces -- */ 4570 if (enable) { 4571 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fal_ctrl1.data); 4572 fal_ctrl1.fields.pmd_tx_disable_0_frc = 0; 4573 WRITE_SESTO_PMA_PMD_REG(pa, reg_addr, fal_ctrl1.data); 4574 } 4575 } else { 4576 reg_addr = MERLIN_IF_CONTROL1_LANE0_ADR + lane; 4577 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mer_ctrl1.data); 4578 mer_ctrl1.fields.pmd_tx_disable_0_frc = 1; 4579 mer_ctrl1.fields.pmd_tx_disable_0_frcval = (!enable); 4580 WRITE_SESTO_PMA_PMD_REG(pa, reg_addr, mer_ctrl1.data); 4581 /* -- Releasing forces -- */ 4582 if (enable) { 4583 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mer_ctrl1.data); 4584 mer_ctrl1.fields.pmd_tx_disable_0_frc = 0; 4585 WRITE_SESTO_PMA_PMD_REG(pa, reg_addr, mer_ctrl1.data); 4586 } 4587 } 4588 } 4589 } 4590 4591 ERR: 4592 PHYMOD_FREE(config.device_aux_modes); 4593 4594 return rv; 4595 } 4596 4597 int _sesto_tx_enable_get(const phymod_phy_access_t *phy, int16_t *enable) 4598 { 4599 phymod_phy_inf_config_t config; 4600 uint16_t ip = 0; 4601 uint16_t lane = 0, max_lane = 0, reg_addr = 0; 4602 uint16_t lane_mask = 0; 4603 int rv = PHYMOD_E_NONE; 4604 const phymod_access_t *pa = &phy->access; 4605 MERLIN_IF_CONTROL1_LANE0_TYPE_T mer_ctrl1; 4606 FALCON_IF_CONTROL1_LANE0_TYPE_T fal_ctrl1; 4607 4608 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4609 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4610 SESTO_IF_ERR_RETURN( 4611 _sesto_phy_interface_config_get(phy, 0, &config)); 4612 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4613 SESTO_GET_IP(phy, config, ip); 4614 4615 max_lane = (ip == SESTO_FALCON_CORE) ? 4616 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4617 4618 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4619 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4620 4621 /* TX squelch get with pmd_tx_disable_0_frcval */ 4622 for (lane = 0; lane < max_lane; lane ++) { 4623 if (lane_mask & (1 << lane)) { 4624 if (ip == SESTO_FALCON_CORE) { 4625 reg_addr = FALCON_IF_CONTROL1_LANE0_ADR + lane; 4626 READ_SESTO_PMA_PMD_REG(pa, reg_addr, fal_ctrl1.data); 4627 *enable = !fal_ctrl1.fields.pmd_tx_disable_0_frcval; 4628 } else { 4629 reg_addr = MERLIN_IF_CONTROL1_LANE0_ADR + lane; 4630 READ_SESTO_PMA_PMD_REG(pa, reg_addr, mer_ctrl1.data); 4631 *enable = !mer_ctrl1.fields.pmd_tx_disable_0_frcval; 4632 } 4633 } 4634 } 4635 4636 ERR: 4637 PHYMOD_FREE(config.device_aux_modes); 4638 4639 return rv; 4640 } 4641 4642 4643 int _sesto_tx_dp_reset(const phymod_phy_access_t *phy) 4644 { 4645 phymod_phy_inf_config_t config; 4646 uint16_t ip = 0; 4647 uint16_t lane = 0, max_lane = 0; 4648 uint16_t lane_mask = 0; 4649 int rv = PHYMOD_E_NONE; 4650 const phymod_access_t *pa = &phy->access; 4651 DP_LANE_RESET_CONTROL0_TYPE_T dp_rst; 4652 4653 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4654 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4655 SESTO_IF_ERR_RETURN( 4656 _sesto_phy_interface_config_get(phy, 0, &config)); 4657 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4658 4659 SESTO_GET_IP(phy, config, ip); 4660 max_lane = (ip == SESTO_FALCON_CORE) ? 4661 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4662 4663 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4664 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4665 4666 /* Reset TX data path */ 4667 for (lane = 0; lane < max_lane; lane ++) { 4668 if (lane_mask & (1 << lane)) { 4669 READ_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4670 if (ip == SESTO_FALCON_CORE) { 4671 dp_rst.fields.demux_ilane_dp_rstb &= ~(1 << lane); 4672 } else { 4673 dp_rst.fields.mux_ilane_dp_rstb &= ~(1 << lane); 4674 } 4675 WRITE_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4676 PHYMOD_USLEEP(1000); 4677 READ_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4678 if (ip == SESTO_FALCON_CORE) { 4679 dp_rst.fields.demux_ilane_dp_rstb |= (1 << lane); 4680 } else { 4681 dp_rst.fields.mux_ilane_dp_rstb |= (1 << lane); 4682 } 4683 WRITE_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4684 4685 } 4686 } 4687 4688 ERR: 4689 PHYMOD_FREE(config.device_aux_modes); 4690 4691 return rv; 4692 } 4693 4694 int _sesto_rx_enable_set(const phymod_phy_access_t *phy, int16_t enable) 4695 { 4696 phymod_phy_inf_config_t config; 4697 uint16_t ip = 0; 4698 uint16_t lane = 0, max_lane = 0; 4699 uint16_t lane_mask = 0; 4700 int rv = PHYMOD_E_NONE; 4701 const phymod_access_t *pa = &phy->access; 4702 M10G_SIGDET_SIGDET_CTRL_1_TYPE_T merlin_ctrl1_lane; 4703 F25G_SIGDET_SIGDET_CTRL_1_TYPE_T falcon_ctrl1_lane; 4704 4705 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4706 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4707 SESTO_IF_ERR_RETURN( 4708 _sesto_phy_interface_config_get(phy, 0, &config)); 4709 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4710 SESTO_GET_IP(phy, config, ip); 4711 4712 max_lane = (ip == SESTO_FALCON_CORE) ? 4713 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4714 4715 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4716 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4717 4718 /* RX squelch set with signal_detect_frc_val */ 4719 for (lane = 0; lane < max_lane; lane ++) { 4720 if (lane_mask & (1 << lane)) { 4721 SESTO_IF_ERR_RETURN( 4722 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4723 ip, SESTO_DEV_PMA_PMD, 0, lane)); 4724 if (ip == SESTO_FALCON_CORE) { 4725 READ_SESTO_PMA_PMD_REG(pa, F25G_SIGDET_SIGDET_CTRL_1_ADR, falcon_ctrl1_lane.data); 4726 falcon_ctrl1_lane.fields.signal_detect_frc = 1; 4727 falcon_ctrl1_lane.fields.signal_detect_frc_val = enable; 4728 WRITE_SESTO_PMA_PMD_REG(pa, F25G_SIGDET_SIGDET_CTRL_1_ADR, falcon_ctrl1_lane.data); 4729 /* -- Releasing forces -- */ 4730 if (enable) { 4731 READ_SESTO_PMA_PMD_REG(pa, F25G_SIGDET_SIGDET_CTRL_1_ADR, falcon_ctrl1_lane.data); 4732 falcon_ctrl1_lane.fields.signal_detect_frc = 0; 4733 WRITE_SESTO_PMA_PMD_REG(pa, F25G_SIGDET_SIGDET_CTRL_1_ADR, falcon_ctrl1_lane.data); 4734 } 4735 } else { 4736 READ_SESTO_PMA_PMD_REG(pa, M10G_SIGDET_SIGDET_CTRL_1_ADR, merlin_ctrl1_lane.data); 4737 merlin_ctrl1_lane.fields.signal_detect_frc = 1; 4738 merlin_ctrl1_lane.fields.signal_detect_frc_val= enable; 4739 WRITE_SESTO_PMA_PMD_REG(pa, M10G_SIGDET_SIGDET_CTRL_1_ADR, merlin_ctrl1_lane.data); 4740 /* -- Releasing forces -- */ 4741 if (enable) { 4742 READ_SESTO_PMA_PMD_REG(pa, M10G_SIGDET_SIGDET_CTRL_1_ADR, merlin_ctrl1_lane.data); 4743 merlin_ctrl1_lane.fields.signal_detect_frc = 0; 4744 WRITE_SESTO_PMA_PMD_REG(pa, M10G_SIGDET_SIGDET_CTRL_1_ADR, merlin_ctrl1_lane.data); 4745 } 4746 } 4747 } 4748 } 4749 ERR: 4750 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 4751 PHYMOD_FREE(config.device_aux_modes); 4752 4753 return rv; 4754 } 4755 4756 int _sesto_rx_enable_get(const phymod_phy_access_t *phy, int16_t *enable) 4757 { 4758 phymod_phy_inf_config_t config; 4759 uint16_t ip = 0; 4760 uint16_t lane = 0, max_lane = 0; 4761 uint16_t lane_mask = 0; 4762 int rv = PHYMOD_E_NONE; 4763 const phymod_access_t *pa = &phy->access; 4764 M10G_SIGDET_SIGDET_CTRL_1_TYPE_T merlin_ctrl1_lane; 4765 F25G_SIGDET_SIGDET_CTRL_1_TYPE_T falcon_ctrl1_lane; 4766 4767 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4768 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4769 SESTO_IF_ERR_RETURN( 4770 _sesto_phy_interface_config_get(phy, 0, &config)); 4771 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4772 SESTO_GET_IP(phy, config, ip); 4773 4774 max_lane = (ip == SESTO_FALCON_CORE) ? 4775 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4776 4777 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4778 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4779 4780 /* RX squelch get with signal_detect_frc_val */ 4781 for (lane = 0; lane < max_lane; lane ++) { 4782 if (lane_mask & (1 << lane)) { 4783 SESTO_IF_ERR_RETURN( 4784 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 4785 ip, SESTO_DEV_PMA_PMD, 0, lane)); 4786 if (ip == SESTO_FALCON_CORE) { 4787 READ_SESTO_PMA_PMD_REG(pa, F25G_SIGDET_SIGDET_CTRL_1_ADR, falcon_ctrl1_lane.data); 4788 *enable = falcon_ctrl1_lane.fields.signal_detect_frc_val; 4789 } else { 4790 READ_SESTO_PMA_PMD_REG(pa, M10G_SIGDET_SIGDET_CTRL_1_ADR, merlin_ctrl1_lane.data); 4791 *enable = merlin_ctrl1_lane.fields.signal_detect_frc_val; 4792 } 4793 } 4794 } 4795 4796 ERR: 4797 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 4798 PHYMOD_FREE(config.device_aux_modes); 4799 4800 return rv; 4801 } 4802 4803 int _sesto_rx_dp_reset(const phymod_phy_access_t *phy) 4804 { 4805 phymod_phy_inf_config_t config; 4806 uint16_t ip = 0; 4807 uint16_t lane = 0, max_lane = 0; 4808 uint16_t lane_mask = 0; 4809 int rv = PHYMOD_E_NONE; 4810 const phymod_access_t *pa = &phy->access; 4811 DP_LANE_RESET_CONTROL0_TYPE_T dp_rst; 4812 4813 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4814 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4815 SESTO_IF_ERR_RETURN( 4816 _sesto_phy_interface_config_get(phy, 0, &config)); 4817 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4818 4819 SESTO_GET_IP(phy, config, ip); 4820 max_lane = (ip == SESTO_FALCON_CORE) ? 4821 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 4822 4823 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 4824 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 4825 4826 /* Reset RX data path */ 4827 for (lane = 0; lane < max_lane; lane ++) { 4828 if (lane_mask & (1 << lane)) { 4829 READ_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4830 if (ip == SESTO_FALCON_CORE) { 4831 dp_rst.fields.demux_ilane_dp_rstb &= ~(1 << lane); 4832 } else { 4833 dp_rst.fields.mux_ilane_dp_rstb &= ~(1 << lane); 4834 } 4835 WRITE_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4836 PHYMOD_USLEEP(1000); 4837 READ_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4838 if (ip == SESTO_FALCON_CORE) { 4839 dp_rst.fields.demux_ilane_dp_rstb |= (1 << lane); 4840 } else { 4841 dp_rst.fields.mux_ilane_dp_rstb |= (1 << lane); 4842 } 4843 WRITE_SESTO_PMA_PMD_REG(pa, DP_LANE_RESET_CONTROL0_ADR, dp_rst.data); 4844 } 4845 } 4846 4847 ERR: 4848 PHYMOD_FREE(config.device_aux_modes); 4849 4850 return rv; 4851 } 4852 4853 4854 int _sesto_tx_lane_control_set(const phymod_phy_access_t *phy, phymod_phy_tx_lane_control_t tx_control) 4855 { 4856 int rv = PHYMOD_E_NONE; 4857 4858 switch (tx_control) { 4859 case phymodTxTrafficDisable: /* disable tx traffic */ 4860 case phymodTxTrafficEnable: /* enable tx traffic */ 4861 return PHYMOD_E_UNAVAIL; 4862 case phymodTxReset: /* reset tx data path */ 4863 SESTO_IF_ERR_RETURN(_sesto_tx_dp_reset(phy)); 4864 break; 4865 case phymodTxSquelchOn: /* squelch tx */ 4866 SESTO_IF_ERR_RETURN(_sesto_tx_enable_set(phy, SESTO_DISABLE)); 4867 break; 4868 case phymodTxSquelchOff: /* squelch tx off */ 4869 SESTO_IF_ERR_RETURN(_sesto_tx_enable_set(phy, SESTO_ENABLE)); 4870 break; 4871 default: 4872 return PHYMOD_E_PARAM; 4873 } 4874 4875 ERR: 4876 return rv; 4877 } 4878 int _sesto_rx_lane_control_set(const phymod_phy_access_t *phy, phymod_phy_rx_lane_control_t rx_control) 4879 { 4880 int rv = PHYMOD_E_NONE; 4881 4882 switch (rx_control) { 4883 case phymodRxReset: /* reset rx data path */ 4884 SESTO_IF_ERR_RETURN(_sesto_rx_dp_reset(phy)); 4885 break; 4886 case phymodRxSquelchOn: /* squelch rx */ 4887 SESTO_IF_ERR_RETURN(_sesto_rx_enable_set(phy, SESTO_DISABLE)); 4888 break; 4889 case phymodRxSquelchOff: /* squelch rx off */ 4890 SESTO_IF_ERR_RETURN(_sesto_rx_enable_set(phy, SESTO_ENABLE)); 4891 break; 4892 default: 4893 return PHYMOD_E_PARAM; 4894 } 4895 4896 ERR: 4897 return rv; 4898 } 4899 4900 int _sesto_tx_lane_control_get(const phymod_phy_access_t *phy, phymod_phy_tx_lane_control_t *tx_control) 4901 { 4902 int16_t tx_ctrl = 0; 4903 int rv = PHYMOD_E_NONE; 4904 4905 switch (*tx_control) { 4906 case phymodTxTrafficDisable: /* disable tx traffic */ 4907 case phymodTxTrafficEnable: /* enable tx traffic */ 4908 case phymodTxReset: /* reset tx data path */ 4909 return PHYMOD_E_UNAVAIL; 4910 break; 4911 case phymodTxSquelchOn: /* squelch tx */ 4912 SESTO_IF_ERR_RETURN(_sesto_tx_enable_get(phy, &tx_ctrl)); 4913 *tx_control = tx_ctrl ? phymodTxSquelchOff: phymodTxSquelchOn; 4914 break; 4915 case phymodTxSquelchOff: /* squelch tx off */ 4916 SESTO_IF_ERR_RETURN(_sesto_tx_enable_get(phy, &tx_ctrl)); 4917 *tx_control = tx_ctrl ? phymodTxSquelchOff: phymodTxSquelchOn; 4918 break; 4919 default: 4920 SESTO_IF_ERR_RETURN(_sesto_tx_enable_get(phy, &tx_ctrl)); 4921 *tx_control = tx_ctrl ? phymodTxSquelchOff: phymodTxSquelchOn; 4922 break; 4923 } 4924 4925 ERR: 4926 return rv; 4927 } 4928 int _sesto_rx_lane_control_get(const phymod_phy_access_t *phy, phymod_phy_rx_lane_control_t *rx_control) 4929 { 4930 int16_t rx_ctrl = 0; 4931 int rv = PHYMOD_E_NONE; 4932 4933 switch (*rx_control) { 4934 case phymodRxReset: /* reset rx data path */ 4935 return PHYMOD_E_UNAVAIL; 4936 case phymodRxSquelchOn: /* squelch rx */ 4937 SESTO_IF_ERR_RETURN(_sesto_rx_enable_get(phy, &rx_ctrl)); 4938 *rx_control = rx_ctrl ? phymodRxSquelchOff: phymodRxSquelchOn; 4939 break; 4940 case phymodRxSquelchOff: /* squelch rx off */ 4941 SESTO_IF_ERR_RETURN(_sesto_rx_enable_get(phy, &rx_ctrl)); 4942 *rx_control = rx_ctrl ? phymodRxSquelchOff: phymodRxSquelchOn; 4943 break; 4944 default: 4945 return PHYMOD_E_PARAM; 4946 } 4947 4948 ERR: 4949 return rv; 4950 } 4951 int _sesto_intr_phymod_intr(const phymod_phy_access_t *phy, uint32_t intr_type, uint16_t *intr) 4952 { 4953 phymod_phy_inf_config_t config; 4954 uint16_t ip = 0, lane_mask = 0; 4955 int rv = PHYMOD_E_NONE; 4956 const phymod_access_t *pa = &phy->access; 4957 4958 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 4959 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 4960 SESTO_IF_ERR_RETURN( _sesto_phy_interface_config_get(phy, 0, &config)); 4961 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 4962 SESTO_GET_IP(phy, config, ip); 4963 4964 switch (intr_type) { 4965 case PHYMOD_INTR_LINK_EVENT: 4966 *intr = (ip == SESTO_FALCON_CORE) ? SESTO_INT_DEMUX_PMD_LOCK_LOST : SESTO_INT_MUX_PMD_LOCK_LOST; 4967 break; 4968 case PHYMOD_INTR_AUTONEG_EVENT: 4969 if (ip == SESTO_FALCON_CORE) { 4970 *intr = SESTO_INT_DEMUX_CL73_AN_COMPLETE; 4971 } else { 4972 if (lane_mask == 0xF) { /* 40G MUX P1 */ 4973 *intr = SESTO_INT_MUX_CL73_AN_COMPLETE_P1; 4974 } else if (lane_mask == 0xF0) { /* 40G MUX P1 */ 4975 *intr = SESTO_INT_MUX_CL73_AN_COMPLETE_P2; 4976 } else { /* 40G PT based on AN Master lane */ 4977 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T an_mst_sel; 4978 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 4979 if (((an_mst_sel.data & 0xF) >= 4) && ((an_mst_sel.data & 0xF) <= 5)) { 4980 *intr = SESTO_INT_MUX_CL73_AN_COMPLETE_P2; 4981 } else { 4982 *intr = SESTO_INT_MUX_CL73_AN_COMPLETE_P1; 4983 } 4984 } 4985 } 4986 break; 4987 case PHYMOD_INTR_PLL_EVENT: 4988 *intr = (ip == SESTO_FALCON_CORE) ? SESTO_INT_PLL_25G_LOCK_LOST : SESTO_INT_PLL_10G_LOCK_LOST; 4989 break; 4990 case PHYMOD_INTR_EMON_EVENT: 4991 *intr = (ip == SESTO_FALCON_CORE) ? SESTO_INT_DEMUX_PCS_MON_LOCK_LOST : SESTO_INT_MUX_PCS_MON_LOCK_LOST; 4992 break; 4993 default: 4994 return PHYMOD_E_NONE; 4995 } 4996 ERR: 4997 PHYMOD_FREE(config.device_aux_modes); 4998 4999 return rv; 5000 } 5001 5002 int _sesto_get_intr_reg(const phymod_phy_access_t *phy, uint32_t intr_type, uint16_t *bit_pos, uint16_t *int_grp) 5003 { 5004 uint16_t intr = -1; 5005 int rv = PHYMOD_E_NONE; 5006 5007 SESTO_IF_ERR_RETURN(_sesto_intr_phymod_intr(phy, intr_type, &intr)); 5008 *int_grp = -1; 5009 5010 /* Get the interrupt bit postion in the reg and interrupt group */ 5011 switch (intr) { 5012 case SESTO_INT_M0_SLV_SYSRESET_REQ: *bit_pos = 0; *int_grp = 0; break; 5013 case SESTO_INT_M0_MST_SYSRESET_REQ: *bit_pos = 1; *int_grp = 0; break; 5014 case SESTO_INT_M0_SLV_LOCKUP: *bit_pos = 2; *int_grp = 0; break; 5015 case SESTO_INT_M0_MST_LOCKUP: *bit_pos = 3; *int_grp = 0; break; 5016 case SESTO_INT_M0_SLV_MISC_INTR: *bit_pos = 4; *int_grp = 0; break; 5017 case SESTO_INT_M0_MST_MISC_INTR: *bit_pos = 5; *int_grp = 0; break; 5018 case SESTO_INT_M0_SLV_MSGOUT_INTR: *bit_pos = 6; *int_grp = 0; break; 5019 case SESTO_INT_M0_MST_MSGOUT_INTR: *bit_pos = 7; *int_grp = 0; break; 5020 case SESTO_INT_M0_SLV_DED: *bit_pos = 8; *int_grp = 0; break; 5021 case SESTO_INT_M0_SLV_SEC: *bit_pos = 9; *int_grp = 0; break; 5022 case SESTO_INT_M0_MST_DED: *bit_pos = 10; *int_grp = 0; break; 5023 case SESTO_INT_M0_MST_SEC: *bit_pos = 11; *int_grp = 0; break; 5024 case SESTO_INT_MODULE2_INTRB_LOW: *bit_pos = 12; *int_grp = 0; break; 5025 case SESTO_INT_MODULE2_INTRB_HIGH: *bit_pos = 13; *int_grp = 0; break; 5026 case SESTO_INT_MODULE1_INTRB_LOW: *bit_pos = 14; *int_grp = 0; break; 5027 case SESTO_INT_MODULE1_INTRB_HIGH: *bit_pos = 15; *int_grp = 0; break; 5028 case SESTO_INT_MUX_PMD_LOCK_LOST: *bit_pos = 0; *int_grp = 1; break; 5029 case SESTO_INT_MUX_PMD_LOCK_FOUND: *bit_pos = 1; *int_grp = 1; break; 5030 case SESTO_INT_MUX_SIGDET_LOST: *bit_pos = 2; *int_grp = 1; break; 5031 case SESTO_INT_MUX_SIGDET_FOUND: *bit_pos = 3; *int_grp = 1; break; 5032 case SESTO_INT_PLL_10G_LOCK_LOST: *bit_pos = 4; *int_grp = 1; break; 5033 case SESTO_INT_PLL_10G_LOCK_FOUND: *bit_pos = 5; *int_grp = 1; break; 5034 case SESTO_INT_MERLIN_PMI_ARB_WDOG_EXP: *bit_pos = 6; *int_grp = 1; break; 5035 case SESTO_INT_MERLIN_PMI_M0_WDOG_EXP: *bit_pos = 7; *int_grp = 1; break; 5036 case SESTO_INT_DEMUX_PMD_LOCK_LOST: *bit_pos = 0; *int_grp = 2; break; 5037 case SESTO_INT_DEMUX_PMD_LOCK_FOUND: *bit_pos = 1; *int_grp = 2; break; 5038 case SESTO_INT_DEMUX_SIGDET_LOST: *bit_pos = 2; *int_grp = 2; break; 5039 case SESTO_INT_DEMUX_SIGDET_FOUND: *bit_pos = 3; *int_grp = 2; break; 5040 case SESTO_INT_PLL_25G_LOCK_LOST: *bit_pos = 4; *int_grp = 2; break; 5041 case SESTO_INT_PLL_25G_LOCK_FOUND: *bit_pos = 5; *int_grp = 2; break; 5042 case SESTO_INT_FALCON_PMD_ARB_WDOG_EXP: *bit_pos = 6; *int_grp = 2; break; 5043 case SESTO_INT_FALCON_PMD_M0_WDOG_EXP: *bit_pos = 7; *int_grp = 2; break; 5044 case SESTO_INT_CL91_RX_ALIGN_LOST: *bit_pos = 0; *int_grp = 3; break; 5045 case SESTO_INT_CL91_RX_ALIGN_FOUND: *bit_pos = 1; *int_grp = 3; break; 5046 case SESTO_INT_DEMUX_ONEG_INBAND_MSG_LOST: *bit_pos = 2; *int_grp = 3; break; 5047 case SESTO_INT_DEMUX_ONEG_INBAND_MSG_FOUND: *bit_pos = 3; *int_grp = 3; break; 5048 case SESTO_INT_DEMUX_PCS_MON_LOCK_LOST: *bit_pos = 4; *int_grp = 3; break; 5049 case SESTO_INT_DEMUX_PCS_MON_LOCK_FOUND: *bit_pos = 5; *int_grp = 3; break; 5050 case SESTO_INT_DEMUX_FIFOERR: *bit_pos = 6; *int_grp = 3; break; 5051 case SESTO_INT_DEMUX_CL73_AN_RESTARTED: *bit_pos = 7; *int_grp = 3; break; 5052 case SESTO_INT_DEMUX_CL73_AN_COMPLETE: *bit_pos = 8; *int_grp = 3; break; 5053 case SESTO_INT_CL91_TX_ALIGN_LOST: *bit_pos = 0; *int_grp = 4; break; 5054 case SESTO_INT_CL91_TX_ALIGN_FOUND: *bit_pos = 1; *int_grp = 4; break; 5055 case SESTO_INT_MUX_ONEG_INBAND_MSG_LOST: *bit_pos = 2; *int_grp = 4; break; 5056 case SESTO_INT_MUX_ONEG_INBAND_MSG_FOUND: *bit_pos = 3; *int_grp = 4; break; 5057 case SESTO_INT_MUX_PCS_MON_LOCK_LOST: *bit_pos = 4; *int_grp = 4; break; 5058 case SESTO_INT_MUX_PCS_MON_LOCK_FOUND: *bit_pos = 5; *int_grp = 4; break; 5059 case SESTO_INT_MUX_FIFOERR: *bit_pos = 6; *int_grp = 4; break; 5060 case SESTO_INT_MUX_CL73_AN_RESTARTED: *bit_pos = 7; *int_grp = 4; break; 5061 case SESTO_INT_MUX_CL73_AN_COMPLETE: *bit_pos = 8; *int_grp = 4; break; 5062 case SESTO_INT_MUX_CL73_AN_RESTARTED_P2: *bit_pos = 9; *int_grp = 4; break; 5063 case SESTO_INT_MUX_CL73_AN_RESTARTED_P1: *bit_pos = 10; *int_grp = 4; break; 5064 case SESTO_INT_MUX_CL73_AN_COMPLETE_P2: *bit_pos = 11; *int_grp = 4; break; 5065 case SESTO_INT_MUX_CL73_AN_COMPLETE_P1: *bit_pos = 12; *int_grp = 4; break; 5066 default: 5067 return PHYMOD_E_PARAM; 5068 } 5069 5070 ERR: 5071 return rv; 5072 } 5073 int _sesto_ext_intr_enable_set(const phymod_phy_access_t *phy, uint32_t intr_type, uint32_t enable) 5074 { 5075 uint16_t intr_grp = 0; 5076 uint16_t bit_pos = 0; 5077 uint16_t intr_mask = 0; 5078 int rv = PHYMOD_E_NONE; 5079 SES_CTRL_M0_EIER_TYPE_T m0_eier; 5080 SES_CTRL_MM_EIER_TYPE_T mm_eier; 5081 SES_CTRL_DF_EIER_TYPE_T df_eier; 5082 SES_CTRL_DEMUX_EIER_TYPE_T demux_eier; 5083 SES_CTRL_MUX_EIER_TYPE_T mux_eier; 5084 const phymod_access_t *pa = &phy->access; 5085 5086 PHYMOD_MEMSET(&m0_eier, 0, sizeof(SES_CTRL_M0_EIER_TYPE_T)); 5087 PHYMOD_MEMSET(&mm_eier, 0, sizeof(SES_CTRL_MM_EIER_TYPE_T)); 5088 PHYMOD_MEMSET(&df_eier, 0, sizeof(SES_CTRL_DF_EIER_TYPE_T)); 5089 PHYMOD_MEMSET(&demux_eier, 0, sizeof(SES_CTRL_DEMUX_EIER_TYPE_T)); 5090 PHYMOD_MEMSET(&mux_eier, 0, sizeof(SES_CTRL_MUX_EIER_TYPE_T)); 5091 5092 5093 /* Get the interrupt bit postion in the reg and interrupt group */ 5094 _sesto_get_intr_reg(phy, intr_type, &bit_pos, &intr_grp); 5095 intr_mask = enable ? (0x1 << bit_pos) : (~(0x1 << bit_pos)); 5096 5097 /* Interrupt enable set on specified interrupt group */ 5098 switch(intr_grp) { 5099 case SESTO_M0_INTR_GRP: 5100 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_M0_EIER_ADR, m0_eier.data); 5101 m0_eier.data = enable ? (intr_mask | m0_eier.data) : (intr_mask & m0_eier.data); 5102 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_M0_EIER_ADR, m0_eier.data); 5103 break; 5104 case SESTO_MM_INTR_GRP: 5105 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_MM_EIER_ADR, mm_eier.data); 5106 mm_eier.data = enable ? (intr_mask | mm_eier.data) : (intr_mask & mm_eier.data); 5107 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_MM_EIER_ADR, mm_eier.data); 5108 break; 5109 case SESTO_DF_INTR_GRP: 5110 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_DF_EIER_ADR, df_eier.data); 5111 df_eier.data = enable ? (intr_mask | df_eier.data) : (intr_mask & df_eier.data); 5112 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_DF_EIER_ADR, df_eier.data); 5113 break; 5114 case SESTO_DEMUX_INTR_GRP: 5115 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_DEMUX_EIER_ADR, demux_eier.data); 5116 demux_eier.data = enable ? (intr_mask | demux_eier.data) : (intr_mask & demux_eier.data); 5117 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_DEMUX_EIER_ADR, demux_eier.data); 5118 break; 5119 case SESTO_MUX_INTR_GRP: 5120 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_MUX_EIER_ADR, mux_eier.data); 5121 mux_eier.data = enable ? (intr_mask | mux_eier.data) : (intr_mask & mux_eier.data); 5122 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_MUX_EIER_ADR, mux_eier.data); 5123 break; 5124 default: 5125 return PHYMOD_E_NONE; 5126 } 5127 5128 ERR: 5129 return rv; 5130 } 5131 int _sesto_ext_intr_enable_get(const phymod_phy_access_t *phy, uint32_t intr_type, uint32_t *enable) 5132 { 5133 uint16_t intr_grp = 0; 5134 uint16_t bit_pos = 0; 5135 uint16_t data = 0; 5136 int rv = PHYMOD_E_NONE; 5137 SES_CTRL_M0_EIER_TYPE_T m0_eier; 5138 SES_CTRL_MM_EIER_TYPE_T mm_eier; 5139 SES_CTRL_DF_EIER_TYPE_T df_eier; 5140 SES_CTRL_DEMUX_EIER_TYPE_T demux_eier; 5141 SES_CTRL_MUX_EIER_TYPE_T mux_eier; 5142 const phymod_access_t *pa = &phy->access; 5143 5144 PHYMOD_MEMSET(&m0_eier, 0, sizeof(SES_CTRL_M0_EIER_TYPE_T)); 5145 PHYMOD_MEMSET(&mm_eier, 0, sizeof(SES_CTRL_MM_EIER_TYPE_T)); 5146 PHYMOD_MEMSET(&df_eier, 0, sizeof(SES_CTRL_DF_EIER_TYPE_T)); 5147 PHYMOD_MEMSET(&demux_eier, 0, sizeof(SES_CTRL_DEMUX_EIER_TYPE_T)); 5148 PHYMOD_MEMSET(&mux_eier, 0, sizeof(SES_CTRL_MUX_EIER_TYPE_T)); 5149 *enable = 0; 5150 5151 /* Get the interrupt bit postion in the reg and interrupt group */ 5152 _sesto_get_intr_reg(phy, intr_type, &bit_pos, &intr_grp); 5153 5154 /* Interrupt enable get on specified interrupt group */ 5155 switch(intr_grp) { 5156 case SESTO_M0_INTR_GRP: 5157 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_M0_EIER_ADR, m0_eier.data); 5158 data = m0_eier.data; 5159 break; 5160 case SESTO_MM_INTR_GRP: 5161 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_MM_EIER_ADR, mm_eier.data); 5162 data = mm_eier.data; 5163 break; 5164 case SESTO_DF_INTR_GRP: 5165 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_DF_EIER_ADR, df_eier.data); 5166 data = df_eier.data; 5167 break; 5168 case SESTO_DEMUX_INTR_GRP: 5169 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_DEMUX_EIER_ADR, demux_eier.data); 5170 data = demux_eier.data; 5171 break; 5172 case SESTO_MUX_INTR_GRP: 5173 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_MUX_EIER_ADR, mux_eier.data); 5174 data = mux_eier.data; 5175 break; 5176 default: 5177 return PHYMOD_E_NONE; 5178 } 5179 *enable = (data & (0x1 << bit_pos)) ? 1 : 0; 5180 5181 ERR: 5182 return rv; 5183 } 5184 5185 int _sesto_ext_intr_status_get(const phymod_phy_access_t *phy, uint32_t intr_type, uint32_t *intr_status) 5186 { 5187 uint16_t intr_grp = 0; 5188 uint16_t bit_pos = 0; 5189 uint16_t data = 0; 5190 int rv = PHYMOD_E_NONE; 5191 SES_CTRL_M0_EIPR_TYPE_T m0_eipr; 5192 SES_CTRL_MM_EIPR_TYPE_T mm_eipr; 5193 SES_CTRL_DF_EIPR_TYPE_T df_eipr; 5194 SES_CTRL_DEMUX_EIPR_TYPE_T demux_eipr; 5195 SES_CTRL_MUX_EIPR_TYPE_T mux_eipr; 5196 const phymod_access_t *pa = &phy->access; 5197 5198 PHYMOD_MEMSET(&m0_eipr, 0, sizeof(SES_CTRL_M0_EIPR_TYPE_T)); 5199 PHYMOD_MEMSET(&mm_eipr, 0, sizeof(SES_CTRL_MM_EIPR_TYPE_T)); 5200 PHYMOD_MEMSET(&df_eipr, 0, sizeof(SES_CTRL_DF_EIPR_TYPE_T)); 5201 PHYMOD_MEMSET(&demux_eipr, 0, sizeof(SES_CTRL_DEMUX_EIPR_TYPE_T)); 5202 PHYMOD_MEMSET(&mux_eipr, 0, sizeof(SES_CTRL_MUX_EIPR_TYPE_T)); 5203 *intr_status = 0; 5204 5205 /* Get the interrupt bit postion in the reg and interrupt group */ 5206 _sesto_get_intr_reg(phy, intr_type, &bit_pos, &intr_grp); 5207 5208 /* Interrupt status get on specified interrupt group */ 5209 switch(intr_grp) { 5210 case SESTO_M0_INTR_GRP: 5211 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_M0_EIPR_ADR, m0_eipr.data); 5212 data = m0_eipr.data; 5213 break; 5214 case SESTO_MM_INTR_GRP: 5215 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_MM_EIPR_ADR, mm_eipr.data); 5216 data = mm_eipr.data; 5217 break; 5218 case SESTO_DF_INTR_GRP: 5219 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_DF_EIPR_ADR, df_eipr.data); 5220 data = df_eipr.data; 5221 break; 5222 case SESTO_DEMUX_INTR_GRP: 5223 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_DEMUX_EIPR_ADR, demux_eipr.data); 5224 data = demux_eipr.data; 5225 break; 5226 case SESTO_MUX_INTR_GRP: 5227 READ_SESTO_PMA_PMD_REG(pa, SES_CTRL_MUX_EIPR_ADR, mux_eipr.data); 5228 data = mux_eipr.data; 5229 break; 5230 default: 5231 return PHYMOD_E_NONE; 5232 } 5233 *intr_status = (data & (0x1 << bit_pos)) ? 1 : 0; 5234 5235 ERR: 5236 return rv; 5237 } 5238 5239 int _sesto_ext_intr_status_clear(const phymod_phy_access_t *phy, uint32_t intr_type) 5240 { 5241 uint16_t intr_grp = 0; 5242 uint16_t bit_pos = 0; 5243 uint16_t intr_mask = 0; 5244 int rv = PHYMOD_E_NONE; 5245 SES_CTRL_M0_EISR_TYPE_T m0_eisr; 5246 SES_CTRL_MM_EISR_TYPE_T mm_eisr; 5247 SES_CTRL_DF_EISR_TYPE_T df_eisr; 5248 SES_CTRL_DEMUX_EISR_TYPE_T demux_eisr; 5249 SES_CTRL_MUX_EISR_TYPE_T mux_eisr; 5250 const phymod_access_t *pa = &phy->access; 5251 5252 PHYMOD_MEMSET(&m0_eisr, 0, sizeof(SES_CTRL_M0_EISR_TYPE_T)); 5253 PHYMOD_MEMSET(&mm_eisr, 0, sizeof(SES_CTRL_MM_EISR_TYPE_T)); 5254 PHYMOD_MEMSET(&df_eisr, 0, sizeof(SES_CTRL_DF_EISR_TYPE_T)); 5255 PHYMOD_MEMSET(&demux_eisr, 0, sizeof(SES_CTRL_DEMUX_EISR_TYPE_T)); 5256 PHYMOD_MEMSET(&mux_eisr, 0, sizeof(SES_CTRL_MUX_EISR_TYPE_T)); 5257 5258 /* Get the interrupt bit postion in the reg and interrupt group */ 5259 _sesto_get_intr_reg(phy, intr_type, &bit_pos, &intr_grp); 5260 intr_mask = 0x1 << bit_pos; 5261 5262 /* Interrupt status clear on specified interrupt group */ 5263 switch(intr_grp) { 5264 case SESTO_M0_INTR_GRP: 5265 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_M0_EISR_ADR, intr_mask); 5266 break; 5267 case SESTO_MM_INTR_GRP: 5268 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_MM_EISR_ADR, intr_mask); 5269 break; 5270 case SESTO_DF_INTR_GRP: 5271 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_DF_EISR_ADR, intr_mask); 5272 break; 5273 case SESTO_DEMUX_INTR_GRP: 5274 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_DEMUX_EISR_ADR, intr_mask); 5275 break; 5276 case SESTO_MUX_INTR_GRP: 5277 WRITE_SESTO_PMA_PMD_REG(pa, SES_CTRL_MUX_EISR_ADR, intr_mask); 5278 break; 5279 default: 5280 return PHYMOD_E_NONE; 5281 } 5282 5283 ERR: 5284 return rv; 5285 } 5286 5287 int _sesto_pll_sequencer_restart(const phymod_core_access_t *core, phymod_sequencer_operation_t operation) 5288 { 5289 uint16_t ip = 0, intf_side = 0; 5290 int rv = PHYMOD_E_NONE; 5291 const phymod_access_t *pa = &core->access; 5292 DP_DECODED_MODE_STATUS0_TYPE_T mode_sts0; 5293 FALCON_IF_COMMON_CONTROL_TYPE_T fal_cmn_ctrl; 5294 MERLIN_IF_COMMON_CONTROL_TYPE_T mer_cmn_ctrl; 5295 5296 SESTO_GET_INTF_SIDE(core, intf_side); 5297 READ_SESTO_PMA_PMD_REG(pa, DP_DECODED_MODE_STATUS0_ADR, mode_sts0.data); 5298 if (intf_side == SESTO_IF_LINE) { 5299 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_FALCON_CORE : SESTO_MERLIN_CORE; 5300 } else { 5301 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_MERLIN_CORE : SESTO_FALCON_CORE; 5302 } 5303 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 5304 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 5305 switch(operation) { 5306 case phymodSeqOpStop: 5307 case phymodSeqOpStart: 5308 return PHYMOD_E_UNAVAIL; 5309 /* Toggle PLL Sequencer with pmd_core_dp_h_rstb_frcval */ 5310 case phymodSeqOpRestart: 5311 if (ip == SESTO_FALCON_CORE) { 5312 READ_SESTO_PMA_PMD_REG(pa, FALCON_IF_COMMON_CONTROL_ADR, fal_cmn_ctrl.data); 5313 fal_cmn_ctrl.fields.pmd_core_dp_h_rstb_frc = 1; 5314 fal_cmn_ctrl.fields.pmd_core_dp_h_rstb_frcval = 0; 5315 WRITE_SESTO_PMA_PMD_REG(pa, FALCON_IF_COMMON_CONTROL_ADR, fal_cmn_ctrl.data); 5316 PHYMOD_USLEEP(1000); 5317 READ_SESTO_PMA_PMD_REG(pa, FALCON_IF_COMMON_CONTROL_ADR, fal_cmn_ctrl.data); 5318 fal_cmn_ctrl.fields.pmd_core_dp_h_rstb_frc = 1; 5319 fal_cmn_ctrl.fields.pmd_core_dp_h_rstb_frcval = 1; 5320 WRITE_SESTO_PMA_PMD_REG(pa, FALCON_IF_COMMON_CONTROL_ADR, fal_cmn_ctrl.data); 5321 } else { 5322 READ_SESTO_PMA_PMD_REG(pa, MERLIN_IF_COMMON_CONTROL_ADR, mer_cmn_ctrl.data); 5323 mer_cmn_ctrl.fields.pmd_core_dp_h_rstb_frc = 1; 5324 mer_cmn_ctrl.fields.pmd_core_dp_h_rstb_frcval = 0; 5325 WRITE_SESTO_PMA_PMD_REG(pa, MERLIN_IF_COMMON_CONTROL_ADR, mer_cmn_ctrl.data); 5326 PHYMOD_USLEEP(1000); 5327 READ_SESTO_PMA_PMD_REG(pa, MERLIN_IF_COMMON_CONTROL_ADR, mer_cmn_ctrl.data); 5328 mer_cmn_ctrl.fields.pmd_core_dp_h_rstb_frc = 1; 5329 mer_cmn_ctrl.fields.pmd_core_dp_h_rstb_frcval = 1; 5330 WRITE_SESTO_PMA_PMD_REG(pa, MERLIN_IF_COMMON_CONTROL_ADR, mer_cmn_ctrl.data); 5331 5332 } 5333 break; 5334 default: 5335 break; 5336 } 5337 /* Clear FRC of rstb */ 5338 SESTO_CHIP_FIELD_WRITE(pa, FALCON_IF_COMMON_CONTROL, pmd_core_dp_h_rstb_frc, 0); 5339 SESTO_CHIP_FIELD_WRITE(pa, MERLIN_IF_COMMON_CONTROL, pmd_core_dp_h_rstb_frc, 0); 5340 5341 ERR: 5342 return rv; 5343 } 5344 5345 int _sesto_fec_enable_set(const phymod_phy_access_t *phy, uint32_t enable) 5346 { 5347 uint16_t ip = 0, intf_side = 0; 5348 int rv = PHYMOD_E_NONE; 5349 const phymod_access_t *pa = &phy->access; 5350 DP_DECODED_MODE_STATUS0_TYPE_T mode_sts0; 5351 5352 SESTO_GET_INTF_SIDE(phy, intf_side); 5353 READ_SESTO_PMA_PMD_REG(pa, DP_DECODED_MODE_STATUS0_ADR, mode_sts0.data); 5354 if (intf_side == SESTO_IF_LINE) { 5355 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_FALCON_CORE : SESTO_MERLIN_CORE; 5356 } else { 5357 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_MERLIN_CORE : SESTO_FALCON_CORE; 5358 } 5359 5360 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 5361 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 5362 /* Enables 100G FEC in Gearbox mode */ 5363 if (ip == SESTO_FALCON_CORE) { 5364 SESTO_CHIP_FIELD_WRITE(pa, DP_SESTO_MODE_CTRL0, mode_cl91_en, enable); 5365 } else { 5366 SESTO_RETURN_WITH_ERR(PHYMOD_E_PARAM, 5367 (_PHYMOD_MSG("FEC Applicable for Gearbox mode and 25G SERDES only"))); 5368 } 5369 5370 ERR: 5371 return rv; 5372 } 5373 int _sesto_fec_enable_get(const phymod_phy_access_t *phy, uint32_t* enable) 5374 { 5375 uint16_t ip = 0, intf_side = 0; 5376 int rv = PHYMOD_E_NONE; 5377 const phymod_access_t *pa = &phy->access; 5378 DP_DECODED_MODE_STATUS0_TYPE_T mode_sts0; 5379 5380 SESTO_GET_INTF_SIDE(phy, intf_side); 5381 READ_SESTO_PMA_PMD_REG(pa, DP_DECODED_MODE_STATUS0_ADR, mode_sts0.data); 5382 if (intf_side == SESTO_IF_LINE) { 5383 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_FALCON_CORE : SESTO_MERLIN_CORE; 5384 } else { 5385 ip = (mode_sts0.fields.decoded_mode_falcon_line) ? SESTO_MERLIN_CORE : SESTO_FALCON_CORE; 5386 } 5387 5388 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 5389 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 5390 /* FEC status on 100G Gearbox mode */ 5391 if (ip == SESTO_FALCON_CORE) { 5392 SESTO_CHIP_FIELD_READ(pa, DP_SESTO_MODE_CTRL0, mode_cl91_en, (*enable)); 5393 } else { 5394 SESTO_RETURN_WITH_ERR(PHYMOD_E_PARAM, 5395 (_PHYMOD_MSG("FEC Applicable for Gearbox mode and 25G SERDES only"))); 5396 } 5397 5398 ERR: 5399 return rv; 5400 } 5401 5402 int _sesto_config_hcd_link_sts (const phymod_access_t* pa, phymod_phy_inf_config_t config, uint16_t ip ) 5403 { 5404 SESTO_DEVICE_AUX_MODE_T *aux_mode; 5405 int rv = PHYMOD_E_NONE; 5406 RX_ANA_REGS_ANARXCONTROL3_TYPE_T an_rx_ctrl3; 5407 5408 aux_mode = config.device_aux_modes; 5409 5410 if (!aux_mode->pass_thru && config.data_rate != SESTO_SPD_100G) { 5411 /* 40G Mux Mode*/ 5412 if (pa->lane_mask & 0xF) { 5413 SESTO_IF_ERR_RETURN( 5414 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5415 SESTO_DEV_AN, 0, 0)); 5416 } else { 5417 SESTO_IF_ERR_RETURN( 5418 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5419 SESTO_DEV_AN, 0, 1)); 5420 } 5421 } else { 5422 SESTO_IF_ERR_RETURN( 5423 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5424 SESTO_DEV_AN, 0, 0)); 5425 } 5426 5427 /* HCD_LINK_REG_WR */ 5428 READ_SESTO_AN_REG(pa, RX_ANA_REGS_ANARXCONTROL3_ADR, 5429 an_rx_ctrl3.data); 5430 an_rx_ctrl3.fields.use_kr4_block_lock_sm = 0; 5431 an_rx_ctrl3.fields.use_kr4_pmd_lock_sm = 1; 5432 WRITE_SESTO_AN_REG(pa, RX_ANA_REGS_ANARXCONTROL3_ADR, 5433 an_rx_ctrl3.data); 5434 5435 ERR: 5436 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 5437 return rv; 5438 } 5439 5440 int _sesto_autoneg_ability_set(const phymod_phy_access_t* phy, sesto_an_ability_t *an_ability) 5441 { 5442 phymod_phy_inf_config_t config; 5443 uint16_t ip = 0, data = 0; 5444 uint16_t lane_mask = 0; 5445 uint16_t intf_side = 0; 5446 int rv = PHYMOD_E_NONE; 5447 const phymod_access_t *pa = &phy->access; 5448 IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_TYPE_T adv1; 5449 IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_TYPE_T adv2; 5450 IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_TYPE_T adv3; 5451 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T an_mst_sel; 5452 SESTO_DEVICE_AUX_MODE_T *aux_mode; 5453 5454 PHYMOD_MEMSET(&adv1, 0, sizeof(IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_TYPE_T)); 5455 PHYMOD_MEMSET(&adv2, 0, sizeof(IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_TYPE_T)); 5456 PHYMOD_MEMSET(&adv3, 0, sizeof(IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_TYPE_T)); 5457 PHYMOD_MEMSET(&an_mst_sel, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T)); 5458 5459 SESTO_GET_INTF_SIDE(phy, intf_side); 5460 if (intf_side == SESTO_IF_SYS) { 5461 /* AN can performed only on line side */ 5462 return PHYMOD_E_PARAM; 5463 } 5464 5465 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 5466 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 5467 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 5468 aux_mode = config.device_aux_modes; 5469 5470 SESTO_IF_ERR_RETURN(_sesto_phy_interface_config_get(phy, 0, &config)); 5471 5472 if ((config.data_rate == SESTO_SPD_10G || config.data_rate == SESTO_SPD_20G || 5473 config.data_rate == SESTO_SPD_11G || config.data_rate == SESTO_SPD_21G) || 5474 ((config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) && aux_mode->gearbox_100g_inverse_mode)) { 5475 goto ERR; 5476 } 5477 SESTO_GET_IP(phy, config, ip); 5478 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5479 /* SES_GEN_CNTRLS_MICRO_SYNC_4_ADR: 0-7 bits are used as scratch register to configure the master lane */ 5480 if (!aux_mode->pass_thru && config.data_rate != SESTO_SPD_100G) { 5481 /* 40G Mux Mode*/ 5482 if (lane_mask & 0xF) { 5483 SESTO_IF_ERR_RETURN(_sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5484 SESTO_DEV_AN, 0, 0)); 5485 if (an_ability->an_master_lane < 4) { 5486 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5487 an_mst_sel.data &= 0xFFF0; 5488 an_mst_sel.data |= an_ability->an_master_lane; 5489 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5490 } else { 5491 PHYMOD_DEBUG_ERROR(("Invalid AN Master lane config, should be between 0 to 3\n")); 5492 } 5493 } else { 5494 SESTO_IF_ERR_RETURN( 5495 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5496 SESTO_DEV_AN, 0, 1)); 5497 if (an_ability->an_master_lane < 4) { 5498 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5499 an_mst_sel.data &= 0xFF0F; 5500 an_mst_sel.data |= (an_ability->an_master_lane << 4); 5501 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5502 } else { 5503 PHYMOD_DEBUG_ERROR(("Invalid AN Master lane config, should be between 0 to 3\n")); 5504 } 5505 } 5506 } else { 5507 if ((aux_mode->BCM84793_capablity) || (config.data_rate == SESTO_SPD_100G)) { 5508 if (an_ability->an_master_lane < 4) { 5509 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5510 an_mst_sel.data &= 0xFF00; 5511 an_mst_sel.data |= an_ability->an_master_lane; 5512 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5513 } else { 5514 PHYMOD_DEBUG_ERROR(("Invalid AN Master lane config, should be between 0 to 3 depends on mode configuration\n")); 5515 } 5516 } else if ((an_ability->an_master_lane < 2) || 5517 (((an_ability->an_master_lane & 0xF) >= 4) && ((an_ability->an_master_lane & 0xF) <= 5))) { 5518 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5519 an_mst_sel.data &= 0xFF00; 5520 an_mst_sel.data |= an_ability->an_master_lane; 5521 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5522 } else { 5523 PHYMOD_DEBUG_ERROR(("Invalid AN Master lane config, should be between 0-1 or 4-5 depends on mode configuration\n")); 5524 } 5525 5526 5527 if (((an_ability->an_master_lane & 0xF) >= 4) && ((an_ability->an_master_lane & 0xF) <= 5)) { 5528 SESTO_IF_ERR_RETURN( 5529 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5530 SESTO_DEV_AN, 0, 1)); 5531 } else { 5532 SESTO_IF_ERR_RETURN( 5533 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5534 SESTO_DEV_AN, 0, 0)); 5535 } 5536 } 5537 5538 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_ADR, 5539 adv3.data); 5540 adv3.fields.fec_requested = an_ability->cl73_adv.an_fec; 5541 WRITE_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_ADR, 5542 adv3.data); 5543 5544 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_ADR, 5545 adv2.data); 5546 adv2.fields.techability = an_ability->cl73_adv.an_base_speed; 5547 WRITE_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_ADR, 5548 adv2.data); 5549 5550 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_ADR, 5551 adv1.data); 5552 adv1.fields.pause = an_ability->cl73_adv.an_pause; 5553 WRITE_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_ADR, 5554 adv1.data); 5555 5556 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 5557 SESTO_IF_ERR_RETURN(_sesto_config_hcd_link_sts (pa, config, ip)); 5558 5559 /* AN without TX training set GPREG11[11] to 1 */ 5560 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, data); 5561 an_ability->cl73_adv.an_cl72 ? (data &= (~(0x1 << 11))) : (data |= (0x1 << 11)); 5562 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, data); 5563 5564 ERR: 5565 PHYMOD_FREE(config.device_aux_modes); 5566 5567 return rv; 5568 } 5569 5570 int _sesto_autoneg_set(const phymod_phy_access_t* phy, const phymod_autoneg_control_t* an) 5571 { 5572 phymod_phy_inf_config_t config; 5573 uint16_t ip = 0; 5574 uint16_t lane_mask = 0; 5575 uint16_t retry_cnt = 0; 5576 uint16_t intf_side = 0, data1; 5577 int rv = PHYMOD_E_NONE; 5578 SES_GEN_CNTRLS_GPREG11_TYPE_T gpreg11; 5579 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T an_mst_sel; 5580 SESTO_DEVICE_AUX_MODE_T *aux_mode; 5581 const phymod_access_t *pa = &phy->access; 5582 5583 SESTO_GET_INTF_SIDE(phy, intf_side); 5584 if (intf_side == SESTO_IF_SYS) { 5585 /* AN can performed only on line side */ 5586 return PHYMOD_E_PARAM; 5587 } 5588 5589 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 5590 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 5591 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 5592 5593 SESTO_IF_ERR_RETURN(_sesto_phy_interface_config_get(phy, 0, &config)); 5594 aux_mode = config.device_aux_modes; 5595 5596 if ((config.data_rate == SESTO_SPD_10G || config.data_rate == SESTO_SPD_20G || 5597 config.data_rate == SESTO_SPD_11G || config.data_rate == SESTO_SPD_21G) || 5598 ((config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) && aux_mode->gearbox_100g_inverse_mode)) { 5599 if (an->enable) { 5600 PHYMOD_DEBUG_ERROR(("Invalid config for CL73, AN does not support for 10G/11G, 20G/21G and 100G Inverse mode\n")); 5601 } 5602 goto ERR; 5603 } 5604 5605 SESTO_GET_IP(phy, config, ip); 5606 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s lanemask:0x%x\n", __func__, 5607 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", lane_mask)); 5608 5609 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 5610 do { 5611 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data1); 5612 /* ATE_GUIDELINES : Sleep 10ms*/ 5613 retry_cnt--; 5614 } while ((data1 != 0) && (retry_cnt)); 5615 5616 if (retry_cnt == 0) { 5617 PHYMOD_DEBUG_VERBOSE(("WARN:: FW Enable not cleared\n")); 5618 goto ERR; 5619 } 5620 5621 /* Setting the master lane by reading static config at scratch register and enable AN*/ 5622 if (an->an_mode == phymod_AN_MODE_CL73) { 5623 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 5624 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5625 5626 if (an->enable) { 5627 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG10_ADR, data1); 5628 data1 &= (~(0x7 << 8)); /* PMD Lock check delay through GPREG10[11:8], default value is '0' of 100ms */ 5629 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG10_ADR, data1); 5630 } 5631 5632 if (!aux_mode->pass_thru && config.data_rate != SESTO_SPD_100G) { 5633 /* 40G Mux Mode*/ 5634 if (lane_mask & 0xF) { 5635 /* Master lane config and AN Enable */ 5636 if ((an_mst_sel.data & 0xF) <= 3) { 5637 SESTO_CHIP_FIELD_WRITE(pa, DP_MER_AN_LANE_SELECT, mer_an_lane_sel0to3, (an_mst_sel.data & 0xF)); 5638 } else { 5639 PHYMOD_DEBUG_ERROR(("Invalid AN master lane, should be b/w 0 to 3\n")); 5640 } 5641 if (an->enable) { 5642 gpreg11.fields.an_enable |= 0x1; 5643 } else { 5644 gpreg11.fields.an_enable &= ~(0x1); 5645 } 5646 } else { 5647 /* Master lane config and AN Enable */ 5648 if (((an_mst_sel.data >> 4) & 0xF) <= 3) { 5649 SESTO_CHIP_FIELD_WRITE(pa, DP_MER_AN_LANE_SELECT, 5650 mer_an_lane_sel4to7, ((an_mst_sel.data >> 4) & 0xF)); 5651 } else { 5652 PHYMOD_DEBUG_ERROR(("Invalid AN master lane, should be b/w 0 to 3\n")); 5653 } 5654 if (an->enable) { 5655 gpreg11.fields.an_enable |= 0x2; 5656 } else { 5657 gpreg11.fields.an_enable &= ~(0x2); 5658 } 5659 } 5660 } else { 5661 /* 40G PT and 100G GBOX */ 5662 if (ip == SESTO_FALCON_CORE) { 5663 /* Master lane config and AN Enable */ 5664 if ((an_mst_sel.data & 0xF) <= 3) { 5665 SESTO_CHIP_FIELD_WRITE(pa, DP_FAL_AN_LANE_SELECT, fal_an_lane_sel0to3, (an_mst_sel.data & 0xF)); 5666 } else { 5667 PHYMOD_DEBUG_ERROR(("Invalid AN master lane, should be b/w 0 to 3\n")); 5668 } 5669 if (an->enable) { 5670 gpreg11.fields.an_enable |= 0x1; 5671 } else { 5672 gpreg11.fields.an_enable &= ~(0x1); 5673 } 5674 } else { 5675 if (((an_mst_sel.data & 0xF) <= 1) || (aux_mode->BCM84793_capablity & ((an_mst_sel.data & 0xF) <= 3))) { 5676 /* Master lane config and AN Enable */ 5677 SESTO_CHIP_FIELD_WRITE(pa, DP_MER_AN_LANE_SELECT, mer_an_lane_sel0to3, (an_mst_sel.data & 0xF)); 5678 if (an->enable) { 5679 gpreg11.fields.an_enable |= 0x1; 5680 } else { 5681 gpreg11.fields.an_enable &= ~(0x1); 5682 } 5683 } else if (((an_mst_sel.data & 0xF) >= 4) && ((an_mst_sel.data & 0xF) <= 5)) { 5684 /* Master lane config and AN Enable */ 5685 SESTO_CHIP_FIELD_WRITE(pa, DP_MER_AN_LANE_SELECT, mer_an_lane_sel4to7, ((an_mst_sel.data & 0xF) - 4)); 5686 if (an->enable) { 5687 gpreg11.fields.an_enable |= 0x2; 5688 } else { 5689 gpreg11.fields.an_enable &= ~(0x2); 5690 } 5691 } else { 5692 /* AN Enable */ 5693 PHYMOD_DEBUG_ERROR(("Invalid AN master lane, should be b/w 0-1 or 4-5 depends on mode configuration\n")); 5694 if (an->enable) { 5695 gpreg11.fields.an_enable |= 0x1; 5696 } else { 5697 gpreg11.fields.an_enable &= ~(0x1); 5698 } 5699 } 5700 } 5701 } 5702 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 5703 } else { 5704 goto ERR; 5705 } 5706 5707 /*Setting the FW Enable to 1*/ 5708 SESTO_IF_ERR_RETURN( _sesto_fw_enable(pa, 1)); 5709 5710 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 5711 do { 5712 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data1); 5713 /* ATE_GUIDELINES : Sleep 10ms*/ 5714 retry_cnt--; 5715 } while ((data1 != 0) && (retry_cnt)); 5716 5717 if (retry_cnt == 0) { 5718 PHYMOD_DEBUG_VERBOSE(("WARN:: FW Enable not cleared\n")); 5719 goto ERR; 5720 } 5721 5722 ERR: 5723 PHYMOD_FREE(config.device_aux_modes); 5724 5725 return rv; 5726 } 5727 5728 int _sesto_autoneg_get(const phymod_phy_access_t* phy, phymod_autoneg_control_t* an, uint32_t *an_done) 5729 { 5730 phymod_phy_inf_config_t config; 5731 uint16_t ip = 0; 5732 uint16_t lane_mask = 0; 5733 uint16_t intf_side = 0; 5734 int rv = PHYMOD_E_NONE; 5735 SESTO_DEVICE_AUX_MODE_T *aux_mode; 5736 IEEE_AN_BLK0_AN_STATUS_REGISTER_TYPE_T an_status; 5737 IEEE_AN_BLK0_AN_CONTROL_REGISTER_TYPE_T an_ctrl; 5738 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T an_mst_sel; 5739 const phymod_access_t *pa = &phy->access; 5740 5741 SESTO_GET_INTF_SIDE(phy, intf_side); 5742 if (intf_side == SESTO_IF_SYS) { 5743 /* AN can performed only on line side */ 5744 return PHYMOD_E_PARAM; 5745 } 5746 PHYMOD_MEMSET(&an_mst_sel, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T)); 5747 PHYMOD_MEMSET(&an_status, 0, sizeof(IEEE_AN_BLK0_AN_STATUS_REGISTER_TYPE_T)); 5748 PHYMOD_MEMSET(&an_ctrl, 0, sizeof(IEEE_AN_BLK0_AN_CONTROL_REGISTER_TYPE_T)); 5749 5750 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 5751 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 5752 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 5753 aux_mode = config.device_aux_modes; 5754 5755 SESTO_IF_ERR_RETURN( 5756 _sesto_phy_interface_config_get(phy, 0, &config)); 5757 aux_mode = config.device_aux_modes; 5758 5759 /* AN does not support 10G, 20G and 100G Inverse mode */ 5760 if ((config.data_rate == SESTO_SPD_10G || config.data_rate == SESTO_SPD_20G || 5761 config.data_rate == SESTO_SPD_11G || config.data_rate == SESTO_SPD_21G) || 5762 ((config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) && aux_mode->gearbox_100g_inverse_mode)) { 5763 goto ERR; 5764 } 5765 5766 SESTO_GET_IP(phy, config, ip); 5767 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s lanemask:0x%x\n", __func__, 5768 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", lane_mask)); 5769 5770 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5771 if (!aux_mode->pass_thru && config.data_rate != SESTO_SPD_100G) { 5772 /* 40G Mux Mode*/ 5773 if (lane_mask & 0xF) { 5774 SESTO_IF_ERR_RETURN( 5775 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5776 SESTO_DEV_AN, 0, 0)); 5777 } else { 5778 SESTO_IF_ERR_RETURN( 5779 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5780 SESTO_DEV_AN, 0, 1)); 5781 } 5782 } else { 5783 if (((an_mst_sel.data & 0xF) >= 4) && ((an_mst_sel.data & 0xF) <= 5)) { 5784 SESTO_IF_ERR_RETURN( 5785 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5786 SESTO_DEV_AN, 0, 1)); 5787 } else { 5788 SESTO_IF_ERR_RETURN( 5789 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5790 SESTO_DEV_AN, 0, 0)); 5791 } 5792 } 5793 5794 /* AN enable status */ 5795 READ_SESTO_AN_REG(pa, IEEE_AN_BLK0_AN_CONTROL_REGISTER_ADR, an_ctrl.data); 5796 an->enable = an_ctrl.fields.auto_negotiationenable; 5797 5798 /* AN Mode */ 5799 an->an_mode = phymod_AN_MODE_CL73; 5800 5801 /* AN complete status read AN_DONE */ 5802 READ_SESTO_AN_REG(pa, IEEE_AN_BLK0_AN_STATUS_REGISTER_ADR, an_status.data); 5803 *an_done = an_status.fields.auto_negotiationcomplete; 5804 5805 ERR: 5806 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 5807 PHYMOD_FREE(config.device_aux_modes); 5808 5809 return rv; 5810 } 5811 5812 int _sesto_autoneg_ability_get(const phymod_phy_access_t* phy, sesto_an_ability_t *an_ability) 5813 { 5814 phymod_phy_inf_config_t config; 5815 uint16_t ip = 0; 5816 uint16_t lane_mask = 0; 5817 uint16_t intf_side = 0; 5818 int rv = PHYMOD_E_NONE; 5819 SESTO_DEVICE_AUX_MODE_T *aux_mode; 5820 IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_TYPE_T adv1; 5821 IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_TYPE_T adv2; 5822 IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_TYPE_T adv3; 5823 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T an_mst_sel; 5824 const phymod_access_t *pa = &phy->access; 5825 5826 5827 SESTO_GET_INTF_SIDE(phy, intf_side); 5828 if (intf_side == SESTO_IF_SYS) { 5829 /* AN can performed only on line side */ 5830 return PHYMOD_E_PARAM; 5831 } 5832 5833 PHYMOD_MEMSET(&adv1, 0, sizeof(IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_TYPE_T)); 5834 PHYMOD_MEMSET(&adv2, 0, sizeof(IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_TYPE_T)); 5835 PHYMOD_MEMSET(&adv3, 0, sizeof(IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_TYPE_T)); 5836 PHYMOD_MEMSET(&an_mst_sel, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T)); 5837 5838 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 5839 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 5840 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 5841 aux_mode = config.device_aux_modes; 5842 5843 SESTO_IF_ERR_RETURN( 5844 _sesto_phy_interface_config_get(phy, 0, &config)); 5845 5846 /* AN does not support 10G, 20G and 100G Inverse mode */ 5847 if ((config.data_rate == SESTO_SPD_10G || config.data_rate == SESTO_SPD_20G || 5848 config.data_rate == SESTO_SPD_11G || config.data_rate == SESTO_SPD_21G) || 5849 ((config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) && aux_mode->gearbox_100g_inverse_mode)) { 5850 goto ERR; 5851 } 5852 5853 SESTO_GET_IP(phy, config, ip); 5854 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s lanemask:0x%x\n", __func__, 5855 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", lane_mask)); 5856 5857 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5858 if (!aux_mode->pass_thru && config.data_rate != SESTO_SPD_100G) { 5859 /* 40G Mux Mode*/ 5860 if (lane_mask & 0xF) { 5861 SESTO_IF_ERR_RETURN( 5862 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5863 SESTO_DEV_AN, 0, 0)); 5864 } else { 5865 SESTO_IF_ERR_RETURN( 5866 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5867 SESTO_DEV_AN, 0, 1)); 5868 } 5869 } else { 5870 if (((an_mst_sel.data & 0xF) >= 4) && ((an_mst_sel.data & 0xF) <= 5)) { 5871 SESTO_IF_ERR_RETURN( 5872 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5873 SESTO_DEV_AN, 0, 1)); 5874 } else { 5875 SESTO_IF_ERR_RETURN( 5876 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5877 SESTO_DEV_AN, 0, 0)); 5878 } 5879 } 5880 5881 /* Fec ability */ 5882 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_3_REGISTER_ADR, 5883 adv3.data); 5884 an_ability->cl73_adv.an_fec = adv3.fields.fec_requested; 5885 5886 /* Techability */ 5887 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_2_REGISTER_ADR, 5888 adv2.data); 5889 an_ability->cl73_adv.an_base_speed = adv2.fields.techability; 5890 5891 /* AN ability */ 5892 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_ADVERTISEMENT_1_REGISTER_ADR, 5893 adv1.data); 5894 an_ability->cl73_adv.an_pause = adv1.fields.pause; 5895 5896 ERR: 5897 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 5898 PHYMOD_FREE(config.device_aux_modes); 5899 5900 return rv; 5901 } 5902 5903 int _sesto_autoneg_remote_ability_get(const phymod_phy_access_t *phy, phymod_autoneg_ability_t* an_ability_get) 5904 { 5905 phymod_phy_inf_config_t config; 5906 uint16_t ip = 0; 5907 uint16_t lane_mask = 0; 5908 uint16_t intf_side = 0; 5909 int rv = PHYMOD_E_NONE; 5910 SESTO_DEVICE_AUX_MODE_T *aux_mode; 5911 IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_1_REG_TYPE_T adv1; 5912 IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_2_REG_TYPE_T adv2; 5913 IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_3_REG_TYPE_T adv3; 5914 SES_GEN_CNTRLS_MICRO_SYNC_4_TYPE_T an_mst_sel; 5915 const phymod_access_t *pa = &phy->access; 5916 5917 SESTO_GET_INTF_SIDE(phy, intf_side); 5918 if (intf_side == SESTO_IF_SYS) { 5919 /* AN can performed only on line side */ 5920 return PHYMOD_E_PARAM; 5921 } 5922 5923 PHYMOD_MEMSET(&adv1, 0, sizeof(IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_1_REG_TYPE_T)); 5924 PHYMOD_MEMSET(&adv2, 0, sizeof(IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_2_REG_TYPE_T)); 5925 PHYMOD_MEMSET(&adv3, 0, sizeof(IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_3_REG_TYPE_T)); 5926 PHYMOD_MEMSET(&an_mst_sel, 0, sizeof(SES_GEN_CNTRLS_MICRO_SYNC_0_TYPE_T)); 5927 5928 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 5929 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 5930 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 5931 aux_mode = config.device_aux_modes; 5932 5933 SESTO_IF_ERR_RETURN( 5934 _sesto_phy_interface_config_get(phy, 0, &config)); 5935 5936 /* AN does not support 10G, 20G and 100G Inverse mode */ 5937 if ((config.data_rate == SESTO_SPD_10G || config.data_rate == SESTO_SPD_20G || 5938 config.data_rate == SESTO_SPD_11G || config.data_rate == SESTO_SPD_21G) || 5939 ((config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) && aux_mode->gearbox_100g_inverse_mode)) { 5940 goto ERR; 5941 } 5942 5943 SESTO_GET_IP(phy, config, ip); 5944 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s lanemask:0x%x\n", __func__, 5945 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", lane_mask)); 5946 5947 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_4_ADR, an_mst_sel.data); 5948 if (!aux_mode->pass_thru && config.data_rate != SESTO_SPD_100G) { 5949 /* 40G Mux Mode*/ 5950 if (lane_mask & 0xF) { 5951 SESTO_IF_ERR_RETURN( 5952 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5953 SESTO_DEV_AN, 0, 0)); 5954 } else { 5955 SESTO_IF_ERR_RETURN( 5956 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5957 SESTO_DEV_AN, 0, 1)); 5958 } 5959 } else { 5960 if (((an_mst_sel.data & 0xF) >= 4) && ((an_mst_sel.data & 0xF) <= 5)) { 5961 SESTO_IF_ERR_RETURN( 5962 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5963 SESTO_DEV_AN, 0, 1)); 5964 } else { 5965 SESTO_IF_ERR_RETURN( 5966 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 5967 SESTO_DEV_AN, 0, 0)); 5968 } 5969 } 5970 5971 /* Fec ability */ 5972 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_3_REG_ADR, 5973 adv3.data); 5974 an_ability_get->an_fec = (adv3.data & 0xC000) >> 15; 5975 5976 /* Techability */ 5977 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_2_REG_ADR, 5978 adv2.data); 5979 an_ability_get->an_cap = (adv2.data & 0xFFE0) >> 5; 5980 5981 /* AN ability */ 5982 READ_SESTO_AN_REG(pa, IEEE_AN_BLK1_AN_LP_BASE_PAGE_ABILITY_1_REG_ADR, 5983 adv1.data); 5984 if (adv1.data & 0x400) { 5985 PHYMOD_AN_CAP_ASYM_PAUSE_SET(an_ability_get); 5986 } else if (adv1.data & 0x800) { 5987 PHYMOD_AN_CAP_SYMM_PAUSE_SET(an_ability_get); 5988 } 5989 5990 ERR: 5991 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 5992 PHYMOD_FREE(config.device_aux_modes); 5993 5994 return rv; 5995 } 5996 5997 5998 int _sesto_port_from_lane_map_get(const phymod_phy_access_t *phy, const phymod_phy_inf_config_t* cfg, uint16_t *port) 5999 { 6000 phymod_phy_inf_config_t config; 6001 uint16_t ip = 0; 6002 uint16_t lane_mask = 0; 6003 SESTO_DEVICE_AUX_MODE_T *aux_mode; 6004 DP_SESTO_MODE_CTRL0_TYPE_T ctrl0; 6005 int rv = PHYMOD_E_NONE; 6006 const phymod_access_t *pa = &phy->access; 6007 6008 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 6009 PHYMOD_MEMCPY(&config, cfg, sizeof(phymod_phy_inf_config_t)); 6010 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)cfg->device_aux_modes; 6011 SESTO_GET_IP(phy, config, ip); 6012 6013 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 6014 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 6015 6016 PHYMOD_MEMSET(&ctrl0, 0, sizeof(DP_SESTO_MODE_CTRL0_TYPE_T)); 6017 READ_SESTO_PMA_PMD_REG(pa, DP_SESTO_MODE_CTRL0_ADR,ctrl0.data); 6018 if (config.data_rate == SESTO_SPD_100G || config.data_rate == SESTO_SPD_106G) { 6019 *port = 0; 6020 } else if (config.data_rate == SESTO_SPD_40G || config.data_rate == SESTO_SPD_42G) { 6021 if (ip == SESTO_FALCON_CORE) { 6022 if (aux_mode->pass_thru || aux_mode->BCM84793_capablity) { 6023 if (lane_mask == 0xF) { /*port 0 */ 6024 *port = 0; 6025 } 6026 } else { /* 40G MUX */ 6027 if (lane_mask == 0x3) { /* port 0 */ 6028 *port = 0; 6029 } else if (lane_mask == 0xC) { /* port 1 */ 6030 *port = 1; 6031 } 6032 } 6033 } else { 6034 if (aux_mode->pass_thru || aux_mode->BCM84793_capablity) { 6035 if (lane_mask == 0x33) { /* port 0 */ 6036 *port = 0; 6037 } 6038 else if (lane_mask == 0xF) { /* port 0 */ 6039 *port = 0; 6040 } 6041 } else { /* 40G MUX */ 6042 if (lane_mask == 0xF) { /* port 0 */ 6043 *port = 0; 6044 } else if (lane_mask == 0xF0) { /* port 1 */ 6045 *port = 1; 6046 } 6047 } 6048 } 6049 if (ctrl0.fields.mode_multiport2_40g_mux && ctrl0.fields.mode_multiport1_10g1 && 6050 ctrl0.fields.mode_multiport1_10g2) { 6051 *port += 1; 6052 } 6053 } else if (config.data_rate == SESTO_SPD_20G || config.data_rate == SESTO_SPD_21G) { 6054 if (ip == SESTO_FALCON_CORE) { 6055 if (aux_mode->pass_thru) { 6056 if (lane_mask == 0x3) { /* port 0 */ 6057 *port = 0; 6058 } else if (lane_mask == 0xC) { /* port 1 */ 6059 *port = 1; 6060 } 6061 } else { /* 20G MUX */ 6062 if (lane_mask == 0x1) { /* port 0 */ 6063 *port = 0; 6064 } else if (lane_mask == 0x4) { /* port 1 */ 6065 *port = 1; 6066 } 6067 } 6068 } else { /* 20G PT & MUX */ 6069 if (lane_mask == 0x3) { /* port 0 */ 6070 *port = 0; 6071 } else if (lane_mask == 0x30) { /* port 1 */ 6072 *port = 1; 6073 } 6074 } 6075 if ((ctrl0.fields.mode_multiport2_20g_mux || ctrl0.fields.mode_multiport2_20g_passthru) && 6076 (ctrl0.fields.mode_multiport1_10g1 && ctrl0.fields.mode_multiport1_10g2)) { 6077 *port += 1; 6078 } 6079 } else if (config.data_rate == SESTO_SPD_1G || config.data_rate == SESTO_SPD_10G || config.data_rate == SESTO_SPD_11G) { 6080 if (ip == SESTO_FALCON_CORE) { 6081 if (lane_mask == 0x1) { /* port 0 */ 6082 *port = 0; 6083 } else if (lane_mask == 0x2) { /* port 1 */ 6084 *port = 1; 6085 } else if (lane_mask == 0x4) { /* port 2 */ 6086 *port = 2; 6087 } else if (lane_mask == 0x8) { /* port 3 */ 6088 *port = 3; 6089 } 6090 } else { 6091 if (lane_mask == 0x1) { /* port 0 */ 6092 *port = 0; 6093 } else if (lane_mask == 0x2) { /* port 1 */ 6094 *port = 1; 6095 } else if (lane_mask == 0x10) { /* port 2 */ 6096 *port = 2; 6097 } else if (lane_mask == 0x20) { /* port 3 */ 6098 *port = 3; 6099 } else if ((lane_mask == 0x4) && (aux_mode->BCM84793_capablity)){ 6100 *port = 2; 6101 } else if ((lane_mask == 0x8) && (aux_mode->BCM84793_capablity)){ 6102 *port = 3; 6103 } 6104 } 6105 } 6106 6107 ERR: 6108 return rv; 6109 } 6110 int _sesto_module_write(const phymod_access_t *pa, uint32_t slv_dev_addr, uint32_t start_addr, 6111 uint32_t no_of_bytes, const uint8_t *write_data) 6112 { 6113 uint16_t lane_mask = 0; 6114 uint32_t index = 0; 6115 uint32_t lower_page_bytes = 0; 6116 uint32_t upper_page_bytes = 0; 6117 uint32_t upper_page_flag = 0; 6118 uint32_t lower_page_flag = 0; 6119 uint32_t lower_page_start_addr = 0; 6120 uint32_t upper_page_start_addr = 0; 6121 SES_GEN_CNTRLS_GEN_CONTROL3_TYPE_T gen_ctrl; 6122 uint16_t START_OF_NVRAM = 0x0; 6123 int rv = PHYMOD_E_NONE; 6124 6125 if(start_addr > 255) { 6126 return PHYMOD_E_PARAM; 6127 } 6128 /* qsfp mode or legacy mode */ 6129 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6130 gen_ctrl.fields.qsfp_mode = 1; 6131 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6132 6133 /* qsfp mode reset at begining */ 6134 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GEN_CONTROL1, modctrl_rstb, 0); 6135 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GEN_CONTROL1, modctrl_rstb, 1); 6136 6137 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 6138 if (lane_mask <= 0xF) { /* QSFP module 0 */ 6139 /* Active Low Select to read NVRAM for QSFP module 0 */ 6140 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6141 gen_ctrl.fields.qsfp_sel0b = 0; 6142 gen_ctrl.fields.qsfp_sel1b = 1; 6143 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6144 /* Module 0 NVRAM ADDR is SES_MODULE_CNTRL_RAM_NVR0_ADR */ 6145 START_OF_NVRAM = 0x0; 6146 } else if (lane_mask <= 0xF0) { /* QSFP module 1 */ 6147 /* Active Low Select to read NVRAM for QSFP module 1 */ 6148 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6149 gen_ctrl.fields.qsfp_sel0b = 1; 6150 gen_ctrl.fields.qsfp_sel1b = 0; 6151 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6152 /* Module 1 NVRAM ADDR is SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM*/ 6153 START_OF_NVRAM = 0x100; 6154 } 6155 6156 /* Configure the slave device ID default is 0x50 */ 6157 SESTO_CHIP_FIELD_WRITE(pa, SES_MODULE_CNTRL_DEV_ID, sl_dev_add, slv_dev_addr); 6158 6159 if(no_of_bytes == 0) { 6160 /* Perform module controller reset and FLUSH */ 6161 SESTO_IF_ERR_RETURN( 6162 _sesto_set_module_command(pa, 0, 0, 0, SESTO_FLUSH)); 6163 return rv; 6164 } 6165 /* if requested number of bytes are not within the boundary (0- 255) 6166 * need to calculate what maximum number of bytes can be taken into 6167 * account for reading or writing to module 6168 */ 6169 if ((no_of_bytes + start_addr) >= 256) { 6170 no_of_bytes = 255 - start_addr + 1; 6171 } 6172 6173 /* To determine page to be written is lower page or upper page or 6174 * both lower and upper page 6175 */ 6176 if ((start_addr + no_of_bytes - 1) > 127) { 6177 /* lower page */ 6178 if (start_addr <= 127) { 6179 lower_page_bytes = 127 - start_addr + 1; 6180 lower_page_flag = 1; 6181 lower_page_start_addr = start_addr; 6182 } 6183 /* upper page */ 6184 if ((start_addr + no_of_bytes) > 127) { 6185 upper_page_flag = 1; 6186 upper_page_bytes = no_of_bytes - lower_page_bytes; 6187 if(start_addr > 128) { 6188 upper_page_start_addr = start_addr; 6189 } else { 6190 upper_page_start_addr = 128; 6191 } 6192 } 6193 } else { /* only lower page */ 6194 lower_page_bytes = no_of_bytes; 6195 lower_page_flag = 1; 6196 lower_page_start_addr = start_addr; 6197 } 6198 6199 /* Wtite data to NVRAM */ 6200 for (index = 0; index < no_of_bytes; index++) { 6201 WRITE_SESTO_PMA_PMD_REG(pa, 6202 (SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + start_addr + index), write_data[index]); 6203 } 6204 6205 if(lower_page_flag) { 6206 SESTO_IF_ERR_RETURN( 6207 _sesto_set_module_command(pa, 0, 0, 0, SESTO_FLUSH)); 6208 for (index = 0; index < (lower_page_bytes / 4); index ++) { 6209 SESTO_IF_ERR_RETURN( 6210 _sesto_set_module_command(pa, SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + 6211 lower_page_start_addr + (4 * index), lower_page_start_addr + (4 * index), 3, SESTO_WRITE)); 6212 } 6213 if ((lower_page_bytes % 4) > 0) { 6214 SESTO_IF_ERR_RETURN( 6215 _sesto_set_module_command(pa, SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + 6216 lower_page_start_addr + (4 * index), lower_page_start_addr + (4 * index), 6217 ((lower_page_bytes % 4) - 1), SESTO_WRITE)); 6218 } 6219 lower_page_flag = 0; 6220 } 6221 6222 if(upper_page_flag) { 6223 SESTO_IF_ERR_RETURN( 6224 _sesto_set_module_command(pa, 0, 0, 0, SESTO_FLUSH)); 6225 for (index = 0; index < (upper_page_bytes / 4); index++) { 6226 SESTO_IF_ERR_RETURN( 6227 _sesto_set_module_command(pa, (SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + 6228 upper_page_start_addr + (4 * index)), upper_page_start_addr + (4 * index), 3, SESTO_WRITE)); 6229 } 6230 if ((upper_page_bytes%4) > 0) { 6231 SESTO_IF_ERR_RETURN( 6232 _sesto_set_module_command(pa, (SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + 6233 upper_page_start_addr + (4 * index)), upper_page_start_addr + (4 * index), 6234 ((upper_page_bytes % 4) - 1), SESTO_WRITE)); 6235 } 6236 upper_page_flag = 0; 6237 } 6238 6239 ERR: 6240 return rv; 6241 } 6242 6243 int _sesto_module_read(const phymod_access_t *pa, uint32_t slv_dev_addr, uint32_t start_addr, 6244 uint32_t no_of_bytes, uint8_t *read_data) 6245 { 6246 uint32_t index = 0; 6247 uint16_t lane_mask = 0; 6248 uint16_t rd_data = 0; 6249 uint32_t lower_page_bytes = 0; 6250 uint32_t upper_page_bytes = 0; 6251 uint32_t upper_page_flag = 0; 6252 uint32_t lower_page_start_addr = 0; 6253 uint32_t upper_page_start_addr = 0; 6254 uint32_t lower_page_flag = 0; 6255 uint16_t START_OF_NVRAM = 0x0; 6256 int rv = PHYMOD_E_NONE; 6257 SES_GEN_CNTRLS_GEN_CONTROL3_TYPE_T gen_ctrl; 6258 6259 if(start_addr > 255) { 6260 return PHYMOD_E_PARAM; 6261 } 6262 /* qsfp mode or legacy mode */ 6263 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6264 gen_ctrl.fields.qsfp_mode = 1; 6265 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6266 6267 /* qsfp mode reset at begining */ 6268 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GEN_CONTROL1, modctrl_rstb, 0); 6269 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_GEN_CONTROL1, modctrl_rstb, 1); 6270 6271 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 6272 if (lane_mask <= 0xF) { /* QSFP module 0 */ 6273 /* Active Low Select to read NVRAM for QSFP module 0 */ 6274 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6275 gen_ctrl.fields.qsfp_sel0b = 0; 6276 gen_ctrl.fields.qsfp_sel1b = 1; 6277 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6278 /* Module 0 NVRAM ADDR is SES_MODULE_CNTRL_RAM_NVR0_ADR */ 6279 START_OF_NVRAM = 0x0; 6280 } else if (lane_mask <= 0xF0) { /* QSFP module 1 */ 6281 /* Active Low Select to read NVRAM for QSFP module 1 */ 6282 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6283 gen_ctrl.fields.qsfp_sel0b = 1; 6284 gen_ctrl.fields.qsfp_sel1b = 0; 6285 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GEN_CONTROL3_ADR, gen_ctrl.data); 6286 /* Module 1 NVRAM ADDR is SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM*/ 6287 START_OF_NVRAM = 0x100; 6288 } 6289 6290 /* Configure the slave device ID default is 0x50 */ 6291 SESTO_CHIP_FIELD_WRITE(pa, SES_MODULE_CNTRL_DEV_ID, sl_dev_add, slv_dev_addr); 6292 6293 if(no_of_bytes == 0) { 6294 /* Perform module controller reset and FLUSH */ 6295 SESTO_IF_ERR_RETURN( 6296 _sesto_set_module_command(pa, 0, 0, 0, SESTO_FLUSH)); 6297 return rv; 6298 } 6299 if ((no_of_bytes + start_addr) >= 256) { 6300 no_of_bytes = 255 - start_addr + 1; 6301 } 6302 6303 /* To determine page to be written is lower page or upper page or 6304 * both lower and upper page 6305 */ 6306 if ((start_addr+no_of_bytes - 1) > 127) { 6307 /* lower page */ 6308 if (start_addr <= 127) { 6309 lower_page_bytes = 127 - start_addr + 1; 6310 lower_page_flag = 1; 6311 lower_page_start_addr = start_addr; 6312 } 6313 /* upper page */ 6314 if ((start_addr + no_of_bytes) > 127) { 6315 upper_page_flag = 1; 6316 upper_page_bytes = no_of_bytes - lower_page_bytes; 6317 if(start_addr > 128) { 6318 upper_page_start_addr = start_addr; 6319 } else { 6320 upper_page_start_addr = 128; 6321 } 6322 } 6323 } else { /* only lower page */ 6324 lower_page_bytes = no_of_bytes; 6325 lower_page_flag = 1; 6326 lower_page_start_addr = start_addr; 6327 } 6328 6329 if (lower_page_flag) { 6330 SESTO_IF_ERR_RETURN( 6331 _sesto_set_module_command(pa, 0, 0, 0, SESTO_FLUSH)); 6332 SESTO_IF_ERR_RETURN( 6333 _sesto_set_module_command(pa, SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + 6334 lower_page_start_addr, lower_page_start_addr, lower_page_bytes - 1, SESTO_RANDOM_ADDRESS_READ)); 6335 lower_page_flag = 0; 6336 } 6337 6338 /* Need to check with chip team how we can read upper page */ 6339 if (upper_page_flag) { 6340 SESTO_IF_ERR_RETURN( 6341 _sesto_set_module_command(pa, 0, 0, 0, SESTO_FLUSH)); 6342 SESTO_IF_ERR_RETURN( 6343 _sesto_set_module_command(pa, SES_MODULE_CNTRL_RAM_NVR0_ADR + START_OF_NVRAM + 6344 upper_page_start_addr, upper_page_start_addr, upper_page_bytes - 1, SESTO_RANDOM_ADDRESS_READ)); 6345 upper_page_flag = 0; 6346 } 6347 6348 /* Read data from NVRAM */ 6349 for (index = 0; index < no_of_bytes; index++) { 6350 READ_SESTO_PMA_PMD_REG(pa, (SES_MODULE_CNTRL_RAM_NVR0_ADR + start_addr + index), rd_data); 6351 read_data[index] = (unsigned char) (rd_data & 0xff); 6352 } 6353 6354 ERR: 6355 return rv; 6356 } 6357 6358 int _sesto_set_module_command(const phymod_access_t *pa, uint16_t xfer_addr, 6359 uint32_t slv_addr, unsigned char xfer_cnt, SESTO_I2CM_CMD_E cmd) 6360 { 6361 SES_MODULE_CNTRL_STATUS_TYPE_T mctrl_status; 6362 uint16_t retry_count = 500; 6363 uint32_t wait_timeout_us = 0; 6364 int rv = PHYMOD_E_NONE; 6365 wait_timeout_us = ((2*(xfer_cnt+1))*100)/5; 6366 6367 if (cmd == SESTO_FLUSH) { 6368 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_CONTROL_ADR, 0xC000); 6369 } else { 6370 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_XFER_ADDRESS_ADR, xfer_addr); 6371 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_XFER_COUNT_ADR, xfer_cnt); 6372 6373 if (cmd == SESTO_CURRENT_ADDRESS_READ) { 6374 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_CONTROL_ADR, 0x8001); 6375 } else if (cmd == SESTO_RANDOM_ADDRESS_READ ) { 6376 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_ADDRESS_ADR, slv_addr); 6377 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_CONTROL_ADR, 0x8003); 6378 } else { 6379 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_ADDRESS_ADR, slv_addr); 6380 WRITE_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_CONTROL_ADR, 0x8022); 6381 } 6382 } 6383 6384 if ((cmd == SESTO_CURRENT_ADDRESS_READ) || 6385 (cmd == SESTO_RANDOM_ADDRESS_READ) || 6386 (cmd == SESTO_WRITE)) { 6387 do { 6388 READ_SESTO_PMA_PMD_REG(pa, SES_MODULE_CNTRL_STATUS_ADR, mctrl_status.data); 6389 PHYMOD_USLEEP(wait_timeout_us); 6390 } while((mctrl_status.fields.xaction_done == 0) && --retry_count); 6391 if(!retry_count) { 6392 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, (_PHYMOD_MSG("Module controller: I2C transaction failed.."))); 6393 } 6394 } 6395 6396 ERR: 6397 return rv; 6398 } 6399 6400 int _sesto_gpio_config_set(const phymod_access_t *pa, int pin_number, phymod_gpio_mode_t gpio_mode) 6401 { 6402 int rv = PHYMOD_E_NONE; 6403 SES_PAD_CTRL_GPIO_0_CONTROL_TYPE_T pad_ctrl_gpio_ctrl; 6404 6405 PHYMOD_MEMSET(&pad_ctrl_gpio_ctrl, 0 , sizeof(SES_PAD_CTRL_GPIO_0_CONTROL_TYPE_T)); 6406 if (pin_number > 3) { 6407 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 6408 (_PHYMOD_MSG("Invalid GPIO pin selected, Valid GPIOs are (0 - 3)"))); 6409 } 6410 6411 READ_SESTO_PMA_PMD_REG(pa, 6412 (SES_PAD_CTRL_GPIO_0_CONTROL_ADR + (pin_number * 2)), 6413 pad_ctrl_gpio_ctrl.data); 6414 6415 switch (gpio_mode) { 6416 case phymodGpioModeDisabled: 6417 return rv; 6418 case phymodGpioModeOutput: 6419 pad_ctrl_gpio_ctrl.fields.gpio_0_oeb = 0; 6420 break; 6421 case phymodGpioModeInput: 6422 pad_ctrl_gpio_ctrl.fields.gpio_0_oeb = 1; 6423 break; 6424 default: 6425 return PHYMOD_E_PARAM; 6426 } 6427 6428 WRITE_SESTO_PMA_PMD_REG(pa, 6429 (SES_PAD_CTRL_GPIO_0_CONTROL_ADR + (pin_number * 2)), 6430 pad_ctrl_gpio_ctrl.data); 6431 ERR: 6432 return rv; 6433 } 6434 6435 int _sesto_gpio_config_get(const phymod_access_t *pa, int pin_number, phymod_gpio_mode_t* gpio_mode) 6436 { 6437 int rv = PHYMOD_E_NONE; 6438 SES_PAD_CTRL_GPIO_0_CONTROL_TYPE_T pad_ctrl_gpio_ctrl; 6439 6440 PHYMOD_MEMSET(&pad_ctrl_gpio_ctrl, 0 , sizeof(SES_PAD_CTRL_GPIO_0_CONTROL_TYPE_T)); 6441 if (pin_number > 3) { 6442 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 6443 (_PHYMOD_MSG("Invalid GPIO pin selected, Valid GPIOs are (0 - 3)"))); 6444 } 6445 6446 READ_SESTO_PMA_PMD_REG(pa, 6447 (SES_PAD_CTRL_GPIO_0_CONTROL_ADR + (pin_number * 2)), 6448 pad_ctrl_gpio_ctrl.data); 6449 6450 switch(pad_ctrl_gpio_ctrl.fields.gpio_0_oeb) { 6451 case 0: 6452 *gpio_mode = phymodGpioModeOutput; 6453 break; 6454 case 1: 6455 *gpio_mode = phymodGpioModeInput; 6456 break; 6457 default: 6458 break; 6459 } 6460 6461 ERR: 6462 return rv; 6463 } 6464 6465 int _sesto_gpio_pin_value_set(const phymod_access_t *pa, int pin_number, int value) 6466 { 6467 int rv = PHYMOD_E_NONE; 6468 SES_PAD_CTRL_GPIO_0_CONTROL_TYPE_T pad_ctrl_gpio_ctrl; 6469 6470 PHYMOD_MEMSET(&pad_ctrl_gpio_ctrl, 0 , sizeof(SES_PAD_CTRL_GPIO_0_CONTROL_TYPE_T)); 6471 if (pin_number > 3) { 6472 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 6473 (_PHYMOD_MSG("Invalid GPIO pin selected, Valid GPIOs are (0 - 3)"))); 6474 } 6475 READ_SESTO_PMA_PMD_REG(pa, 6476 (SES_PAD_CTRL_GPIO_0_CONTROL_ADR + (pin_number * 2)), 6477 pad_ctrl_gpio_ctrl.data); 6478 6479 pad_ctrl_gpio_ctrl.fields.gpio_0_ibof = 1; 6480 pad_ctrl_gpio_ctrl.fields.gpio_0_out_frcval = value ? 1 : 0; 6481 6482 WRITE_SESTO_PMA_PMD_REG(pa, 6483 (SES_PAD_CTRL_GPIO_0_CONTROL_ADR + (pin_number * 2)), 6484 pad_ctrl_gpio_ctrl.data); 6485 ERR: 6486 return rv; 6487 } 6488 6489 int _sesto_gpio_pin_value_get(const phymod_access_t *pa, int pin_number, int* value) 6490 { 6491 int rv = PHYMOD_E_NONE; 6492 SES_PAD_CTRL_GPIO_0_STATUS_TYPE_T pad_sts_gpio; 6493 6494 PHYMOD_MEMSET(&pad_sts_gpio, 0, sizeof(SES_PAD_CTRL_GPIO_0_STATUS_TYPE_T)); 6495 if (pin_number > 3) { 6496 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 6497 (_PHYMOD_MSG("Invalid GPIO pin selected, Valid GPIOs are (0 - 3)"))); 6498 } 6499 6500 READ_SESTO_PMA_PMD_REG(pa, 6501 (SES_PAD_CTRL_GPIO_0_STATUS_ADR + (pin_number * 2)), 6502 pad_sts_gpio.data); 6503 *value = pad_sts_gpio.fields.gpio_0_din; 6504 6505 ERR: 6506 return rv; 6507 } 6508 6509 int _sesto_phy_repeater_mode_set(const phymod_phy_access_t *phy, phymod_operation_mode_t repeater_mode) 6510 { 6511 phymod_phy_inf_config_t config; 6512 uint16_t ip = 0; 6513 uint16_t port = 0; 6514 uint16_t data = 0, retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 6515 int rv = PHYMOD_E_NONE; 6516 SESTO_DEVICE_AUX_MODE_T *aux_mode; 6517 SES_GEN_CNTRLS_GPREG11_TYPE_T gpreg11; 6518 const phymod_access_t *pa = &phy->access; 6519 6520 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 6521 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 6522 aux_mode = config.device_aux_modes; 6523 6524 SESTO_IF_ERR_RETURN( 6525 _sesto_phy_interface_config_get(phy, 0, &config)); 6526 6527 ip = aux_mode->passthru_sys_side_core ? SESTO_MERLIN_CORE : SESTO_FALCON_CORE; 6528 6529 /* ip == SESTO_MERLIN_CORE, line sie core is SESTO_FALCON_CORE */ 6530 PHYMOD_DEBUG_VERBOSE(("%s:: IP:%s \n", __func__, 6531 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON")); 6532 PHYMOD_MEMSET(&gpreg11, 0, sizeof(SES_GEN_CNTRLS_GPREG11_TYPE_T)); 6533 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 6534 6535 SESTO_IF_ERR_RETURN( 6536 _sesto_port_from_lane_map_get(phy, &config, &port)); 6537 6538 6539 if (ip == SESTO_FALCON_CORE) { 6540 if (!repeater_mode) { 6541 gpreg11.fields.dis_rptr_20g_to_10g |= (0x1 << port); 6542 } else { 6543 gpreg11.fields.dis_rptr_20g_to_10g &= ~(0x1 << port); 6544 } 6545 } else { 6546 if (!repeater_mode) { 6547 gpreg11.fields.dis_rptr_10g_to_20g |= (0x1 << port); 6548 } else { 6549 gpreg11.fields.dis_rptr_10g_to_20g &= ~(0x1 << port); 6550 } 6551 } 6552 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_GPREG11_ADR, gpreg11.data); 6553 6554 /* Set FW_ENABLE = 1 */ 6555 SESTO_CHIP_FIELD_WRITE(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, 1); 6556 do { 6557 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data); 6558 } while ((data != 0) && (retry_cnt --)); 6559 if (retry_cnt == 0) { 6560 SESTO_RETURN_WITH_ERR(PHYMOD_E_CONFIG, 6561 (_PHYMOD_MSG("repeater_mode_set failed, micro controller is busy.."))); 6562 } 6563 6564 ERR: 6565 PHYMOD_FREE(config.device_aux_modes); 6566 6567 return rv; 6568 } 6569 int _sesto_core_cfg_tx_set(const phymod_phy_access_t *phy,const phymod_tx_t* tx) 6570 { 6571 phymod_tx_t tmp_tx; 6572 int rv = PHYMOD_E_NONE; 6573 6574 PHYMOD_MEMSET(&tmp_tx,0x0,sizeof(phymod_tx_t)); 6575 SESTO_IF_ERR_RETURN( 6576 _sesto_tx_get(phy,&tmp_tx)); 6577 if (!(((tx->main & 0x7F) == 0x7F) && ((tx->pre & 0x7F) == 0x7F) && ((tx->post & 0x7F) == 0x7F))) { 6578 tmp_tx.pre = tx->pre; 6579 tmp_tx.main = tx->main; 6580 tmp_tx.post = tx->post; 6581 6582 } 6583 tmp_tx.amp = tx->amp; 6584 SESTO_IF_ERR_RETURN( 6585 _sesto_tx_set(phy,&tmp_tx)); 6586 6587 ERR: 6588 return rv; 6589 } 6590 6591 int _sesto_core_cfg_polarity_set(const phymod_phy_access_t *phy, uint32_t tx_polarity, uint32_t rx_polarity) 6592 { 6593 phymod_phy_inf_config_t config; 6594 uint16_t ip = 0; 6595 uint16_t lane = 0; 6596 uint16_t lane_mask = 0, max_lane = 0; 6597 uint32_t rx_lane_polarity = 0; 6598 uint32_t tx_lane_polarity = 0; 6599 int rv = PHYMOD_E_NONE; 6600 const phymod_access_t *pa = &phy->access; 6601 6602 if (rx_polarity == 0 && tx_polarity == 0) { 6603 return rv; 6604 } 6605 6606 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 6607 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 6608 SESTO_IF_ERR_RETURN( 6609 _sesto_phy_interface_config_get(phy, 0, &config)); 6610 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 6611 SESTO_GET_IP(phy, config, ip); 6612 6613 max_lane = (ip == SESTO_FALCON_CORE) ? 6614 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 6615 6616 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 6617 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 6618 6619 for (lane = 0; lane < max_lane; lane ++) { 6620 if (lane_mask & (1 << lane)) { 6621 SESTO_IF_ERR_RETURN( 6622 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, 6623 ip, SESTO_DEV_PMA_PMD, 0, lane)); 6624 if (rx_polarity != 0) { 6625 rx_lane_polarity = (rx_polarity >> lane) & 0x1; 6626 } 6627 if (tx_polarity != 0) { 6628 tx_lane_polarity = (tx_polarity >> lane) & 0x1; 6629 } 6630 if (ip == SESTO_FALCON_CORE) { 6631 /* FALCON polarity inversion */ 6632 PHYMOD_DEBUG_VERBOSE(("Falcon polarity inversion set\n")); 6633 if (tx_lane_polarity) { 6634 /* Write to Tx misc config register */ 6635 SESTO_CHIP_FIELD_WRITE(pa, F25G_TLB_TX_TLB_TX_MISC_CONFIG, 6636 tx_pmd_dp_invert, tx_lane_polarity); 6637 } 6638 if (rx_lane_polarity) { 6639 /* Write to Rx misc config register */ 6640 SESTO_CHIP_FIELD_WRITE(pa, F25G_TLB_RX_TLB_RX_MISC_CONFIG, 6641 rx_pmd_dp_invert, rx_lane_polarity); 6642 } 6643 } else { 6644 /* MERLIN polarity inversion */ 6645 PHYMOD_DEBUG_VERBOSE(("Merlin polarity inversion set\n")); 6646 if (tx_lane_polarity) { 6647 /* Write to Tx misc config register */ 6648 SESTO_CHIP_FIELD_WRITE(pa, M10G_TLB_TX_TLB_TX_MISC_CONFIG, 6649 tx_pmd_dp_invert, tx_lane_polarity); 6650 } 6651 if (rx_lane_polarity) { 6652 /* Write to Rx misc config register */ 6653 SESTO_CHIP_FIELD_WRITE(pa, M10G_TLB_RX_TLB_RX_MISC_CONFIG, 6654 rx_pmd_dp_invert, rx_lane_polarity); 6655 } 6656 } 6657 } 6658 } 6659 ERR: 6660 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 6661 PHYMOD_FREE(config.device_aux_modes); 6662 6663 return rv; 6664 } 6665 6666 err_code_t _sesto_merlin_read_pll_range(const phymod_access_t *pa, uint32_t *pll_range) 6667 { 6668 err_code_t __err; 6669 __err=ERR_CODE_NONE; 6670 *pll_range = rdc_pll_range(); 6671 return (ERR_CODE_NONE); 6672 } 6673 err_code_t _sesto_falcon_read_pll_range(const phymod_access_t *pa, uint32_t *pll_range) 6674 { 6675 err_code_t __err; 6676 __err=ERR_CODE_NONE; 6677 *pll_range = rdc_falcon_furia_sesto_ams_pll_range(); 6678 return (ERR_CODE_NONE); 6679 } 6680 6681 int _sesto_firmware_lane_config_set(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t fw_config) 6682 { 6683 uint16_t ip = 0, data = 0; 6684 SESTO_DEVICE_AUX_MODE_T *aux_mode; 6685 SES_GEN_CNTRLS_MICRO_SYNC_5_TYPE_T intf_sel_p0_p1; 6686 SES_GEN_CNTRLS_MICRO_SYNC_6_TYPE_T intf_sel_p2_p3; 6687 phymod_phy_inf_config_t config; 6688 const phymod_access_t *pa = &phy->access; 6689 uint16_t retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 6690 uint16_t port = 0, no_of_ports = 0; 6691 int rv = PHYMOD_E_NONE; 6692 6693 PHYMOD_MEMSET(&intf_sel_p0_p1, 0, sizeof(intf_sel_p0_p1)); 6694 PHYMOD_MEMSET(&intf_sel_p2_p3, 0, sizeof(intf_sel_p2_p3)); 6695 6696 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 6697 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 6698 SESTO_IF_ERR_RETURN( 6699 _sesto_phy_interface_config_get(phy, 0, &config)); 6700 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)config.device_aux_modes; 6701 SESTO_GET_IP(phy, config, ip); 6702 SESTO_GET_PORT_FROM_MODE((&config), no_of_ports, aux_mode); 6703 SESTO_IF_ERR_RETURN(_sesto_port_from_lane_map_get(phy, &config, &port)); 6704 6705 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6706 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6707 if (no_of_ports == 1) { /* 100G/40GPT */ 6708 if (ip == SESTO_MERLIN_CORE) { 6709 if (fw_config.UnreliableLos) { 6710 intf_sel_p0_p1.fields.p0_10g_media_type = 3; 6711 } else { 6712 intf_sel_p0_p1.fields.p0_10g_media_type = fw_config.MediaType; 6713 } 6714 intf_sel_p0_p1.fields.p0_10g_dfe_on = fw_config.DfeOn; 6715 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6716 } else { 6717 if (fw_config.UnreliableLos) { 6718 intf_sel_p0_p1.fields.p0_20g_media_type = 3; 6719 } else { 6720 intf_sel_p0_p1.fields.p0_20g_media_type = fw_config.MediaType; 6721 } 6722 intf_sel_p0_p1.fields.p0_20g_dfe_on = fw_config.DfeOn; 6723 intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode = fw_config.LpDfeOn; 6724 intf_sel_p0_p1.fields.p0_scrambling_dis = fw_config.ScramblingDisable; 6725 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6726 } 6727 } else if (no_of_ports == 2) { /* 40GMUX/20GMUX/20PT */ 6728 if (port == 0) { 6729 if (ip == SESTO_MERLIN_CORE) { 6730 if (fw_config.UnreliableLos) { 6731 intf_sel_p0_p1.fields.p0_10g_media_type = 3; 6732 } else { 6733 intf_sel_p0_p1.fields.p0_10g_media_type = fw_config.MediaType; 6734 } 6735 intf_sel_p0_p1.fields.p0_10g_dfe_on = fw_config.DfeOn; 6736 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6737 } else { 6738 if (fw_config.UnreliableLos) { 6739 intf_sel_p0_p1.fields.p0_20g_media_type = 3; 6740 } else { 6741 intf_sel_p0_p1.fields.p0_20g_media_type = fw_config.MediaType; 6742 } 6743 intf_sel_p0_p1.fields.p0_20g_dfe_on = fw_config.DfeOn; 6744 intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode = fw_config.LpDfeOn; 6745 intf_sel_p0_p1.fields.p0_scrambling_dis = fw_config.ScramblingDisable; 6746 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6747 } 6748 } else { 6749 if (ip == SESTO_MERLIN_CORE) { 6750 if (fw_config.UnreliableLos) { 6751 intf_sel_p2_p3.fields.p2_10g_media_type = 3; 6752 } else { 6753 intf_sel_p2_p3.fields.p2_10g_media_type = fw_config.MediaType; 6754 } 6755 intf_sel_p2_p3.fields.p2_10g_dfe_on = fw_config.DfeOn; 6756 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6757 } else { 6758 if (fw_config.UnreliableLos) { 6759 intf_sel_p2_p3.fields.p2_20g_media_type = 3; 6760 } else { 6761 intf_sel_p2_p3.fields.p2_20g_media_type = fw_config.MediaType; 6762 } 6763 intf_sel_p2_p3.fields.p2_20g_dfe_on = fw_config.DfeOn; 6764 intf_sel_p2_p3.fields.p2_20g_dfe_lp_mode = fw_config.LpDfeOn; 6765 intf_sel_p2_p3.fields.p2_scrambling_dis = fw_config.ScramblingDisable; 6766 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6767 } 6768 } 6769 } else { /* 10G */ 6770 if (port == 0) { 6771 if (ip == SESTO_MERLIN_CORE) { 6772 if (fw_config.UnreliableLos) { 6773 intf_sel_p0_p1.fields.p0_10g_media_type = 3; 6774 } else { 6775 intf_sel_p0_p1.fields.p0_10g_media_type = fw_config.MediaType; 6776 } 6777 intf_sel_p0_p1.fields.p0_10g_dfe_on = fw_config.DfeOn; 6778 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6779 } else { 6780 if (fw_config.UnreliableLos) { 6781 intf_sel_p0_p1.fields.p0_20g_media_type = 3; 6782 } else { 6783 intf_sel_p0_p1.fields.p0_20g_media_type = fw_config.MediaType; 6784 } 6785 intf_sel_p0_p1.fields.p0_20g_dfe_on = fw_config.DfeOn; 6786 intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode = fw_config.LpDfeOn; 6787 intf_sel_p0_p1.fields.p0_scrambling_dis = fw_config.ScramblingDisable; 6788 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6789 } 6790 } else if (port == 1) { 6791 if (ip == SESTO_MERLIN_CORE) { 6792 if (fw_config.UnreliableLos) { 6793 intf_sel_p0_p1.fields.p1_10g_media_type = 3; 6794 } else { 6795 intf_sel_p0_p1.fields.p1_10g_media_type = fw_config.MediaType; 6796 } 6797 intf_sel_p0_p1.fields.p1_10g_dfe_on = fw_config.DfeOn; 6798 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6799 } else { 6800 if (fw_config.UnreliableLos) { 6801 intf_sel_p0_p1.fields.p1_20g_media_type = 3; 6802 } else { 6803 intf_sel_p0_p1.fields.p1_20g_media_type = fw_config.MediaType; 6804 } 6805 intf_sel_p0_p1.fields.p1_20g_dfe_on = fw_config.DfeOn; 6806 intf_sel_p0_p1.fields.p1_20g_dfe_lp_mode = fw_config.LpDfeOn; 6807 intf_sel_p0_p1.fields.p1_scrambling_dis = fw_config.ScramblingDisable; 6808 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6809 } 6810 } else if (port == 2) { 6811 if (ip == SESTO_MERLIN_CORE) { 6812 if (fw_config.UnreliableLos) { 6813 intf_sel_p2_p3.fields.p2_10g_media_type = 3; 6814 } else { 6815 intf_sel_p2_p3.fields.p2_10g_media_type = fw_config.MediaType; 6816 } 6817 intf_sel_p2_p3.fields.p2_10g_dfe_on = fw_config.DfeOn; 6818 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6819 } else { 6820 if (fw_config.UnreliableLos) { 6821 intf_sel_p2_p3.fields.p2_20g_media_type = 3; 6822 } else { 6823 intf_sel_p2_p3.fields.p2_20g_media_type = fw_config.MediaType; 6824 } 6825 intf_sel_p2_p3.fields.p2_20g_dfe_on = fw_config.DfeOn; 6826 intf_sel_p2_p3.fields.p2_20g_dfe_lp_mode = fw_config.LpDfeOn; 6827 intf_sel_p2_p3.fields.p2_scrambling_dis = fw_config.ScramblingDisable; 6828 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6829 } 6830 } else { 6831 if (ip == SESTO_MERLIN_CORE) { 6832 if (fw_config.UnreliableLos) { 6833 intf_sel_p2_p3.fields.p3_10g_media_type = 3; 6834 } else { 6835 intf_sel_p2_p3.fields.p3_10g_media_type = fw_config.MediaType; 6836 } 6837 intf_sel_p2_p3.fields.p3_10g_dfe_on = fw_config.DfeOn; 6838 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6839 } else { 6840 if (fw_config.UnreliableLos) { 6841 intf_sel_p2_p3.fields.p3_20g_media_type = 3; 6842 } else { 6843 intf_sel_p2_p3.fields.p3_20g_media_type = fw_config.MediaType; 6844 } 6845 intf_sel_p2_p3.fields.p3_20g_dfe_on = fw_config.DfeOn; 6846 intf_sel_p2_p3.fields.p3_20g_dfe_lp_mode = fw_config.LpDfeOn; 6847 intf_sel_p2_p3.fields.p3_scrambling_dis = fw_config.ScramblingDisable; 6848 WRITE_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6849 } 6850 } 6851 } 6852 6853 /*Setting the FW Enable to 1*/ 6854 SESTO_IF_ERR_RETURN( _sesto_fw_enable(pa, 1)); 6855 6856 retry_cnt = SESTO_FW_DLOAD_RETRY_CNT; 6857 do { 6858 SESTO_CHIP_FIELD_READ(pa, SES_GEN_CNTRLS_FIRMWARE_ENABLE, fw_enable_val, data); 6859 retry_cnt--; 6860 } while ((data != 0) && (retry_cnt)); 6861 6862 if (retry_cnt == 0) { 6863 PHYMOD_DEBUG_VERBOSE(("WARN:: FW Enable not cleared\n")); 6864 goto ERR; 6865 } 6866 6867 ERR: 6868 PHYMOD_FREE(config.device_aux_modes); 6869 return rv; 6870 } 6871 6872 int _sesto_firmware_lane_config_get(const phymod_phy_access_t* phy, phymod_firmware_lane_config_t* fw_config) 6873 { 6874 uint16_t ip = 0; 6875 SESTO_DEVICE_AUX_MODE_T *aux_mode; 6876 SES_GEN_CNTRLS_MICRO_SYNC_5_TYPE_T intf_sel_p0_p1; 6877 SES_GEN_CNTRLS_MICRO_SYNC_6_TYPE_T intf_sel_p2_p3; 6878 phymod_phy_inf_config_t config; 6879 const phymod_access_t *pa = &phy->access; 6880 uint16_t port = 0, no_of_ports = 0; 6881 int rv = PHYMOD_E_NONE; 6882 6883 PHYMOD_MEMSET(&intf_sel_p0_p1, 0, sizeof(intf_sel_p0_p1)); 6884 PHYMOD_MEMSET(&intf_sel_p2_p3, 0, sizeof(intf_sel_p2_p3)); 6885 6886 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 6887 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 6888 SESTO_IF_ERR_RETURN( 6889 _sesto_phy_interface_config_get(phy, 0, &config)); 6890 aux_mode = (SESTO_DEVICE_AUX_MODE_T*)config.device_aux_modes; 6891 SESTO_GET_IP(phy, config, ip); 6892 SESTO_GET_PORT_FROM_MODE((&config), no_of_ports, aux_mode); 6893 SESTO_IF_ERR_RETURN(_sesto_port_from_lane_map_get(phy, &config, &port)); 6894 6895 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_5_ADR, intf_sel_p0_p1.data); 6896 READ_SESTO_PMA_PMD_REG(pa, SES_GEN_CNTRLS_MICRO_SYNC_6_ADR, intf_sel_p2_p3.data); 6897 if (no_of_ports == 1) { /* 100G/40GPT */ 6898 if (ip == SESTO_MERLIN_CORE) { 6899 if (intf_sel_p0_p1.fields.p0_10g_media_type == 3) { 6900 fw_config->UnreliableLos = 1; 6901 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6902 } else { 6903 fw_config->MediaType = intf_sel_p0_p1.fields.p0_10g_media_type; 6904 } 6905 fw_config->DfeOn = intf_sel_p0_p1.fields.p0_10g_dfe_on; 6906 } else { 6907 if (intf_sel_p0_p1.fields.p0_20g_media_type == 3) { 6908 fw_config->UnreliableLos = 1; 6909 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6910 } else { 6911 fw_config->MediaType = intf_sel_p0_p1.fields.p0_20g_media_type; 6912 } 6913 fw_config->DfeOn = intf_sel_p0_p1.fields.p0_20g_dfe_on; 6914 fw_config->LpDfeOn = intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode; 6915 fw_config->ScramblingDisable = intf_sel_p0_p1.fields.p0_scrambling_dis; 6916 } 6917 } else if (no_of_ports == 2) { /* 40GMUX/20GMUX/20PT */ 6918 if (port == 0) { 6919 if (ip == SESTO_MERLIN_CORE) { 6920 if (intf_sel_p0_p1.fields.p0_10g_media_type == 3) { 6921 fw_config->UnreliableLos = 1; 6922 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6923 } else { 6924 fw_config->MediaType = intf_sel_p0_p1.fields.p0_10g_media_type; 6925 } 6926 fw_config->DfeOn = intf_sel_p0_p1.fields.p0_10g_dfe_on; 6927 } else { 6928 if (intf_sel_p0_p1.fields.p0_20g_media_type == 3) { 6929 fw_config->UnreliableLos = 1; 6930 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6931 } else { 6932 fw_config->MediaType = intf_sel_p0_p1.fields.p0_20g_media_type; 6933 } 6934 fw_config->DfeOn = intf_sel_p0_p1.fields.p0_20g_dfe_on; 6935 fw_config->LpDfeOn = intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode; 6936 fw_config->ScramblingDisable = intf_sel_p0_p1.fields.p0_scrambling_dis; 6937 } 6938 } else { 6939 if (ip == SESTO_MERLIN_CORE) { 6940 if (intf_sel_p2_p3.fields.p2_10g_media_type == 3) { 6941 fw_config->UnreliableLos = 1; 6942 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6943 } else { 6944 fw_config->MediaType = intf_sel_p2_p3.fields.p2_10g_media_type; 6945 } 6946 fw_config->DfeOn = intf_sel_p2_p3.fields.p2_10g_dfe_on; 6947 } else { 6948 if (intf_sel_p2_p3.fields.p2_20g_media_type == 3) { 6949 fw_config->UnreliableLos = 1; 6950 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6951 } else { 6952 fw_config->MediaType = intf_sel_p2_p3.fields.p2_20g_media_type; 6953 } 6954 fw_config->DfeOn = intf_sel_p2_p3.fields.p2_20g_dfe_on; 6955 fw_config->LpDfeOn = intf_sel_p2_p3.fields.p2_20g_dfe_lp_mode; 6956 fw_config->ScramblingDisable = intf_sel_p2_p3.fields.p2_scrambling_dis; 6957 } 6958 } 6959 } else { /* 10G */ 6960 if (port == 0) { 6961 if (ip == SESTO_MERLIN_CORE) { 6962 if (intf_sel_p0_p1.fields.p0_10g_media_type == 3) { 6963 fw_config->UnreliableLos = 1; 6964 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6965 } else { 6966 fw_config->MediaType = intf_sel_p0_p1.fields.p0_10g_media_type; 6967 } 6968 fw_config->DfeOn = intf_sel_p0_p1.fields.p0_10g_dfe_on; 6969 } else { 6970 if (intf_sel_p0_p1.fields.p0_20g_media_type == 3) { 6971 fw_config->UnreliableLos = 1; 6972 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6973 } else { 6974 fw_config->MediaType = intf_sel_p0_p1.fields.p0_20g_media_type; 6975 } 6976 fw_config->DfeOn = intf_sel_p0_p1.fields.p0_20g_dfe_on; 6977 fw_config->LpDfeOn = intf_sel_p0_p1.fields.p0_20g_dfe_lp_mode; 6978 fw_config->ScramblingDisable = intf_sel_p0_p1.fields.p0_scrambling_dis; 6979 } 6980 } else if (port == 1) { 6981 if (ip == SESTO_MERLIN_CORE) { 6982 if (intf_sel_p0_p1.fields.p1_10g_media_type == 3) { 6983 fw_config->UnreliableLos = 1; 6984 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6985 } else { 6986 fw_config->MediaType = intf_sel_p0_p1.fields.p1_10g_media_type; 6987 } 6988 fw_config->DfeOn = intf_sel_p0_p1.fields.p1_10g_dfe_on; 6989 } else { 6990 if (intf_sel_p0_p1.fields.p1_20g_media_type == 3) { 6991 fw_config->UnreliableLos = 1; 6992 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 6993 } else { 6994 fw_config->MediaType = intf_sel_p0_p1.fields.p1_20g_media_type; 6995 } 6996 fw_config->DfeOn = intf_sel_p0_p1.fields.p1_20g_dfe_on; 6997 fw_config->LpDfeOn = intf_sel_p0_p1.fields.p1_20g_dfe_lp_mode; 6998 fw_config->ScramblingDisable = intf_sel_p0_p1.fields.p1_scrambling_dis; 6999 } 7000 } else if (port == 2) { 7001 if (ip == SESTO_MERLIN_CORE) { 7002 if (intf_sel_p2_p3.fields.p2_10g_media_type == 3) { 7003 fw_config->UnreliableLos = 1; 7004 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 7005 } else { 7006 fw_config->MediaType = intf_sel_p2_p3.fields.p2_10g_media_type; 7007 } 7008 fw_config->DfeOn = intf_sel_p2_p3.fields.p2_10g_dfe_on; 7009 } else { 7010 if (intf_sel_p2_p3.fields.p2_20g_media_type == 3) { 7011 fw_config->UnreliableLos = 1; 7012 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 7013 } else { 7014 fw_config->MediaType = intf_sel_p2_p3.fields.p2_20g_media_type; 7015 } 7016 fw_config->DfeOn = intf_sel_p2_p3.fields.p2_20g_dfe_on; 7017 fw_config->LpDfeOn = intf_sel_p2_p3.fields.p2_20g_dfe_lp_mode; 7018 fw_config->ScramblingDisable = intf_sel_p2_p3.fields.p2_scrambling_dis; 7019 } 7020 } else { 7021 if (ip == SESTO_MERLIN_CORE) { 7022 if (intf_sel_p2_p3.fields.p3_10g_media_type == 3) { 7023 fw_config->UnreliableLos = 1; 7024 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 7025 } else { 7026 fw_config->MediaType = intf_sel_p2_p3.fields.p3_10g_media_type; 7027 } 7028 fw_config->DfeOn = intf_sel_p2_p3.fields.p3_10g_dfe_on; 7029 } else { 7030 if (intf_sel_p2_p3.fields.p3_20g_media_type) { 7031 fw_config->UnreliableLos = 1; 7032 fw_config->MediaType = phymodFirmwareMediaTypeOptics; 7033 } else { 7034 fw_config->MediaType = intf_sel_p2_p3.fields.p3_20g_media_type; 7035 } 7036 fw_config->DfeOn = intf_sel_p2_p3.fields.p3_20g_dfe_on; 7037 fw_config->LpDfeOn = intf_sel_p2_p3.fields.p3_20g_dfe_lp_mode; 7038 fw_config->ScramblingDisable = intf_sel_p2_p3.fields.p2_scrambling_dis; 7039 } 7040 } 7041 } 7042 7043 ERR: 7044 PHYMOD_FREE(config.device_aux_modes); 7045 return rv; 7046 } 7047 7048 int _sesto_phy_short_channel_mode_set(const phymod_phy_access_t *phy, uint32_t enable) 7049 { 7050 phymod_phy_inf_config_t config; 7051 uint16_t data = 0; 7052 uint16_t ip = 0, lane = 0; 7053 uint16_t lane_mask = 0, max_lane = 0; 7054 const phymod_access_t *pa = &phy->access; 7055 int rv = PHYMOD_E_NONE; 7056 7057 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 7058 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 7059 SESTO_IF_ERR_RETURN( 7060 _sesto_phy_interface_config_get(phy, 0, &config)); 7061 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 7062 SESTO_GET_IP(phy, config, ip); 7063 7064 max_lane = (ip == SESTO_FALCON_CORE) ? 7065 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 7066 7067 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 7068 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 7069 7070 if (ip == SESTO_MERLIN_CORE) { 7071 /* short_channel_mode can performed only on falcon side */ 7072 return PHYMOD_E_PARAM; 7073 } 7074 7075 for (lane = 0; lane < max_lane; lane ++) { 7076 if (lane_mask & (1 << lane)) { 7077 SESTO_IF_ERR_RETURN( 7078 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, SESTO_DEV_PMA_PMD, 0, lane)); 7079 /* put the lane under dp reset */ 7080 SESTO_CHIP_FIELD_WRITE(pa, F25G_CKRST_CTRL_RPTR_LANE_CLK_RESET_N_POWERDOWN_CONTROL, ln_dp_s_rstb, 0); 7081 /* config RAM variable */ 7082 SESTO_CHIP_FIELD_WRITE(pa, SES_M0ACCESS_ADDR_MASTER_DRAM_MEM_ADD, mst_dram_mem_add, (0x420 + (lane * 0x130))); 7083 SESTO_CHIP_FIELD_READ(pa, SES_M0ACCESS_DATA_MASTER_DRAM_RDATA, mst_dram_rdata, data); 7084 enable ? (data |= (0x1 << 11)): (data &= (~(0x1 << 11))); 7085 SESTO_CHIP_FIELD_WRITE(pa, SES_M0ACCESS_ADDR_MASTER_DRAM_MEM_ADD, mst_dram_mem_add, (0x420 + (lane * 0x130))); 7086 SESTO_CHIP_FIELD_WRITE(pa, SES_M0ACCESS_DATA_MASTER_DRAM_WDATA, mst_dram_wdata, data); 7087 /* Relase the lane under dp reset */ 7088 SESTO_CHIP_FIELD_WRITE(pa, F25G_CKRST_CTRL_RPTR_LANE_CLK_RESET_N_POWERDOWN_CONTROL, ln_dp_s_rstb, 1); 7089 } 7090 } 7091 ERR: 7092 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 7093 PHYMOD_FREE(config.device_aux_modes); 7094 7095 return rv; 7096 } 7097 7098 int _sesto_phy_short_channel_mode_get(const phymod_phy_access_t *phy, uint32_t *enable, uint32_t *status) 7099 { 7100 phymod_phy_inf_config_t config; 7101 uint16_t data = 0; 7102 uint16_t ip = 0, lane = 0; 7103 uint16_t lane_mask = 0, max_lane = 0; 7104 const phymod_access_t *pa = &phy->access; 7105 int rv = PHYMOD_E_NONE; 7106 *enable = 1; 7107 7108 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 7109 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 7110 SESTO_IF_ERR_RETURN( 7111 _sesto_phy_interface_config_get(phy, 0, &config)); 7112 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 7113 SESTO_GET_IP(phy, config, ip); 7114 7115 max_lane = (ip == SESTO_FALCON_CORE) ? 7116 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 7117 7118 PHYMOD_DEBUG_VERBOSE(("%s ::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 7119 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 7120 7121 if (ip == SESTO_MERLIN_CORE) { 7122 /* short_channel_mode can performed only on falcon side */ 7123 return PHYMOD_E_PARAM; 7124 } 7125 7126 for (lane = 0; lane < max_lane; lane ++) { 7127 if (lane_mask & (1 << lane)) { 7128 /* config RAM variable */ 7129 SESTO_CHIP_FIELD_WRITE(pa, SES_M0ACCESS_ADDR_MASTER_DRAM_MEM_ADD, mst_dram_mem_add, (0x420 + (lane * 0x130))); 7130 SESTO_CHIP_FIELD_READ(pa, SES_M0ACCESS_DATA_MASTER_DRAM_RDATA, mst_dram_rdata, data); 7131 *enable &= ((data >> 11) & 0x1); 7132 } 7133 } 7134 ERR: 7135 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 7136 PHYMOD_FREE(config.device_aux_modes); 7137 7138 return rv; 7139 } 7140 7141 int _sesto_phy_eye_margin_est_get(const phymod_phy_access_t *phy, int *left_eye_mUI, int *right_eye_mUI, int *upper_eye_mV, int *lower_eye_mV) 7142 { 7143 phymod_phy_inf_config_t config; 7144 7145 uint16_t ip = 0; 7146 uint16_t lane = 0, max_lane = 0; 7147 uint16_t lane_mask = 0; 7148 int rv = PHYMOD_E_NONE; 7149 const phymod_access_t *pa = &phy->access; 7150 PHYMOD_MEMSET(&config, 0, sizeof(phymod_phy_inf_config_t)); 7151 config.device_aux_modes = PHYMOD_MALLOC(sizeof(SESTO_DEVICE_AUX_MODE_T), "sesto_device_aux_mode"); 7152 SESTO_IF_ERR_RETURN( 7153 _sesto_phy_interface_config_get(phy, 0, &config)); 7154 7155 SESTO_GET_IP(phy, config, ip); 7156 max_lane = (ip == SESTO_FALCON_CORE) ? 7157 SESTO_MAX_FALCON_LANE : SESTO_MAX_MERLIN_LANE; 7158 7159 lane_mask = PHYMOD_ACC_LANE_MASK(pa); 7160 PHYMOD_DEBUG_VERBOSE(("%s::IP:%s Max_lane:%d lanemask:0x%x\n", __func__, 7161 (ip == SESTO_MERLIN_CORE)?"MERLIN":"FALCON", max_lane, lane_mask)); 7162 7163 for (lane = 0; lane < max_lane; lane++) { 7164 if ((lane_mask & (1 << lane))) { 7165 SESTO_IF_ERR_RETURN ( 7166 _sesto_set_slice_reg (pa, SESTO_SLICE_UNICAST, ip, 7167 SESTO_DEV_PMA_PMD, 0, lane)); 7168 PHYMOD_DEBUG_VERBOSE(("Phy Diagnostics for Lane:%d \n",lane)); 7169 if(ip == SESTO_FALCON_CORE) { 7170 SESTO_IF_ERR_RETURN ( 7171 _falcon_furia_sesto_eye_margin_est_get(pa,left_eye_mUI,right_eye_mUI,upper_eye_mV,lower_eye_mV)); 7172 break; 7173 } else { 7174 SESTO_IF_ERR_RETURN ( 7175 _merlin_sesto_eye_margin_est_get(pa,left_eye_mUI,right_eye_mUI,upper_eye_mV,lower_eye_mV)); 7176 break; 7177 7178 } 7179 } 7180 } 7181 ERR: 7182 SESTO_RESET_SLICE(pa, SESTO_DEV_PMA_PMD); 7183 PHYMOD_FREE(config.device_aux_modes); 7184 return rv; 7185 } 7186 7187