Commit d55595f0 authored by Jiawen Wu's avatar Jiawen Wu Committed by David S. Miller

net: pcs: xpcs: add specific vendor supoprt for Wangxun 10Gb NICs

Since Wangxun 10Gb NICs require some special configuration on the IP of
Synopsys Designware XPCS, introduce dev_flag for different vendors. Read
OUI from device identifier registers, to detect Wangxun devices.

And xpcs_soft_reset() is skipped to avoid the reset of device identifier
registers.
Signed-off-by: default avatarJiawen Wu <jiawenwu@trustnetic.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1355fe13
...@@ -238,6 +238,29 @@ static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val) ...@@ -238,6 +238,29 @@ static int xpcs_write_vpcs(struct dw_xpcs *xpcs, int reg, u16 val)
return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val); return xpcs_write_vendor(xpcs, MDIO_MMD_PCS, reg, val);
} }
static int xpcs_dev_flag(struct dw_xpcs *xpcs)
{
int ret, oui;
ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID1);
if (ret < 0)
return ret;
oui = ret;
ret = xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVID2);
if (ret < 0)
return ret;
ret = (ret >> 10) & 0x3F;
oui |= ret << 16;
if (oui == DW_OUI_WX)
xpcs->dev_flag = DW_DEV_TXGBE;
return 0;
}
static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev) static int xpcs_poll_reset(struct dw_xpcs *xpcs, int dev)
{ {
/* Poll until the reset bit clears (50ms per retry == 0.6 sec) */ /* Poll until the reset bit clears (50ms per retry == 0.6 sec) */
...@@ -1284,6 +1307,10 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, ...@@ -1284,6 +1307,10 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
goto out; goto out;
} }
ret = xpcs_dev_flag(xpcs);
if (ret)
goto out;
xpcs->pcs.ops = &xpcs_phylink_ops; xpcs->pcs.ops = &xpcs_phylink_ops;
xpcs->pcs.neg_mode = true; xpcs->pcs.neg_mode = true;
if (compat->an_mode == DW_10GBASER) if (compat->an_mode == DW_10GBASER)
...@@ -1291,9 +1318,11 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev, ...@@ -1291,9 +1318,11 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev,
xpcs->pcs.poll = true; xpcs->pcs.poll = true;
ret = xpcs_soft_reset(xpcs, compat); if (xpcs->dev_flag != DW_DEV_TXGBE) {
if (ret) ret = xpcs_soft_reset(xpcs, compat);
goto out; if (ret)
goto out;
}
return xpcs; return xpcs;
} }
......
...@@ -20,12 +20,19 @@ ...@@ -20,12 +20,19 @@
#define DW_AN_C37_1000BASEX 4 #define DW_AN_C37_1000BASEX 4
#define DW_10GBASER 5 #define DW_10GBASER 5
/* device vendor OUI */
#define DW_OUI_WX 0x0018fc80
/* dev_flag */
#define DW_DEV_TXGBE BIT(0)
struct xpcs_id; struct xpcs_id;
struct dw_xpcs { struct dw_xpcs {
struct mdio_device *mdiodev; struct mdio_device *mdiodev;
const struct xpcs_id *id; const struct xpcs_id *id;
struct phylink_pcs pcs; struct phylink_pcs pcs;
int dev_flag;
}; };
int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface); int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment