diff options
author | David Hendricks <dhendricks@fb.com> | 2018-03-09 14:30:38 -0800 |
---|---|---|
committer | Philipp Deppenwiese <zaolin.daisuki@gmail.com> | 2018-07-03 15:53:32 +0000 |
commit | 7d48ac5c7dfb52fc470bbad1013b4d460bc6a1e0 (patch) | |
tree | 42002ba1e86627339ff4a6cf38efb4b3f00033bb /src/vendorcode/cavium/bdk/libbdk-hal/if | |
parent | d837e660074e0621d63f59515f933c209441b653 (diff) |
soc/cavium: Integrate BDK files into coreboot
* Make it compile.
* Fix whitespace errors.
* Fix printf formats.
* Add missing headers includes
* Guard headers with ifdefs
Compile DRAM init code in romstage.
Compile QLM, PCIe, RNG, PHY, GPIO, MDIO init code in ramstage.
Change-Id: I0a93219a14bfb6ebe41103a825d5032b11e7f2c6
Signed-off-by: David Hendricks <dhendricks@fb.com>
Reviewed-on: https://review.coreboot.org/25089
Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com>
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'src/vendorcode/cavium/bdk/libbdk-hal/if')
5 files changed, 1551 insertions, 0 deletions
diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-marvell.c b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-marvell.c new file mode 100644 index 0000000000..e8f3a009dd --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-marvell.c @@ -0,0 +1,115 @@ +/***********************license start*********************************** +* Copyright (c) 2003-2016 Cavium Inc. (support@cavium.com). All rights +* reserved. +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* * Neither the name of Cavium Inc. nor the names of +* its contributors may be used to endorse or promote products +* derived from this software without specific prior written +* permission. +* +* This Software, including technical data, may be subject to U.S. export +* control laws, including the U.S. Export Administration Act and its +* associated regulations, and may be subject to export or import +* regulations in other countries. +* +* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR +* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT +* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY +* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT +* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES +* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR +* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, +* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK +* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. +***********************license end**************************************/ +#include <bdk.h> +#include <libbdk-hal/bdk-mdio.h> +#include <libbdk-hal/bdk-qlm.h> +#include <libbdk-hal/if/bdk-if.h> + +/** + * Setup marvell PHYs + * This function sets up one port in a marvell 88E1512 in SGMII mode + */ +static void setup_marvell_phy(bdk_node_t node, int mdio_bus, int mdio_addr) +{ + int phy_status = 0; + + BDK_TRACE(PHY, "%s In SGMII mode for Marvell PHY 88E1512\n", __FUNCTION__); + /* Switch to Page 18 */ + phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 22, 18); + if (phy_status < 0) + return; + + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 22); + if (phy_status < 0) + return; + + /* Change the Phy System mode from RGMII(default hw reset mode) to SGMII */ + phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 20, 1); + if (phy_status < 0) + return; + + /* Requires a Software reset */ + phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 20, 0x8001); + if (phy_status < 0) + return; + + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 20); + if (phy_status < 0) + return; + + /* Change the Page back to 0 */ + phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 22, 0); + if (phy_status < 0) + return; + + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 22); + if (phy_status < 0) + return; + + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 17); + if (phy_status < 0) + return; +} + +int bdk_if_phy_marvell_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr) +{ + BDK_TRACE(PHY,"In %s\n",__FUNCTION__); + + /* Check if the PHY is marvell PHY we expect */ + int phy_status = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1); + if (phy_status != 0x0141) + return 0; + + /* Check that the GSER mode is SGMII */ + /* Switch the marvell PHY to the correct mode */ + bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm); + + BDK_TRACE(PHY,"%s: QLM:%d QLM_MODE:%d\n",__FUNCTION__, qlm, qlm_mode); + + if ((qlm_mode != BDK_QLM_MODE_SGMII_1X1) && + (qlm_mode != BDK_QLM_MODE_SGMII_2X1)) + return 0; + + BDK_TRACE(PHY,"%s: Detected Marvell Phy in SGMII mode\n", __FUNCTION__); + for (int port = 0; port < 2; port++) + { + setup_marvell_phy(node, mdio_bus, phy_addr + port); + } + return 0; +} diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-8514.c b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-8514.c new file mode 100644 index 0000000000..4d6ef8d25d --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-8514.c @@ -0,0 +1,224 @@ +/***********************license start*********************************** +* Copyright (c) 2003-2016 Cavium Inc. (support@cavium.com). All rights +* reserved. +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* * Neither the name of Cavium Inc. nor the names of +* its contributors may be used to endorse or promote products +* derived from this software without specific prior written +* permission. +* +* This Software, including technical data, may be subject to U.S. export +* control laws, including the U.S. Export Administration Act and its +* associated regulations, and may be subject to export or import +* regulations in other countries. +* +* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR +* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT +* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY +* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT +* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES +* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR +* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, +* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK +* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. +***********************license end**************************************/ +#include <bdk.h> +#include <libbdk-hal/if/bdk-if.h> +#include <libbdk-hal/bdk-mdio.h> +#include <libbdk-hal/bdk-qlm.h> + +#define VSC_PHY_STD_PAGE (0x0) +#define VSC_PHY_EXT1_PAGE (0x1) +#define VSC_PHY_EXT2_PAGE (0x2) +#define VSC_PHY_EXT3_PAGE (0x3) +#define VSC_PHY_EXT4_PAGE (0x4) +#define VSC_PHY_GPIO_PAGE (0x10) +#define VSC_PHY_TEST_PAGE (0x2A30) +#define VSC_PHY_TR_PAGE (0x52B5) + +const uint16_t init_script_rev_a[] = { +// Op, Page, Reg, Value, Mask +// 0, 1, 2, 3, 4 +// --, ------, ----, ------, ----- + 0, 0x0000, 0x1f, 0x0000, 0xffff, + 1, 0x0000, 0x16, 0x0001, 0x0001, + 0, 0x0001, 0x1f, 0x2A30, 0xffff, + 1, 0x2A30, 0x08, 0x8000, 0x8000, + 0, 0x2A30, 0x1f, 0x52B5, 0xffff, + 0, 0x52B5, 0x12, 0x0068, 0xffff, + 0, 0x52B5, 0x11, 0x8980, 0xffff, + 0, 0x52B5, 0x10, 0x8f90, 0xffff, + 0, 0x52B5, 0x12, 0x0000, 0xffff, + 0, 0x52B5, 0x11, 0x0003, 0xffff, + 0, 0x52B5, 0x10, 0x8796, 0xffff, + 0, 0x52B5, 0x12, 0x0050, 0xffff, + 0, 0x52B5, 0x11, 0x100f, 0xffff, + 0, 0x52B5, 0x10, 0x87fa, 0xffff, + 0, 0x52B5, 0x1f, 0x2A30, 0xffff, + 1, 0x2A30, 0x08, 0x0000, 0x8000, + 0, 0x2A30, 0x1f, 0x0000, 0xffff, + 1, 0x0000, 0x16, 0x0000, 0x0001, + 0xf, 0xffff, 0xff, 0xffff, 0xffff +}; + +static void wr_masked(bdk_node_t node, int mdio_bus, int phy_addr, int reg, int value, int mask) +{ + int nmask = ~mask; + int old = bdk_mdio_read(node, mdio_bus, phy_addr, reg); + int vmask = value & mask; + int newv = old & nmask; + newv = newv | vmask; + bdk_mdio_write(node, mdio_bus, phy_addr, reg, newv); +} +static void vitesse_init_script(bdk_node_t node, int mdio_bus, int phy_addr) +{ + const uint16_t *ptr; + uint16_t reg_addr; + uint16_t reg_val; + uint16_t mask; + + BDK_TRACE(PHY,"In %s\n",__FUNCTION__); + BDK_TRACE(PHY,"Loading init script for VSC8514\n"); + + ptr = init_script_rev_a; + while (*ptr != 0xf) + { + reg_addr = *(ptr+2); + reg_val = *(ptr+3); + mask = *(ptr+4); + ptr+=5; + if (mask != 0xffff) + { + wr_masked(node, mdio_bus, phy_addr, reg_addr,reg_val,mask); + } + else + { + bdk_mdio_write(node,mdio_bus,phy_addr,reg_addr,reg_val); + } + } + + BDK_TRACE(PHY,"loading init script is done\n"); + +} + +static void vitesse_program(bdk_node_t node, int mdio_bus, int phy_addr) +{ + return; +} + +/** + * Setup Vitesse PHYs + * This function sets up one port in a Vitesse VSC8514 + */ +static void setup_vitesse_phy(bdk_node_t node, int mdio_bus, int phy_addr) +{ + /*setting MAC if*/ + bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_GPIO_PAGE); + wr_masked(node,mdio_bus,phy_addr, 19, 0x4000, 0xc000); + bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x80e0); + + /*Setting media if*/ + bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_STD_PAGE); + // Reg23, 10:8 Select copper, CAT5 copper only + wr_masked(node,mdio_bus,phy_addr, 23, 0x0000, 0x0700); + + // Reg0:15, soft Reset + wr_masked(node,mdio_bus,phy_addr, 0, 0x8000, 0x8000); + int time_out = 100; + while (time_out && bdk_mdio_read(node,mdio_bus,phy_addr, 0) & 0x8000) + { + bdk_wait_usec(100000); + time_out--; + } + + if (time_out == 0) + { + BDK_TRACE(PHY,"setting PHY TIME OUT\n"); + return; + } + else + { + BDK_TRACE(PHY,"Setting a phy port is done\n"); + } + + bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_EXT3_PAGE); + bdk_mdio_write(node, mdio_bus, phy_addr, 16, 0x80); + // Select main registers + bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_STD_PAGE); + + /* + + if (LOOP_INTERNAL) + { + reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0); + reg0 = bdk_insert(reg0, 1, 14, 1); + bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0); + } + + // Far end loopback (External side) + if (LOOP_EXTERNAL) + { + reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23); + reg23 = bdk_insert(reg23, 1, 3, 1); + bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23); + } + + + // Dump registers + if (false) + { + printf("\nVitesse PHY register dump, PHY address %d, mode %s\n", + phy_addr, (qsgmii) ? "QSGMII" : "SGMII"); + int phy_addr = 4; + for (int reg_set = 0; reg_set <= 0x10; reg_set += 0x10) + { + printf("\nDump registers with reg[31]=0x%x\n", reg_set); + bdk_mdio_write(node, mdio_bus, phy_addr, 31, reg_set); + for (int reg=0; reg < 32; reg++) + printf("reg[%02d]=0x%x\n", reg, bdk_mdio_read(node, mdio_bus, phy_addr, reg)); + } + } + */ +} + +//static void vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr) +int bdk_if_phy_vsc8514_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr) +{ + /* Check if the PHY is Vetesse PHY we expect */ + int phy_status_1 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1); + int phy_status_2 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID2); + if (phy_status_1 != 0x0007 || phy_status_2 != 0x0670) + { + bdk_error("The PHY on this board is NOT VSC8514.\n"); + return -1; + } + + /* Check that the GSER mode is SGMII or QSGMII */ + bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm); + if (qlm_mode != BDK_QLM_MODE_QSGMII_4X1) + return -1; + + vitesse_init_script(node, mdio_bus, phy_addr); + vitesse_program(node, mdio_bus, phy_addr); + + /* VSC8514 just support QSGMII */ + for (int port = 0; port < 4; port++) + setup_vitesse_phy(node, mdio_bus, phy_addr + port); + + return 1; + +} diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-xfi.c b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-xfi.c new file mode 100644 index 0000000000..b6f052ad47 --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-xfi.c @@ -0,0 +1,395 @@ +/***********************license start*********************************** +* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights +* reserved. +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* * Neither the name of Cavium Inc. nor the names of +* its contributors may be used to endorse or promote products +* derived from this software without specific prior written +* permission. +* +* This Software, including technical data, may be subject to U.S. export +* control laws, including the U.S. Export Administration Act and its +* associated regulations, and may be subject to export or import +* regulations in other countries. +* +* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR +* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT +* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY +* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT +* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES +* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR +* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, +* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK +* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. +***********************license end**************************************/ +#include <bdk.h> +#include <libbdk-hal/if/bdk-if.h> +#include <libbdk-hal/bdk-mdio.h> +#include <libbdk-hal/bdk-twsi.h> + +/* This code is an optional part of the BDK. It is only linked in + * if BDK_REQUIRE() needs it */ +//BDK_REQUIRE(TWSI); +BDK_REQUIRE_DEFINE(XFI); + +/* +Rate Select Settings +Mode State : 6/8 +Rate Select State : 0 +RSEL1 : 0 +RSEL0 : 0 +Ref Clock Gen(MHz) : 156.25 +Data Rate(Gbps) : 10.3125 +Description : 10 GbE + + +Data Rate Detection Configuration Registers + +Mode Pin Settings: +Mode State : 0 +MODE1 : 0 +MODE0 : 0 +Mode : Two-wire serial interface mode + +LOS Pin Strap Mode Settings +Mode State : 2/6/8 +State : 4 +LOS1 : Float +LOS0 : Float +LOS Amplitude(mVpp) : 20 +LOS Hysteresis(dB) : 2 + +Input Equalization Retimer Mode Settings +Mode State : 6/8 +EQ State : 0 +EQ1 : 0 +EQ0 : 0 +EQ(dB) : Auto +DFE : Auto +Comment : Full Auto + +Input Equalization Re-Driver Mode Settings +Mode State : +EQ State : 0 +EQ1 : 0 +EQ0 : 0 +EQ(dB) : Auto +DFE : APowered Down +Comment : Analog EQ Only + + + +Output De-Emphasis Retimer Mode Settings +Mode State : 6/8 +DE State : 3 +TX1 : Float +TX0 : 0 +PRE c(-1) mA : -1 +MAIN c( 0) mA : 15 +POST c(+1) mA : 4 +DC Amplitude(mV): 500 +De-Emphasis(dB) : -6.02 +Comment : + + +Output De-Emphasis Re-Driver Mode Settings +Mode State : 2 +DE State : 3 +TX1 : Float +TX0 : 0 +Frequency(Gbps) : 10.3125 +DC Amplitude(mV): 600 +De-Emphasis(dB) : 4 +Comment : 10GbE + + +*/ + +static int debug = 0; + +#define xfi_printf(fmt, args...) \ + do { \ + if(debug == 1){ \ + printf(fmt, ##args); \ + } \ + } while(0) + + +int bdk_xfi_vsc7224_dump(int twsi_id, int unit){ + bdk_node_t node=0; + uint8_t dev_addr=0x10 + unit; + uint16_t internal_addr=0x7F; + int num_bytes=2; + int ia_width_bytes=1; + uint64_t data=0; + int p, i; + uint64_t result[0x100] = {0}; + + uint64_t pagenum[9] = {0x00, 0x01, 0x02, 0x03, 0x20, 0x21, 0x30, 0x31, 0x40}; + + for(p=0; p < (sizeof(pagenum)/sizeof(pagenum[0])); p++){ + data = pagenum[p]; + bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, data); + for(i=0x80; i<=0xFF; i++){ + result[i] = 0x00; + result[i] = bdk_twsix_read_ia(node, twsi_id, dev_addr, (uint16_t)i, num_bytes, ia_width_bytes); + } + for(i=0x80; i<=0xFF; i++){ + if(i==0x80){ + printf("\npage_%02X[0x100] = {\n", (uint8_t)pagenum[p]); + } + if(i % 8 == 0){ + printf("/* 0x%2X */", i); + } + printf(" 0x%04X,", (uint16_t)result[i]); + if(i==0xFF){ + printf("};"); + } + if((i+1) % 8 == 0){ + printf("\n"); + } + } + } + + return 0; +} + +/* XFI ReTimer/ReDriver Mode Settings */ + +/* +power down regs: +Page Reg Position Mask val RegFieldName +0x00 0x89 b07 0x0080 1 PD_INBUF +0x00 0x8A b10 0x0400 1 PD_DFECRU +0x00 0x8A b01 0x0002 1 PD_DFE +0x00 0x8A b00 0x0001 1 PD_DFEADAPT +0x00 0x97 b15 0x8000 1 ASYN_SYNN +0x00 0x97 b09 0x0200 1 PD_OD +0x00 0xA0 b11 0x0800 1 PD_LOS +0x00 0xA4 b15 0x8000 1 PD_CH +0x00 0xB5 b07 0x0080 1 PD_INBUF +0x00 0xB9 b15 0x8000 1 ASYN_SYNN +0x00 0xB9 b09 0x0200 1 PD_OD +0x00 0xBF b07 0x0080 1 PD_INBUF +0x00 0xF0 b15 0x8000 1 ASYN_SYNN +0x00 0xF0 b09 0x0200 1 PD_OD +0x00 0xF6 b07 0x0080 1 PD_INBUF +0x00 0xFA b15 0x8000 1 ASYN_SYNN +0x00 0xFA b09 0x0200 1 PD_OD +*/ +struct regmap{ + short int page; + unsigned char reg; + unsigned short int retimer; + unsigned short int redriver; +}; + +/* This table only applies to SFF8104 */ +struct regmap xfiregmap[64] = { +//CH 0 +{0x00, 0x84, 0x0800, 0x0000}, //EQTABLE_DCOFF0 (0n_84) +{0x00, 0x8A, 0x7000, 0x0400}, //DFECRU_CTRL (0n_8A) +{0x00, 0x8B, 0x4060, 0x0000}, //DFECRU_CFVF_CFAP (0n_8B) +{0x00, 0x90, 0xDE85, 0x0000}, //DFECRU_DFEAUTO (0n_90) +{0x00, 0x91, 0x2020, 0x0000}, //DFECRU_BTMX_BFMX (0n_91) +{0x00, 0x92, 0x0860, 0x0000}, //DFECRU_DXMX_TRMX (0n_92) +{0x00, 0x93, 0x6000, 0x0000}, //DFECRU_TRMN_ERRI (0n_93) +{0x00, 0x94, 0x0001, 0x0000}, //DFECRU_DFEMODE (0n_94) +{0x00, 0x95, 0x0008, 0x0000}, //DFECRU_RATESEL (0n_95) +{0x00, 0x97, 0x0000, 0x8080}, //OUTDRVCTRL (0n_97) +{0x00, 0x99, 0x001E, 0x0014}, //KR_MAINTAP (0n_99) +{0x00, 0x9A, 0x000B, 0x0000}, //KR_PRETAP (0n_9A) +{0x00, 0x9B, 0x0010, 0x0000}, //KR_POSTTAP (0n_9B) +{0x00, 0x9E, 0x03E8, 0x07D0}, //LOSASSRT (0n_9E) +{0x00, 0x9F, 0x04EA, 0x09D5}, //LOSDASSRT (0n_9F) +{0x00, 0xB2, 0x0888, 0x0000}, //NA + +//CH 1 +{0x01, 0x84, 0x0800, 0x0000}, +{0x01, 0x8A, 0x7000, 0x0400}, +{0x01, 0x8B, 0x4060, 0x0000}, +{0x01, 0x90, 0xDE85, 0x0000}, +{0x01, 0x91, 0x2020, 0x0000}, +{0x01, 0x92, 0x0860, 0x0000}, +{0x01, 0x93, 0x6000, 0x0000}, +{0x01, 0x94, 0x0001, 0x0000}, +{0x01, 0x95, 0x0008, 0x0000}, +{0x01, 0x97, 0x0000, 0x8080}, +{0x01, 0x99, 0x001E, 0x0014}, +{0x01, 0x9A, 0x000B, 0x0000}, +{0x01, 0x9B, 0x0010, 0x0000}, +{0x01, 0x9E, 0x03E8, 0x07D0}, +{0x01, 0x9F, 0x04EA, 0x09D5}, +{0x01, 0xB2, 0x0888, 0x0000}, + +//POWER_DOWN Channel 2 and 3 +{0x02, 0x8A, 0x0400, 0x0400}, +{0x02, 0xA4, 0x8000, 0x8000}, +{0x03, 0x8A, 0x0400, 0x0400}, +{0x03, 0xA4, 0x8000, 0x8000}, + +{0x30, 0x80, 0x3453, 0x0000}, //FSYNM_NVAL (3f_80) +{0x30, 0x81, 0x00F6, 0x0000}, //FSYNFVAL_MSB (3f_81) +{0x30, 0x82, 0x8800, 0x0000}, //FSYNFVAL_LSB (3f_82) +{0x30, 0x83, 0x000F, 0x0000}, //FSYNRVAL_MSB (3f_83) +{0x30, 0x84, 0xB5E0, 0x0000}, //FSYNRVAL_LSB (3f_84) +{0x30, 0x85, 0x0000, 0x0400}, //FSYNTST (3f_85) + +{0x40, 0x80, 0x4C00, 0x0000}, //ANMUXSEL (40_80) +{0x40, 0x81, 0x4000, 0x0000}, //DGMUXCTRL (40_81) +{0x40, 0x82, 0x7800, 0xC000}, //RCKINCTRL (40_82) +{0x40, 0x84, 0x0020, 0x0000}, //CHRCKSEL (40_84) + +{-1, 0, 0, 0}, +}; + +int bdk_vsc7224_modeset(int twsi_id, int unit, int xfi_mode){ + bdk_node_t node=0; + uint8_t dev_addr=0x10 + unit; + uint16_t internal_addr=0x7F; + uint16_t page=0; + int num_bytes=2; + int ia_width_bytes=1; + uint64_t data=0; + int val=0; + int ret = 0, r=0; + uint16_t reg = 0; + + if(xfi_mode==0){ + printf("XFI Mode Retimer\n"); + }else{ + printf("XFI Mode Redriver\n"); + } + + while(xfiregmap[r].page != -1){ + page = xfiregmap[r].page; + reg = xfiregmap[r].reg; + if(xfi_mode==0){ + data = xfiregmap[r].retimer; + }else{ + data = xfiregmap[r].redriver; + } + ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)page); + if(ret !=0){ + printf("XFI init Error\n"); + break; + } + ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes, data); + if(ret !=0){ + printf("XFI init Error\n"); + break; + } + val = bdk_twsix_read_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes); + if(val == -1){ + printf("XFI Read Reg Failed @ page:reg :: %2X:%2X \n",page, reg); + break; + }else{ + xfi_printf(" Page: reg: data: val :: %2X:%2X:%04X:%04X\n", page, reg, (uint16_t)data, val); + } + r++; + } + + return ret; +} + + +int bdk_vsc7224_regmap_modeget(int twsi_id, int unit){ + bdk_node_t node=0; + uint8_t dev_addr=0x10 + unit; + uint16_t internal_addr=0x7F; + uint16_t page=0; + int num_bytes=2; + int ia_width_bytes=1; + //uint64_t data=0; + uint16_t reg = 0; + int ret = 0, r=0; + int data; + + printf("\n===========================================\n"); + printf("Page :Reg :Value :Retimer :Redriver\n"); + printf("===========================================\n"); + while(xfiregmap[r].page != -1){ + page = xfiregmap[r].page; + reg = xfiregmap[r].reg; + + ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)page); + if(ret !=0){ + printf("XFI init Error\n"); + break; + } + data = bdk_twsix_read_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes); + if(data == -1){ + printf("XFI Read Reg Failed @ page:reg :: %2X:%2X \n",page, reg); + break; + } + printf(" %02X: %02X: %04X: %04X: %04X\n", page, reg, (uint16_t)data, xfiregmap[r].retimer, xfiregmap[r].redriver); + r++; + } + printf("=======================================\n"); + + return ret; +} + +int bdk_vsc7224_wp_regs(int twsi_id, int unit, int xfi_wp){ + bdk_node_t node=0; + uint8_t dev_addr=0x10 + unit; + uint16_t internal_addr=0x7E; + uint16_t data=0x0000; + int num_bytes=2; + int ia_width_bytes=1; + int ret =0; + + if(xfi_wp == 1){ + data = 0x0000; + }else{ + data = 0xFFFF; + } + + ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)data); + if(ret !=0){ + printf("XFI VSC7224 Write Protect Error\n"); + } + + return ret; +} + +int bdk_vsc7224_set_reg(int twsi_id, int unit, int page, int reg, int val){ + bdk_node_t node=0; + uint8_t dev_addr=0x10 + unit; + uint16_t internal_addr = reg; + int num_bytes=2; + int ia_width_bytes=1; + int ret=0; + + xfi_printf(" Unit: Page: reg: val :: %02x:%2X:%2X:%04X\n", unit, page, reg, val & 0xFFFF); + ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, 0x7F, num_bytes, ia_width_bytes, (uint64_t)(page & 0xFF)); + if (ret) { + printf("XFI VSC7224 TWSI Set Page Register Error\n"); + } + + ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)(val & 0xFFFF)); + if (ret) { + printf("XFI VSC7224 TWSI Set Register Error\n"); + } + + return ret; +} + +int bdk_vsc7224_debug(int _debug){ + debug =_debug; + return 0; +} diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse.c b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse.c new file mode 100644 index 0000000000..e1ef6b0f2d --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse.c @@ -0,0 +1,372 @@ +/***********************license start*********************************** +* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights +* reserved. +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* * Neither the name of Cavium Inc. nor the names of +* its contributors may be used to endorse or promote products +* derived from this software without specific prior written +* permission. +* +* This Software, including technical data, may be subject to U.S. export +* control laws, including the U.S. Export Administration Act and its +* associated regulations, and may be subject to export or import +* regulations in other countries. +* +* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR +* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT +* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY +* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT +* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES +* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR +* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, +* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK +* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. +***********************license end**************************************/ +#include <bdk.h> +#include <libbdk-hal/if/bdk-if.h> +#include <libbdk-hal/bdk-mdio.h> +#include <libbdk-hal/bdk-qlm.h> + +static bool LOOP_INTERNAL = false; +static bool LOOP_EXTERNAL = false; + +static uint8_t patch_arr[] = { + 0x44, 0x83, 0x02, 0x42, 0x12, 0x02, 0x44, 0x93, 0x02, 0x44, + 0xca, 0x02, 0x44, 0x4d, 0x02, 0x43, 0xef, 0xed, 0xff, 0xe5, + 0xfc, 0x54, 0x38, 0x64, 0x20, 0x70, 0x08, 0x65, 0xff, 0x70, + 0x04, 0xed, 0x44, 0x80, 0xff, 0x22, 0x8f, 0x19, 0x7b, 0xbb, + 0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, + 0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e, + 0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, + 0xce, 0xd8, 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02, + 0x41, 0xed, 0x85, 0x1a, 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff, + 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0x03, 0x02, 0x41, 0xed, + 0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25, 0xe0, 0x25, + 0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x02, 0x12, + 0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, + 0xd7, 0xef, 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x02, + 0x74, 0xc7, 0x25, 0x1a, 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8, + 0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d, 0x24, 0x5b, 0x12, 0x44, + 0x2a, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11, 0x7f, 0x07, + 0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6, + 0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78, + 0xc1, 0xf6, 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f, + 0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07, + 0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80, 0x1f, 0x78, 0xc5, 0xe6, + 0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff, 0x78, 0xcb, + 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb, + 0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78, + 0xc2, 0xf6, 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40, + 0x03, 0x02, 0x41, 0xd1, 0xef, 0x54, 0x03, 0x60, 0x33, 0x14, + 0x60, 0x46, 0x24, 0xfe, 0x60, 0x42, 0x04, 0x70, 0x4b, 0xef, + 0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78, 0x02, 0xce, + 0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d, + 0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff, + 0xed, 0x3e, 0xfe, 0x12, 0x44, 0x6a, 0x7d, 0x11, 0x80, 0x0b, + 0x78, 0xc2, 0xe6, 0x70, 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d, + 0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a, 0x8e, 0x1e, 0x8f, 0x1f, + 0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6, 0x06, 0x24, + 0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a, + 0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x44, 0x2a, 0x12, 0x3e, + 0xda, 0x78, 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb, + 0x20, 0x75, 0xdb, 0x28, 0x12, 0x44, 0x42, 0x12, 0x44, 0x42, + 0xe5, 0x1a, 0x12, 0x44, 0x35, 0xe5, 0x1a, 0xc3, 0x13, 0x12, + 0x44, 0x35, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd, 0xf8, 0xe6, + 0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02, + 0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5, + 0xdb, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8, + 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb, + 0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6, 0x70, 0xc8, 0x75, 0xdb, + 0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3, 0x94, 0x17, + 0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5, + 0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x02, 0x03, 0x02, + 0x40, 0x76, 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50, + 0x03, 0x02, 0x40, 0x3a, 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff, + 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x44, 0x6a, 0x22, 0xff, + 0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x44, 0x6a, 0x22, 0xd2, + 0x00, 0x75, 0xfb, 0x03, 0xab, 0x7e, 0xaa, 0x7d, 0x7d, 0x19, + 0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e, 0x54, 0x0f, 0x24, + 0xf3, 0x60, 0x03, 0x02, 0x42, 0xb9, 0x12, 0x44, 0xa3, 0x12, + 0x44, 0xaa, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x2a, 0x13, 0x92, + 0x04, 0xef, 0xa2, 0xe1, 0x92, 0x03, 0x30, 0x04, 0x1f, 0xe4, + 0xf5, 0x10, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7b, 0x54, 0x7f, + 0x04, 0x12, 0x3d, 0xd7, 0x74, 0x25, 0x25, 0x10, 0xf8, 0xa6, + 0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02, 0x40, 0xe4, + 0x12, 0x44, 0xa3, 0x12, 0x44, 0xaa, 0xd8, 0xfb, 0x54, 0x05, + 0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6, + 0xe5, 0x7d, 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78, + 0xc4, 0xf6, 0x12, 0x42, 0xcf, 0x20, 0x04, 0x0c, 0x12, 0x44, + 0xa3, 0x12, 0x44, 0xaa, 0xd8, 0xfb, 0x13, 0x92, 0x05, 0x22, + 0xc2, 0x05, 0x22, 0x12, 0x44, 0xa3, 0x12, 0x44, 0xaa, 0xd8, + 0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d, + 0xb8, 0x12, 0x42, 0xc5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x42, + 0xc5, 0xe4, 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00, + 0x7d, 0xee, 0x7f, 0x92, 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb, + 0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38, 0xbd, 0x22, 0x78, 0xc1, + 0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12, 0x38, + 0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e, + 0x00, 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33, + 0xce, 0xd8, 0xf9, 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d, + 0x60, 0x44, 0x85, 0x11, 0xfb, 0xe5, 0x11, 0x54, 0x02, 0x25, + 0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b, 0xfb, 0xee, 0x12, + 0x44, 0x2d, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11, 0x7f, + 0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6, + 0x07, 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7, + 0xef, 0x4e, 0x60, 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, + 0x04, 0x80, 0x07, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x0a, + 0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x78, + 0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10, 0x75, + 0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x43, 0x7d, + 0x7d, 0x76, 0x12, 0x43, 0x7d, 0x79, 0xc6, 0xe7, 0x78, 0xc4, + 0x66, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6, + 0x70, 0x09, 0xfb, 0xfa, 0x7d, 0xfe, 0x7f, 0x8e, 0x12, 0x38, + 0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f, 0x8e, 0x12, 0x38, + 0xbd, 0x22, 0xe4, 0xf5, 0x19, 0x74, 0x25, 0x25, 0x19, 0xf8, + 0xe6, 0x64, 0x03, 0x60, 0x51, 0xe5, 0x19, 0x24, 0x17, 0xfd, + 0x7b, 0xeb, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x8f, 0xfb, 0x7b, + 0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7, 0xef, 0x64, + 0x01, 0x4e, 0x60, 0x1c, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e, + 0x9a, 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x70, 0x15, 0x7b, 0xcc, + 0x7d, 0x10, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e, + 0x70, 0x07, 0x12, 0x44, 0xb1, 0x7b, 0x03, 0x80, 0x0a, 0x12, + 0x44, 0xb1, 0x74, 0x25, 0x25, 0x19, 0xf8, 0xe6, 0xfb, 0x7a, + 0x00, 0x7d, 0x54, 0x12, 0x38, 0xbd, 0x05, 0x19, 0xe5, 0x19, + 0xc3, 0x94, 0x02, 0x40, 0x9c, 0x22, 0xe5, 0x7e, 0x30, 0xe5, + 0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02, 0x7d, 0x33, 0x7f, 0x35, + 0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d, 0x33, 0x7f, + 0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04, + 0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47, + 0xd1, 0xe0, 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f, + 0x86, 0x12, 0x36, 0x29, 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0, + 0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22, 0x54, 0x01, 0xc4, 0x33, + 0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb, 0x22, 0xf5, + 0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22, + 0xe5, 0x7e, 0x54, 0x0f, 0x64, 0x01, 0x70, 0x0d, 0xe5, 0x7e, + 0x30, 0xe4, 0x08, 0x90, 0x47, 0xd0, 0xe0, 0x44, 0x02, 0xf0, + 0x22, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0xab, + 0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda, + 0x7b, 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef, + 0x4e, 0x60, 0xf3, 0x22, 0x12, 0x44, 0xc5, 0x12, 0x44, 0xbb, + 0x90, 0x47, 0xfa, 0xe0, 0x54, 0xf8, 0x44, 0x02, 0xf0, 0x22, + 0x30, 0x04, 0x03, 0x12, 0x43, 0x87, 0x78, 0xc4, 0xe6, 0xff, + 0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x7e, 0xae, 0x7d, + 0x78, 0x04, 0x22, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22, + 0xe5, 0x19, 0x24, 0x17, 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22, + 0xe4, 0x78, 0xc4, 0xf6, 0xc2, 0x05, 0x78, 0xc1, 0xf6, 0x22, + 0xc2, 0x04, 0xc2, 0x03, 0x22, 0x22 +}; + +/** + * Setup Vitesse PHYs + * This function sets up one port in a Vitesse VSC8574 for + * either SGMII or QSGMII + */ +static void setup_vitesse_phy(bdk_node_t node, int mdio_bus, int phy_addr, bool qsgmii) +{ + // Select "G" registers + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x10); + // Reg 19G, bit 15:14 + // 0 = SGMII + // 1 = QSGMII + int reg19 = bdk_mdio_read(node, mdio_bus, phy_addr, 19); + int reg18; + if (qsgmii) + { + // QSGMII + reg19 = (reg19 & ~(3 << 14)) | (1 << 14); + reg18 = 0x80e0; + } + else + { + // SGMII + reg19 = (reg19 & ~(3 << 14)) | (0 << 14); + reg18 = 0x80f0; + } + bdk_mdio_write(node, mdio_bus, phy_addr, 19, reg19); + // Write 18G, change all 4 ports + bdk_mdio_write(node, mdio_bus, phy_addr, 18, reg18); + // Select main registers + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0); + // Reg23, 10:8 Select copper + int reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23); + reg23 = (reg23 & ~(7 << 8)) | (0 << 8); + bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23); + // Reg0, Reset + int reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0); + reg0 |= (1 << 15); + bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0); + // Reg 16E3, bit 7 auto negotiation + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 3); + bdk_mdio_write(node, mdio_bus, phy_addr, 16, 0x80); + // Select main registers + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0); + // Near end loopback (Thunder side) + if (LOOP_INTERNAL) + { + reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0); + reg0 |= (1 << 14); + bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0); + } + + // Far end loopback (External side) + if (LOOP_EXTERNAL) + { + reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23); + reg23 |= (1 << 3); + bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23); + } +} + +static void wr_masked(bdk_node_t node, int mdio_bus, int phy_addr, int reg, int value, int mask) +{ + int nmask = ~mask; + int old = bdk_mdio_read(node, mdio_bus, phy_addr, reg); + int vmask = value & mask; + int newv = old & nmask; + newv = newv | vmask; + bdk_mdio_write(node, mdio_bus, phy_addr, reg, newv); +} + +static void vitesse_program(bdk_node_t node, int mdio_bus, int phy_addr) +{ + printf("Programming Vitesse PHY at address %d\n", phy_addr); + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010); + bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x800f); + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010); + + int reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18); + int timeout = 10; + while ((reg18g & (1<<15)) && (timeout > 0)) + { + bdk_wait_usec(100000); + reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18); + timeout = timeout - 1; + } + if (timeout == 0) + bdk_error("Vetesse: Timeout waiting for complete\n"); + + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0000); + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010); + wr_masked(node, mdio_bus, phy_addr, 12, 0x0000, 0x0800); + bdk_mdio_write(node, mdio_bus, phy_addr, 9, 0x005b); + bdk_mdio_write(node, mdio_bus, phy_addr, 10, 0x005b); + wr_masked(node, mdio_bus, phy_addr, 12, 0x0800, 0x0800); + bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x800f); + wr_masked(node, mdio_bus, phy_addr, 0, 0x0000, 0x8000); + bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x0000); + wr_masked(node, mdio_bus, phy_addr, 12, 0x0000, 0x0800); + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x10); + bdk_mdio_write(node, mdio_bus, phy_addr, 0, 0x7009); + bdk_mdio_write(node, mdio_bus, phy_addr, 12, 0x5002); + bdk_mdio_write(node, mdio_bus, phy_addr, 11, 0x0000); + + for (unsigned int i=0; i<sizeof(patch_arr); i++) + { + int d = 0x5000 | patch_arr[i]; + bdk_mdio_write(node, mdio_bus, phy_addr, 12, d); + } + bdk_mdio_write(node, mdio_bus, phy_addr, 12, 0x0000); + + bdk_mdio_write(node, mdio_bus, phy_addr, 3, 0x3eb7); + bdk_mdio_write(node, mdio_bus, phy_addr, 4, 0x4012); + bdk_mdio_write(node, mdio_bus, phy_addr, 12, 0x0100); + bdk_mdio_write(node, mdio_bus, phy_addr, 0, 0x4018); + bdk_mdio_write(node, mdio_bus, phy_addr, 0, 0xc018); + + // below verifies CRC is correct in 8051 RAM. CRC is 16-bit. + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0001); + bdk_mdio_write(node, mdio_bus, phy_addr, 25, 0x4000); + bdk_mdio_write(node, mdio_bus, phy_addr, 26, sizeof(patch_arr) + 1); + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010); + bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x8008); + + reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18); + timeout = 10; + while ((reg18g & (1<<15)) && (timeout > 0)) + { + bdk_wait_usec(100000); + reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18); + timeout = timeout - 1; + } + if (timeout == 0) + bdk_error("Vetesse: Timeout waiting for complete\n"); + + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0001); + + int crc_calculated = bdk_mdio_read(node, mdio_bus, phy_addr, 25); + if (crc_calculated != 0xB7C2) + printf("8051 crc_calculated = 0x%x, expected_crc = 0x%x\n", crc_calculated, 0xB7C2); + + bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0000); +} + +//static void vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr) +int bdk_if_phy_vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr) +{ + /* Check if the PHY is Vetesse PHY we expect */ + int phy_status = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1); + if (phy_status != 0x0007) + return 0; + + /* Check that the GSER mode is SGMII or QSGMII */ + bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm); + if ((qlm_mode != BDK_QLM_MODE_SGMII_1X1) && + (qlm_mode != BDK_QLM_MODE_SGMII_2X1) && + (qlm_mode != BDK_QLM_MODE_SGMII_4X1) && + (qlm_mode != BDK_QLM_MODE_QSGMII_4X1)) + return 0; + + /* Program the Vetesse PHY */ + vitesse_program(node, mdio_bus, phy_addr); + + /* Switch the Vitesse PHY to the correct mode */ + bool is_qsgmii = (qlm_mode == BDK_QLM_MODE_QSGMII_4X1); + if (is_qsgmii) + { + for (int port = 0; port < 4; port++) + setup_vitesse_phy(node, mdio_bus, phy_addr + port, true); + } + else + setup_vitesse_phy(node, mdio_bus, phy_addr, false); + return 0; +} + +#if 0 +int bdk_if_phy_vetesse_setup(bdk_node_t node) +{ + for (int bgx = 0; bgx < 4; bgx++) + { + int port = 0; + int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, node, bgx, port); + if (phy_addr != -1) + { + int node = (phy_addr >> 24) & 0xff; + int mdio_bus = (phy_addr >> 8) & 0xff; + int mdio_addr = phy_addr & 0xff; + if (node == 0xff) + node = bdk_numa_local(); + if ((phy_addr & BDK_IF_PHY_TYPE_MASK) == BDK_IF_PHY_MDIO) + { + int qlm = bdk_qlm_get(node, BDK_IF_BGX, bgx, port); + if (qlm != -1) + vetesse_setup(node, qlm, mdio_bus, mdio_addr); + } + } + } + return 0; +} +#endif diff --git a/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy.c b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy.c new file mode 100644 index 0000000000..5b02eff0cd --- /dev/null +++ b/src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy.c @@ -0,0 +1,445 @@ +/***********************license start*********************************** +* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights +* reserved. +* +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are +* met: +* +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* +* * Redistributions in binary form must reproduce the above +* copyright notice, this list of conditions and the following +* disclaimer in the documentation and/or other materials provided +* with the distribution. +* +* * Neither the name of Cavium Inc. nor the names of +* its contributors may be used to endorse or promote products +* derived from this software without specific prior written +* permission. +* +* This Software, including technical data, may be subject to U.S. export +* control laws, including the U.S. Export Administration Act and its +* associated regulations, and may be subject to export or import +* regulations in other countries. +* +* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS" +* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR +* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT +* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY +* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT +* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES +* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR +* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, +* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK +* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU. +***********************license end**************************************/ +#include <bdk.h> +#include <libbdk-hal/if/bdk-if.h> +#include <libbdk-hal/bdk-config.h> +#include <libbdk-hal/bdk-mdio.h> +#include <libbdk-hal/bdk-qlm.h> +#include <libbdk-hal/bdk-twsi.h> + +/** + * Called when the PHY is connected through TWSI + * + * @param dev_node Node the ethernet device is on + * @param phy_addr Encoded address, see bdk-if.h for format + * + * @return Link status + */ +static bdk_if_link_t __bdk_if_phy_get_twsi(bdk_node_t dev_node, int phy_addr) +{ + /* For TWSI: + Bits[31:24]: Node ID, 0xff for device node + Bits[23:16]: TWSI internal address width in bytes (0-2) + Bits[15:12]: 2=TWSI + Bits[11:8]: TWSI bus number + Bits[7:0]: TWSI address */ + int node = (phy_addr >> 24) & 0xff; + int twsi_ia_width = (phy_addr >> 16) & 0xff; + int twsi_bus = (phy_addr >> 8) & 0xf; + int twsi_addr = phy_addr & 0xff; + if (node == 0xff) + node = dev_node; + + bdk_if_link_t result; + result.u64 = 0; + + /* This is from the Avago SFP 1G Module data sheet + Register 17 (Extended Status 1) */ + int64_t phy_status = bdk_twsix_read_ia(node, twsi_bus, twsi_addr, 17, 2, twsi_ia_width); + if (phy_status != -1) + { + int speed = (phy_status >> 14)& 3; + int duplex = (phy_status >> 13)& 1; + int resolved = (phy_status >> 11)& 1; + int link = (phy_status >> 10)& 1; + if (resolved) + { + result.s.up = link; + result.s.full_duplex = duplex; + switch (speed) + { + case 0: /* 10 Mbps */ + result.s.speed = 10; + break; + case 1: /* 100 Mbps */ + result.s.speed = 100; + break; + case 2: /* 1 Gbps */ + result.s.speed = 1000; + break; + case 3: /* Illegal */ + result.u64 = 0; + break; + } + } + } + + return result; +} + +/** + * Read the status of a PHY + * + * @param dev_node Node the ethernet device is on + * @param phy_addr Encoded PHY address, see bdk-if.h for format + * + * @return Link status + */ +bdk_if_link_t __bdk_if_phy_get(bdk_node_t dev_node, int phy_addr) +{ + int node = (phy_addr >> 24) & 0xff; + int mdio_bus = (phy_addr >> 8) & 0xff; + int mdio_addr = phy_addr & 0xff; + if (node == 0xff) + node = dev_node; + int phy_status; + bdk_if_link_t result; + result.u64 = 0; + + /* PHY address of -1 menas there is no PHY and we should have never + gotten here */ + if (phy_addr == -1) + return result; + + /* A PHY address with the special value 0x1000 represents a PHY we can't + connect to through MDIO which is assumed to be at 1Gbps */ + if (phy_addr == BDK_IF_PHY_FIXED_1GB) + { + result.s.up = 1; + result.s.full_duplex = 1; + result.s.speed = 1000; + return result; + } + + /* A PHY address with the special value 0x1001 represents a PHY we can't + connect to through MDIO which is assumed to be at 100Mbps */ + if (phy_addr == BDK_IF_PHY_FIXED_100MB) + { + result.s.up = 1; + result.s.full_duplex = 1; + result.s.speed = 100; + return result; + } + + /* Check for a PHY connected through TWSI */ + if ((phy_addr & BDK_IF_PHY_TYPE_MASK) == BDK_IF_PHY_TWSI) + return __bdk_if_phy_get_twsi(dev_node, phy_addr); + + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, BDK_MDIO_PHY_REG_ID1); + if ((phy_status <= 0) || (phy_status == 0xffff)) + return result; + + switch (phy_status) + { + case 0x0141: /* Marvell */ + { + + /* This code assumes we are using a Marvell Gigabit PHY. All the + speed information can be read from register 17 in one go. Somebody + using a different PHY will need to handle it above in the board + specific area */ + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 17); + if (phy_status < 0) + return result; + + /* If the resolve bit 11 isn't set, see if autoneg is turned off + (bit 12, reg 0). The resolve bit doesn't get set properly when + autoneg is off, so force it */ + if ((phy_status & (1<<11)) == 0) + { + bdk_mdio_phy_reg_control_t control; + int phy_c = bdk_mdio_read(node, mdio_bus, mdio_addr, BDK_MDIO_PHY_REG_CONTROL); + if (phy_c < 0) + return result; + control.u16 = phy_c; + if (control.s.autoneg_enable == 0) + phy_status |= 1<<11; + } + + /* Only return a link if the PHY has finished auto negotiation + and set the resolved bit (bit 11) */ + if (phy_status & (1<<11)) + { + result.s.up = 1; + result.s.full_duplex = ((phy_status>>13)&1); + switch ((phy_status>>14)&3) + { + case 0: /* 10 Mbps */ + result.s.speed = 10; + break; + case 1: /* 100 Mbps */ + result.s.speed = 100; + break; + case 2: /* 1 Gbps */ + result.s.speed = 1000; + break; + case 3: /* Illegal */ + result.u64 = 0; + break; + } + } + break; + } + case 0x0022: /* Kendin */ + { + /* Register 1Fh - PHY Control */ + /* Micrel KSZ9031RNX, EBB8104 RGMII transceiver */ + /* Reports as "Kendin" in BDK_MDIO_PHY_REG_ID1 */ + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x1F); + if (phy_status & (1 << 6)) // Speed Status - 1000Base-T + { + result.s.up = 1; + result.s.speed = 1000; + } + else if (phy_status & (1 << 5)) // Speed Status - 100Base-TX + { + result.s.up = 1; + result.s.speed = 100; + } + else if (phy_status & (1 << 4)) // Speed Status - 10Base-T + { + result.s.up = 1; + result.s.speed = 10; + } + if (phy_status & (1 << 3)) // Duplex Status + { + result.s.full_duplex = 1; + } + break; + } + case 0x0007: /* Vitesse */ + { + /* Auxiliary Control and Status, Address 28 (0x1C) */ + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x1c); + result.s.full_duplex = (phy_status>>5)&1; + switch ((phy_status>>3) & 3) + { + case 0: + result.s.speed = 10; + result.s.up = 1; + break; + case 1: + result.s.speed = 100; + result.s.up = 1; + break; + default: + result.s.speed = 1000; + break; + } + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x01); + result.s.up = (phy_status>>2)&1; + break; + } + default: /* Treat like Broadcom */ + { + /* Below we are going to read SMI/MDIO register 0x19 which works + on Broadcom parts */ + phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x19); + if (phy_status < 0) + return result; + + switch ((phy_status>>8) & 0x7) + { + case 0: + result.u64 = 0; + break; + case 1: + result.s.up = 1; + result.s.full_duplex = 0; + result.s.speed = 10; + break; + case 2: + result.s.up = 1; + result.s.full_duplex = 1; + result.s.speed = 10; + break; + case 3: + result.s.up = 1; + result.s.full_duplex = 0; + result.s.speed = 100; + break; + case 4: + result.s.up = 1; + result.s.full_duplex = 1; + result.s.speed = 100; + break; + case 5: + result.s.up = 1; + result.s.full_duplex = 1; + result.s.speed = 100; + break; + case 6: + result.s.up = 1; + result.s.full_duplex = 0; + result.s.speed = 1000; + break; + case 7: + result.s.up = 1; + result.s.full_duplex = 1; + result.s.speed = 1000; + break; + } + break; + } + } + + /* If link is down, return all fields as zero. */ + if (!result.s.up) + result.u64 = 0; + + return result; +} + +/** + * PHY XS initialization, primarily for RXAUI + * + * @param dev_node Node the ethernet device is on + * @param phy_addr Encoded PHY address, see bdk-if.h for format + * + * @return none + */ +void __bdk_if_phy_xs_init(bdk_node_t dev_node, int phy_addr) +{ + /* This code only supports PHYs connected through MDIO */ + if ((phy_addr & BDK_IF_PHY_TYPE_MASK) != BDK_IF_PHY_MDIO) + return; + + int node = (phy_addr >> 24) & 0xff; + int mdio_bus = (phy_addr >> 8) & 0xff; + int mdio_addr = phy_addr & 0xff; + if (node == 0xff) + node = dev_node; + + /* Read the PMA/PMD Device Identifier (1.2, 1.3) + OUI is spread across both registers */ + int dev_addr = 1; + int reg_addr = 2; + int phy_id1 = bdk_mdio_45_read(node, mdio_bus, mdio_addr, dev_addr, reg_addr); + if (phy_id1 == -1) + return; + reg_addr = 3; + int phy_id2 = bdk_mdio_45_read(node, mdio_bus, mdio_addr, dev_addr, reg_addr); + if (phy_id2 == -1) + return; + int model_number = (phy_id2 >> 4) & 0x3F; + int oui = phy_id1; + oui <<= 6; + oui |= (phy_id2 >> 10) & 0x3F; + switch (oui) + { + case 0x5016: /* Marvell */ + if (model_number == 9) /* 88X3140/3120 */ + { + BDK_TRACE(BGX, "N%d.MDIO%d.%d: Performing PHY reset on Marvell RXAUI PHY\n", + node, mdio_bus, mdio_addr); + dev_addr = 4; + reg_addr = 0; + /* Write bit 15, Software Reset, in PHY XS Control 1 (4.0). On CN78xx, + sometimes the PHY/BGX gets stuck in local fault mode, link never comes up, + and this appears to clear it up. Haven't seen this on CN81xx or T88, + but the reset seems like cheap insurance. */ + if (bdk_mdio_45_write(node, mdio_bus, mdio_addr, dev_addr, reg_addr, (1 << 15))) + { + bdk_error("PHY XS: MDIO write to (%d.%d) failed\n", dev_addr, reg_addr); + return; + } + + int reset_pending = 1; + while (reset_pending) + { + reset_pending = bdk_mdio_45_read(node, mdio_bus, mdio_addr, dev_addr, reg_addr); + reset_pending &= (1 << 15); + } + + /* Adjust the RXAUI TX Level for Marvell PHY, per Brendan Metzner + write 5 to register 4.49155 */ + reg_addr = 49155; + if (bdk_mdio_45_write(node, mdio_bus, mdio_addr, dev_addr, reg_addr, 5)) + { + bdk_error("PHY XS: MDIO write to (%d.%d) failed\n", dev_addr, reg_addr); + return; + } + } + break; + + default: /* Unknown PHY, or no PHY present */ + break; + } +} + +int bdk_if_phy_setup(bdk_node_t dev_node) +{ + /* 81xx has only 2 BGX (BGX0-BGX1); BGX2 is RGMII */ + for (int bgx = 0; bgx < 2; bgx++) + { + int port = 0; + int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, dev_node, bgx, port); + if (phy_addr != -1) + { + int node = (phy_addr >> 24) & 0xff; + int mdio_bus = (phy_addr >> 8) & 0xff; + int mdio_addr = phy_addr & 0xff; + if (node == 0xff) + node = bdk_numa_local(); + if ((phy_addr & BDK_IF_PHY_TYPE_MASK) == BDK_IF_PHY_MDIO) + { + int qlm = bdk_qlm_get_qlm_num(node, BDK_IF_BGX, bgx, port); + if (qlm == -1) + continue; + + BDK_TRACE(PHY, "N%d.BGX%d.%d: Configuring ...\n", node, bgx, port); + + /* Check PHY id */ + int phy_status_1 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1); + int phy_status_2 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID2); + + /* Vitesse */ + if (phy_status_1 == 0x0007) + { + if (phy_status_2 == 0x0670) + { + bdk_if_phy_vsc8514_setup(node, qlm, mdio_bus, mdio_addr); + } + else + { + bdk_if_phy_vetesse_setup(node, qlm, mdio_bus, mdio_addr); + } + } + + /* Marvell */ + else if (phy_status_1 == 0x0141) + bdk_if_phy_marvell_setup(node, qlm, mdio_bus, mdio_addr); + else + BDK_TRACE(PHY, "N%d.BGX%d.%d: Unknown PHY %x\n", node, bgx, port, phy_status_1); + } + } + } + return 0; +} + |