|
@@ -100,9 +100,11 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
|
|
#ifndef MDIO_PMA_10GBR_PMD_CTRL
|
|
#ifndef MDIO_PMA_10GBR_PMD_CTRL
|
|
#define MDIO_PMA_10GBR_PMD_CTRL 0x0096
|
|
#define MDIO_PMA_10GBR_PMD_CTRL 0x0096
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
#ifndef MDIO_PMA_10GBR_FEC_CTRL
|
|
#ifndef MDIO_PMA_10GBR_FEC_CTRL
|
|
#define MDIO_PMA_10GBR_FEC_CTRL 0x00ab
|
|
#define MDIO_PMA_10GBR_FEC_CTRL 0x00ab
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
#ifndef MDIO_AN_XNP
|
|
#ifndef MDIO_AN_XNP
|
|
#define MDIO_AN_XNP 0x0016
|
|
#define MDIO_AN_XNP 0x0016
|
|
#endif
|
|
#endif
|
|
@@ -110,14 +112,23 @@ MODULE_DESCRIPTION("AMD 10GbE (amd-xgbe) PHY driver");
|
|
#ifndef MDIO_AN_INTMASK
|
|
#ifndef MDIO_AN_INTMASK
|
|
#define MDIO_AN_INTMASK 0x8001
|
|
#define MDIO_AN_INTMASK 0x8001
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
#ifndef MDIO_AN_INT
|
|
#ifndef MDIO_AN_INT
|
|
#define MDIO_AN_INT 0x8002
|
|
#define MDIO_AN_INT 0x8002
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#ifndef MDIO_AN_KR_CTRL
|
|
|
|
+#define MDIO_AN_KR_CTRL 0x8003
|
|
|
|
+#endif
|
|
|
|
+
|
|
#ifndef MDIO_CTRL1_SPEED1G
|
|
#ifndef MDIO_CTRL1_SPEED1G
|
|
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
|
|
#define MDIO_CTRL1_SPEED1G (MDIO_CTRL1_SPEED10G & ~BMCR_SPEED100)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
+#ifndef MDIO_KR_CTRL_PDETECT
|
|
|
|
+#define MDIO_KR_CTRL_PDETECT 0x01
|
|
|
|
+#endif
|
|
|
|
+
|
|
/* SerDes integration register offsets */
|
|
/* SerDes integration register offsets */
|
|
#define SIR0_KR_RT_1 0x002c
|
|
#define SIR0_KR_RT_1 0x002c
|
|
#define SIR0_STATUS 0x0040
|
|
#define SIR0_STATUS 0x0040
|
|
@@ -341,6 +352,7 @@ struct amd_xgbe_phy_priv {
|
|
enum amd_xgbe_phy_rx kx_state;
|
|
enum amd_xgbe_phy_rx kx_state;
|
|
struct work_struct an_work;
|
|
struct work_struct an_work;
|
|
struct workqueue_struct *an_workqueue;
|
|
struct workqueue_struct *an_workqueue;
|
|
|
|
+ unsigned int parallel_detect;
|
|
};
|
|
};
|
|
|
|
|
|
static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev)
|
|
static int amd_xgbe_an_enable_kr_training(struct phy_device *phydev)
|
|
@@ -808,6 +820,13 @@ static enum amd_xgbe_phy_an amd_xgbe_an_start(struct phy_device *phydev)
|
|
/* Enable and start auto-negotiation */
|
|
/* Enable and start auto-negotiation */
|
|
phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0);
|
|
phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_INT, 0);
|
|
|
|
|
|
|
|
+ ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL);
|
|
|
|
+ if (ret < 0)
|
|
|
|
+ return AMD_XGBE_AN_ERROR;
|
|
|
|
+
|
|
|
|
+ ret |= MDIO_KR_CTRL_PDETECT;
|
|
|
|
+ phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_KR_CTRL, ret);
|
|
|
|
+
|
|
ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
|
|
ret = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_CTRL1);
|
|
if (ret < 0)
|
|
if (ret < 0)
|
|
return AMD_XGBE_AN_ERROR;
|
|
return AMD_XGBE_AN_ERROR;
|
|
@@ -888,6 +907,10 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
|
|
int sleep;
|
|
int sleep;
|
|
unsigned int an_supported = 0;
|
|
unsigned int an_supported = 0;
|
|
|
|
|
|
|
|
+ /* Start in KX mode */
|
|
|
|
+ if (amd_xgbe_phy_set_mode(phydev, AMD_XGBE_MODE_KX))
|
|
|
|
+ priv->an_state = AMD_XGBE_AN_ERROR;
|
|
|
|
+
|
|
while (1) {
|
|
while (1) {
|
|
mutex_lock(&priv->an_mutex);
|
|
mutex_lock(&priv->an_mutex);
|
|
|
|
|
|
@@ -895,8 +918,9 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
|
|
|
|
|
|
switch (priv->an_state) {
|
|
switch (priv->an_state) {
|
|
case AMD_XGBE_AN_START:
|
|
case AMD_XGBE_AN_START:
|
|
- priv->an_state = amd_xgbe_an_start(phydev);
|
|
|
|
an_supported = 0;
|
|
an_supported = 0;
|
|
|
|
+ priv->parallel_detect = 0;
|
|
|
|
+ priv->an_state = amd_xgbe_an_start(phydev);
|
|
break;
|
|
break;
|
|
|
|
|
|
case AMD_XGBE_AN_EVENT:
|
|
case AMD_XGBE_AN_EVENT:
|
|
@@ -913,6 +937,7 @@ static void amd_xgbe_an_state_machine(struct work_struct *work)
|
|
break;
|
|
break;
|
|
|
|
|
|
case AMD_XGBE_AN_COMPLETE:
|
|
case AMD_XGBE_AN_COMPLETE:
|
|
|
|
+ priv->parallel_detect = an_supported ? 0 : 1;
|
|
netdev_info(phydev->attached_dev, "%s successful\n",
|
|
netdev_info(phydev->attached_dev, "%s successful\n",
|
|
an_supported ? "Auto negotiation"
|
|
an_supported ? "Auto negotiation"
|
|
: "Parallel detection");
|
|
: "Parallel detection");
|
|
@@ -1150,7 +1175,8 @@ static int amd_xgbe_phy_read_status(struct phy_device *phydev)
|
|
if (ret)
|
|
if (ret)
|
|
return ret;
|
|
return ret;
|
|
|
|
|
|
- if (phydev->autoneg == AUTONEG_ENABLE) {
|
|
|
|
|
|
+ if ((phydev->autoneg == AUTONEG_ENABLE) &&
|
|
|
|
+ !priv->parallel_detect) {
|
|
if (!(mmd_mask & MDIO_DEVS_AN))
|
|
if (!(mmd_mask & MDIO_DEVS_AN))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|