aboutsummaryrefslogtreecommitdiff
path: root/src/vendorcode/cavium/bdk/libbdk-hal/if
diff options
context:
space:
mode:
Diffstat (limited to 'src/vendorcode/cavium/bdk/libbdk-hal/if')
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-marvell.c115
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-8514.c224
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-xfi.c395
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse.c372
-rw-r--r--src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy.c445
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;
+}
+