lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230411092725.104992-6-jiawenwu@trustnetic.com>
Date:   Tue, 11 Apr 2023 17:27:24 +0800
From:   Jiawen Wu <jiawenwu@...stnetic.com>
To:     netdev@...r.kernel.org, linux@...linux.org.uk
Cc:     linux-i2c@...r.kernel.org, linux-gpio@...r.kernel.org,
        mengyuanlou@...-swift.com, Jiawen Wu <jiawenwu@...stnetic.com>
Subject: [PATCH net-next v2 5/6] net: txgbe: Implement phylink pcs

Register MDIO bus for PCS layer, support 10GBASE-R and 1000BASE-X
interfaces to the controller.

Signed-off-by: Jiawen Wu <jiawenwu@...stnetic.com>
---
 drivers/net/ethernet/wangxun/Kconfig          |   1 +
 .../net/ethernet/wangxun/txgbe/txgbe_phy.c    | 377 ++++++++++++++++++
 .../net/ethernet/wangxun/txgbe/txgbe_type.h   |  59 +++
 3 files changed, 437 insertions(+)

diff --git a/drivers/net/ethernet/wangxun/Kconfig b/drivers/net/ethernet/wangxun/Kconfig
index d9cccdad8a53..9e374e9c3d9c 100644
--- a/drivers/net/ethernet/wangxun/Kconfig
+++ b/drivers/net/ethernet/wangxun/Kconfig
@@ -42,6 +42,7 @@ config TXGBE
 	depends on PCI
 	select GPIOLIB_IRQCHIP
 	select GPIOLIB
+	select PHYLINK
 	select LIBWX
 	select I2C
 	select SFP
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
index 42e66db6e9ff..123fa7ed9039 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_phy.c
@@ -6,7 +6,9 @@
 #include <linux/gpio/machine.h>
 #include <linux/gpio/driver.h>
 #include <linux/gpio/property.h>
+#include <linux/phylink.h>
 #include <linux/iopoll.h>
+#include <linux/mdio.h>
 #include <linux/i2c.h>
 #include <linux/pci.h>
 
@@ -74,6 +76,375 @@ static int txgbe_swnodes_register(struct txgbe *txgbe)
 	return software_node_register_node_group(nodes->group);
 }
 
+static int pcs_read(struct txgbe *txgbe, int dev, u32 reg)
+{
+	return mdiodev_c45_read(txgbe->mdiodev, dev, reg);
+}
+
+static int pcs_write(struct txgbe *txgbe, int dev, u32 reg, u16 val)
+{
+	return mdiodev_c45_write(txgbe->mdiodev, dev, reg, val);
+}
+
+static int pma_read(struct txgbe *txgbe, u32 reg)
+{
+	return pcs_read(txgbe, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg);
+}
+
+static int pma_write(struct txgbe *txgbe, u32 reg, u16 val)
+{
+	return pcs_write(txgbe, MDIO_MMD_PMAPMD, TXGBE_PMA_MMD + reg, val);
+}
+
+static int txgbe_pcs_read(struct mii_bus *bus, int addr, int devnum, int regnum)
+{
+	struct wx *wx  = bus->priv;
+	u32 offset, val;
+
+	offset = devnum << 16 | regnum;
+
+	/* Set the LAN port indicator to IDA_ADDR */
+	wr32(wx, TXGBE_XPCS_IDA_ADDR, offset);
+
+	/* Read the data from IDA_DATA register */
+	val = rd32(wx, TXGBE_XPCS_IDA_DATA);
+
+	return (u16)val;
+}
+
+static int txgbe_pcs_write(struct mii_bus *bus, int addr, int devnum, int regnum, u16 val)
+{
+	struct wx *wx = bus->priv;
+	u32 offset;
+
+	offset = devnum << 16 | regnum;
+
+	/* Set the LAN port indicator to IDA_ADDR */
+	wr32(wx, TXGBE_XPCS_IDA_ADDR, offset);
+
+	/* Write the data to IDA_DATA register */
+	wr32(wx, TXGBE_XPCS_IDA_DATA, val);
+
+	return 0;
+}
+
+static void txgbe_ephy_write(struct txgbe *txgbe, u32 addr, u32 data)
+{
+	struct wx *wx = txgbe->wx;
+
+	/* Set the LAN port indicator to IDA_ADDR */
+	wr32(wx, TXGBE_ETHPHY_IDA_ADDR, addr);
+
+	/* Write the data to IDA_DATA register */
+	wr32(wx, TXGBE_ETHPHY_IDA_DATA, data);
+}
+
+static int txgbe_pcs_validate(struct phylink_pcs *pcs,
+			      unsigned long *supported,
+			      const struct phylink_link_state *state)
+{
+	/* When in 802.3z mode, we must have AN enabled */
+	if (phy_interface_mode_is_8023z(state->interface) &&
+	    !phylink_test(state->advertising, Autoneg))
+		return -EINVAL;
+
+	return 0;
+}
+
+static void txgbe_pma_config_10gbaser(struct txgbe *txgbe)
+{
+	u16 val;
+
+	pcs_write(txgbe, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBR);
+	val = pcs_read(txgbe, MDIO_MMD_PMAPMD, MDIO_CTRL1);
+	val |= MDIO_CTRL1_SPEED10G;
+	pcs_write(txgbe, MDIO_MMD_PMAPMD, MDIO_CTRL1, val);
+
+	pma_write(txgbe, TXGBE_MPLLA_CTL0, 0x21);
+	pma_write(txgbe, TXGBE_MPLLA_CTL3, 0);
+	val = pma_read(txgbe, TXGBE_TX_GENCTRL1);
+	val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTRL1_VBOOST_LVL);
+	pma_write(txgbe, TXGBE_TX_GENCTRL1, val);
+	pma_write(txgbe, TXGBE_MISC_CTL0, 0xCF00);
+	pma_write(txgbe, TXGBE_VCO_CAL_LD0, 0x549);
+	pma_write(txgbe, TXGBE_VCO_CAL_REF0, 0x29);
+	pma_write(txgbe, TXGBE_TX_RATE_CTL, 0);
+	pma_write(txgbe, TXGBE_RX_RATE_CTL, 0);
+	pma_write(txgbe, TXGBE_TX_GEN_CTL2, 0x300);
+	pma_write(txgbe, TXGBE_RX_GEN_CTL2, 0x300);
+	pma_write(txgbe, TXGBE_MPLLA_CTL2, 0x600);
+
+	pma_write(txgbe, TXGBE_RX_EQ_CTL0, 0x45);
+	val = pma_read(txgbe, TXGBE_RX_EQ_ATTN_CTL);
+	val &= ~TXGBE_RX_EQ_ATTN_LVL0;
+	pma_write(txgbe, TXGBE_RX_EQ_ATTN_CTL, val);
+	pma_write(txgbe, TXGBE_DFE_TAP_CTL0, 0xBE);
+	val = pma_read(txgbe, TXGBE_AFE_DFE_ENABLE);
+	val &= ~(TXGBE_DFE_EN_0 | TXGBE_AFE_EN_0);
+	pma_write(txgbe, TXGBE_AFE_DFE_ENABLE, val);
+	val = pma_read(txgbe, TXGBE_RX_EQ_CTL4);
+	val &= ~TXGBE_RX_EQ_CTL4_CONT_ADAPT0;
+	pma_write(txgbe, TXGBE_RX_EQ_CTL4, val);
+}
+
+static void txgbe_pma_config_1000basex(struct txgbe *txgbe)
+{
+	u16 val;
+
+	pcs_write(txgbe, MDIO_MMD_PCS, MDIO_CTRL2, MDIO_PCS_CTRL2_10GBX);
+	pcs_write(txgbe, MDIO_MMD_PMAPMD, MDIO_CTRL1, 0);
+	pcs_write(txgbe, MDIO_MMD_VEND2, MDIO_CTRL1,
+		  MDIO_PMA_CTRL1_SPEED1000 | MDIO_CTRL1_FULLDPLX);
+
+	val = pma_read(txgbe, TXGBE_TX_GENCTRL1);
+	val = u16_replace_bits(val, 0x5, TXGBE_TX_GENCTRL1_VBOOST_LVL);
+	val &= ~TXGBE_TX_GENCTRL1_VBOOST_EN0;
+	pma_write(txgbe, TXGBE_TX_GENCTRL1, val);
+	pma_write(txgbe, TXGBE_MISC_CTL0, 0xCF00);
+
+	pma_write(txgbe, TXGBE_RX_EQ_CTL0, 0x7706);
+	val = pma_read(txgbe, TXGBE_RX_EQ_ATTN_CTL);
+	val &= ~TXGBE_RX_EQ_ATTN_LVL0;
+	pma_write(txgbe, TXGBE_RX_EQ_ATTN_CTL, val);
+	pma_write(txgbe, TXGBE_DFE_TAP_CTL0, 0);
+	val = pma_read(txgbe, TXGBE_RX_GEN_CTL3);
+	val = u16_replace_bits(val, 0x4, TXGBE_RX_GEN_CTL3_LOS_TRSHLD0);
+	pma_write(txgbe, TXGBE_RX_EQ_ATTN_CTL, val);
+
+	pma_write(txgbe, TXGBE_MPLLA_CTL0, 0x20);
+	pma_write(txgbe, TXGBE_MPLLA_CTL3, 0x46);
+	pma_write(txgbe, TXGBE_VCO_CAL_LD0, 0x540);
+	pma_write(txgbe, TXGBE_VCO_CAL_REF0, 0x2A);
+	pma_write(txgbe, TXGBE_AFE_DFE_ENABLE, 0);
+	pma_write(txgbe, TXGBE_RX_EQ_CTL4, 0x10);
+	pma_write(txgbe, TXGBE_TX_RATE_CTL, 0x3);
+	pma_write(txgbe, TXGBE_RX_RATE_CTL, 0x3);
+	pma_write(txgbe, TXGBE_TX_GEN_CTL2, 0x100);
+	pma_write(txgbe, TXGBE_RX_GEN_CTL2, 0x100);
+	pma_write(txgbe, TXGBE_MPLLA_CTL2, 0x200);
+	pcs_write(txgbe, MDIO_MMD_VEND2, TXGBE_MII_AN_CTRL, TXGBE_MII_AN_CTRL_MII);
+}
+
+static void txgbe_set_an37_ability(struct txgbe *txgbe)
+{
+	u16 val;
+
+	pcs_write(txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_CTRL1,
+		  TXGBE_PCS_DIG_CTRL1_EN_VSMMD1 |
+		  TXGBE_PCS_DIG_CTRL1_CLS7_BP |
+		  TXGBE_PCS_DIG_CTRL1_BYP_PWRUP);
+	pcs_write(txgbe, MDIO_MMD_VEND2, TXGBE_MII_AN_CTRL,
+		  TXGBE_MII_AN_CTRL_MII |
+		  TXGBE_MII_AN_CTRL_TXCFG |
+		  TXGBE_MII_AN_CTRL_PCS_MODE(0) |
+		  TXGBE_MII_AN_CTRL_INTR_EN);
+	pcs_write(txgbe, MDIO_MMD_VEND2, TXGBE_MII_DIG_CTRL1,
+		  TXGBE_MII_DIG_CTRL1_MAC_AUTOSW);
+	val = pcs_read(txgbe, MDIO_MMD_VEND2, MDIO_CTRL1);
+	val |= BMCR_ANRESTART | BMCR_ANENABLE;
+	pcs_write(txgbe, MDIO_MMD_VEND2, MDIO_CTRL1, val);
+}
+
+static void txgbe_setup_adv(struct txgbe *txgbe, phy_interface_t interface,
+			    const unsigned long *advertising)
+{
+	int adv;
+
+	adv = phylink_mii_c22_pcs_encode_advertisement(interface,
+						       advertising);
+	if (adv > 0)
+		mdiodev_c45_modify(txgbe->mdiodev, MDIO_MMD_VEND2, MII_ADVERTISE,
+				   0xffff, adv);
+}
+
+static int txgbe_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
+			    phy_interface_t interface,
+			    const unsigned long *advertising,
+			    bool permit_pause_to_mac)
+{
+	struct txgbe *txgbe = container_of(pcs, struct txgbe, pcs);
+	struct wx *wx = txgbe->wx;
+	int ret, val;
+
+	if (interface == txgbe->interface)
+		goto out;
+
+	/* Wait xpcs power-up good */
+	ret = read_poll_timeout(pcs_read, val,
+				(val & TXGBE_PCS_DIG_STS_PSEQ_ST) ==
+				TXGBE_PCS_DIG_STS_PSEQ_ST_GOOD,
+				10000, 1000000, false,
+				txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_STS);
+	if (ret < 0) {
+		wx_err(wx, "xpcs power-up timeout.\n");
+		return ret;
+	}
+
+	/* Disable xpcs AN-73 */
+	pcs_write(txgbe, MDIO_MMD_AN, MDIO_CTRL1, 0);
+
+	/* Disable PHY MPLLA for eth mode change(after ECO) */
+	txgbe_ephy_write(txgbe, TXGBE_SUP_DIG_MPLLA_OVRD_IN_0, 0x243A);
+	WX_WRITE_FLUSH(wx);
+	usleep_range(1000, 2000);
+
+	/* Set the eth change_mode bit first in mis_rst register
+	 * for corresponding LAN port
+	 */
+	wr32(wx, TXGBE_MIS_RST, TXGBE_MIS_RST_LAN_ETH_MODE(wx->bus.func));
+
+	switch (interface) {
+	case PHY_INTERFACE_MODE_10GBASER:
+		txgbe_pma_config_10gbaser(txgbe);
+		break;
+	case PHY_INTERFACE_MODE_1000BASEX:
+		txgbe_pma_config_1000basex(txgbe);
+		break;
+	default:
+		break;
+	}
+
+	pcs_write(txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_CTRL1,
+		  TXGBE_PCS_DIG_CTRL1_VR_RST | TXGBE_PCS_DIG_CTRL1_EN_VSMMD1);
+	/* wait phy initialization done */
+	ret = read_poll_timeout(pcs_read, val,
+				!(val & TXGBE_PCS_DIG_CTRL1_VR_RST),
+				100000, 10000000, false,
+				txgbe, MDIO_MMD_PCS, TXGBE_PCS_DIG_CTRL1);
+	if (ret < 0)
+		wx_err(wx, "PHY initialization timeout.\n");
+
+	txgbe->interface = interface;
+
+out:
+	if (interface == PHY_INTERFACE_MODE_1000BASEX) {
+		txgbe_setup_adv(txgbe, interface, advertising);
+		txgbe_set_an37_ability(txgbe);
+	}
+
+	return ret;
+}
+
+static void txgbe_pcs_get_state_10gbr(struct txgbe *txgbe,
+				      struct phylink_link_state *state)
+{
+	int ret;
+
+	state->link = false;
+
+	ret = pcs_read(txgbe, MDIO_MMD_PCS, MDIO_STAT1);
+	if (ret < 0)
+		return;
+
+	if (ret & MDIO_STAT1_LSTATUS)
+		state->link = true;
+
+	if (state->link) {
+		state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
+		state->duplex = DUPLEX_FULL;
+		state->speed = SPEED_10000;
+	}
+}
+
+static void txgbe_pcs_get_state_1000bx(struct txgbe *txgbe,
+				       struct phylink_link_state *state)
+{
+	int lpa, bmsr, an_intr;
+
+	/* Reset link state */
+	state->link = false;
+
+	lpa = pcs_read(txgbe, MDIO_MMD_VEND2, MII_LPA);
+	if (lpa < 0 || lpa & LPA_RFAULT) {
+		wx_err(txgbe->wx, "read pcs lpa error: %d\n", lpa);
+		return;
+	}
+
+	bmsr = pcs_read(txgbe, MDIO_MMD_VEND2, MII_BMSR);
+	if (bmsr < 0) {
+		wx_err(txgbe->wx, "read pcs lpa error: %d\n", bmsr);
+		return;
+	}
+
+	/* Clear AN complete interrupt */
+	an_intr = pcs_read(txgbe, MDIO_MMD_VEND2, TXGBE_MII_AN_INTR);
+	if (an_intr & TXGBE_MII_AN_INTR_CL37_CMPLT) {
+		an_intr &= ~TXGBE_MII_AN_INTR_CL37_CMPLT;
+		pcs_write(txgbe, MDIO_MMD_VEND2, TXGBE_MII_AN_INTR, an_intr);
+	}
+
+	phylink_mii_c22_pcs_decode_state(state, bmsr, lpa);
+}
+
+static void txgbe_pcs_get_state(struct phylink_pcs *pcs,
+				struct phylink_link_state *state)
+{
+	struct txgbe *txgbe = container_of(pcs, struct txgbe, pcs);
+
+	switch (state->interface) {
+	case PHY_INTERFACE_MODE_10GBASER:
+		txgbe_pcs_get_state_10gbr(txgbe, state);
+		return;
+	case PHY_INTERFACE_MODE_1000BASEX:
+		txgbe_pcs_get_state_1000bx(txgbe, state);
+		return;
+	default:
+		return;
+	}
+}
+
+static void txgbe_pcs_an_restart(struct phylink_pcs *pcs)
+{
+	struct txgbe *txgbe = container_of(pcs, struct txgbe, pcs);
+
+	mdiodev_c45_modify(txgbe->mdiodev, MDIO_MMD_VEND2, MDIO_CTRL1,
+			   BMCR_ANRESTART, BMCR_ANRESTART);
+}
+
+static const struct phylink_pcs_ops txgbe_pcs_ops = {
+	.pcs_validate = txgbe_pcs_validate,
+	.pcs_config = txgbe_pcs_config,
+	.pcs_get_state = txgbe_pcs_get_state,
+	.pcs_an_restart = txgbe_pcs_an_restart,
+};
+
+static int txgbe_mdio_pcs_init(struct txgbe *txgbe)
+{
+	struct mdio_device *mdiodev;
+	struct wx *wx = txgbe->wx;
+	struct mii_bus *mii_bus;
+	struct pci_dev *pdev;
+	int ret = 0;
+
+	pdev = wx->pdev;
+
+	mii_bus = devm_mdiobus_alloc(&pdev->dev);
+	if (!mii_bus)
+		return -ENOMEM;
+
+	mii_bus->name = "txgbe_pcs_mdio_bus";
+	mii_bus->read_c45 = &txgbe_pcs_read;
+	mii_bus->write_c45 = &txgbe_pcs_write;
+	mii_bus->parent = &pdev->dev;
+	mii_bus->phy_mask = ~0;
+	mii_bus->priv = wx;
+	snprintf(mii_bus->id, MII_BUS_ID_SIZE, "txgbe_pcs-%x",
+		 (pdev->bus->number << 8) | pdev->devfn);
+
+	ret = devm_mdiobus_register(&pdev->dev, mii_bus);
+	if (ret)
+		return ret;
+
+	mdiodev = mdio_device_create(mii_bus, 0);
+	if (IS_ERR(mdiodev))
+		return PTR_ERR(mdiodev);
+
+	txgbe->mdiodev = mdiodev;
+	txgbe->pcs.ops = &txgbe_pcs_ops;
+
+	return 0;
+}
+
 static void txgbe_i2c_start(struct wx *wx, u16 dev_addr)
 {
 	wr32(wx, TXGBE_I2C_ENABLE, 0);
@@ -457,6 +828,12 @@ int txgbe_init_phy(struct txgbe *txgbe)
 		return ret;
 	}
 
+	ret = txgbe_mdio_pcs_init(txgbe);
+	if (ret) {
+		wx_err(txgbe->wx, "failed to init mdio pcs: %d\n", ret);
+		goto err;
+	}
+
 	ret = txgbe_i2c_adapter_add(txgbe);
 	if (ret) {
 		wx_err(txgbe->wx, "failed to init i2c interface: %d\n", ret);
diff --git a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
index 58b0054ae59c..d83225b4e34e 100644
--- a/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
+++ b/drivers/net/ethernet/wangxun/txgbe/txgbe_type.h
@@ -5,6 +5,7 @@
 #define _TXGBE_TYPE_H_
 
 #include <linux/property.h>
+#include <linux/phylink.h>
 
 /* Device IDs */
 #define TXGBE_DEV_ID_SP1000                     0x1001
@@ -43,6 +44,8 @@
 
 /**************** SP Registers ****************************/
 /* chip control Registers */
+#define TXGBE_MIS_RST                           0x1000C
+#define TXGBE_MIS_RST_LAN_ETH_MODE(_i)          BIT((_i) + 29)
 #define TXGBE_MIS_PRB_CTL                       0x10010
 #define TXGBE_MIS_PRB_CTL_LAN_UP(_i)            BIT(1 - (_i))
 /* FMGR Registers */
@@ -102,6 +105,59 @@
 #define TXGBE_I2C_SCL_STUCK_TIMEOUT             0x149AC
 #define TXGBE_I2C_SDA_STUCK_TIMEOUT             0x149B0
 
+/************************************** ETH PHY ******************************/
+#define TXGBE_XPCS_IDA_ADDR                     0x13000
+#define TXGBE_XPCS_IDA_DATA                     0x13004
+#define TXGBE_ETHPHY_IDA_ADDR                   0x13008
+#define TXGBE_ETHPHY_IDA_DATA                   0x1300C
+/* PHY Registers */
+#define TXGBE_SUP_DIG_MPLLA_OVRD_IN_0           0x4
+/* Vendor Specific PCS MMD Registers */
+#define TXGBE_PCS_DIG_CTRL1                     0x8000
+#define TXGBE_PCS_DIG_CTRL1_VR_RST              BIT(15)
+#define TXGBE_PCS_DIG_CTRL1_EN_VSMMD1           BIT(13)
+#define TXGBE_PCS_DIG_CTRL1_CLS7_BP             BIT(12)
+#define TXGBE_PCS_DIG_CTRL1_BYP_PWRUP           BIT(1)
+#define TXGBE_PCS_DIG_STS                       0x8010
+#define TXGBE_PCS_DIG_STS_PSEQ_ST               GENMASK(4, 2)
+#define TXGBE_PCS_DIG_STS_PSEQ_ST_GOOD          FIELD_PREP(GENMASK(4, 2), 0x4)
+/* Vendor Specific MII MMD Standard Registers */
+#define TXGBE_MII_DIG_CTRL1                     0x8000
+#define TXGBE_MII_DIG_CTRL1_MAC_AUTOSW          BIT(9)
+#define TXGBE_MII_AN_CTRL                       0x8001
+#define TXGBE_MII_AN_CTRL_MII                   BIT(8)
+#define TXGBE_MII_AN_CTRL_TXCFG                 BIT(3)
+#define TXGBE_MII_AN_CTRL_PCS_MODE(_v)          FIELD_PREP(GENMASK(2, 1), _v)
+#define TXGBE_MII_AN_CTRL_INTR_EN               BIT(0)
+#define TXGBE_MII_AN_INTR                       0x8002
+#define TXGBE_MII_AN_INTR_CL37_CMPLT            BIT(0)
+/* Vendor Specific PMA MMD Registers */
+#define TXGBE_PMA_MMD                           0x8020
+#define TXGBE_TX_GENCTRL1                       0x11
+#define TXGBE_TX_GENCTRL1_VBOOST_LVL            GENMASK(10, 8)
+#define TXGBE_TX_GENCTRL1_VBOOST_EN0            BIT(4)
+#define TXGBE_TX_GEN_CTL2                       0x12
+#define TXGBE_TX_RATE_CTL                       0x14
+#define TXGBE_RX_GEN_CTL2                       0x32
+#define TXGBE_RX_GEN_CTL3                       0x33
+#define TXGBE_RX_GEN_CTL3_LOS_TRSHLD0           GENMASK(2, 0)
+#define TXGBE_RX_RATE_CTL                       0x34
+#define TXGBE_RX_EQ_ATTN_CTL                    0x37
+#define TXGBE_RX_EQ_ATTN_LVL0                   GENMASK(2, 0)
+#define TXGBE_RX_EQ_CTL0                        0x38
+#define TXGBE_RX_EQ_CTL4                        0x3C
+#define TXGBE_RX_EQ_CTL4_CONT_ADAPT0            BIT(0)
+#define TXGBE_AFE_DFE_ENABLE                    0x3D
+#define TXGBE_DFE_EN_0                          BIT(4)
+#define TXGBE_AFE_EN_0                          BIT(0)
+#define TXGBE_DFE_TAP_CTL0                      0x3E
+#define TXGBE_MPLLA_CTL0                        0x51
+#define TXGBE_MPLLA_CTL2                        0x53
+#define TXGBE_MPLLA_CTL3                        0x57
+#define TXGBE_MISC_CTL0                         0x70
+#define TXGBE_VCO_CAL_LD0                       0x72
+#define TXGBE_VCO_CAL_REF0                      0x76
+
 /* Part Number String Length */
 #define TXGBE_PBANUM_LENGTH                     32
 
@@ -186,9 +242,12 @@ struct txgbe_nodes {
 struct txgbe {
 	struct wx *wx;
 	struct txgbe_nodes nodes;
+	struct mdio_device *mdiodev;
+	struct phylink_pcs pcs;
 	struct i2c_adapter *i2c_adap;
 	struct gpio_chip *gpio;
 	struct platform_device *sfp_dev;
+	phy_interface_t interface;
 	u32 gpio_orig;
 };
 
-- 
2.27.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ