From: gnandiba@amd.com
To: dev@dpdk.org
Subject: [dpdk-dev] [PATCH v2 2/2] net/axgbe: auto-negotiation support enabled for 1Gbps
Date: Fri, 10 Jan 2020 18:30:11 +0530 [thread overview]
Message-ID: <20200110130011.6244-1-gnandiba@amd.com> (raw)
From: Girish Nandibasappa <girish.nandibasappa@amd.com>
Added CL37 Auto-neg support for 1Gbps interface in
axgbe DPDK driver
Signed-off-by: Girish Nandibasappa <girish.nandibasappa@amd.com>
---
drivers/net/axgbe/axgbe_common.h | 1 +
drivers/net/axgbe/axgbe_mdio.c | 192 +++++++++++++++++++++++++++--
drivers/net/axgbe/axgbe_phy_impl.c | 37 ++++++
3 files changed, 219 insertions(+), 11 deletions(-)
diff --git a/drivers/net/axgbe/axgbe_common.h b/drivers/net/axgbe/axgbe_common.h
index 34f60f156..99fa92d5c 100644
--- a/drivers/net/axgbe/axgbe_common.h
+++ b/drivers/net/axgbe/axgbe_common.h
@@ -1296,6 +1296,7 @@
#define AXGBE_AN_CL37_PCS_MODE_BASEX 0x00
#define AXGBE_AN_CL37_PCS_MODE_SGMII 0x04
#define AXGBE_AN_CL37_TX_CONFIG_MASK 0x08
+#define AXGBE_AN_CL37_MII_CTRL_8BIT 0x0100
#define AXGBE_PMA_CDR_TRACK_EN_MASK 0x01
#define AXGBE_PMA_CDR_TRACK_EN_OFF 0x00
diff --git a/drivers/net/axgbe/axgbe_mdio.c b/drivers/net/axgbe/axgbe_mdio.c
index 2721e5cc9..3902b1ec3 100644
--- a/drivers/net/axgbe/axgbe_mdio.c
+++ b/drivers/net/axgbe/axgbe_mdio.c
@@ -29,6 +29,19 @@ static void axgbe_an37_disable_interrupts(struct axgbe_port *pdata)
XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
}
+static void axgbe_an37_enable_interrupts(struct axgbe_port *pdata)
+{
+ unsigned int reg;
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL);
+ reg |= AXGBE_PCS_CL37_BP;
+ XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_PCS_DIG_CTRL, reg);
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+ reg |= AXGBE_AN_CL37_INT_MASK;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
+}
+
static void axgbe_an73_clear_interrupts(struct axgbe_port *pdata)
{
XMDIO_WRITE(pdata, MDIO_MMD_AN, MDIO_AN_INT, 0);
@@ -54,7 +67,7 @@ static void axgbe_an_enable_interrupts(struct axgbe_port *pdata)
break;
case AXGBE_AN_MODE_CL37:
case AXGBE_AN_MODE_CL37_SGMII:
- PMD_DRV_LOG(ERR, "Unsupported AN_MOD_37\n");
+ axgbe_an37_enable_interrupts(pdata);
break;
default:
break;
@@ -254,6 +267,12 @@ static void axgbe_an37_set(struct axgbe_port *pdata, bool enable,
XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_CTRL1, reg);
}
+static void axgbe_an37_restart(struct axgbe_port *pdata)
+{
+ axgbe_an37_enable_interrupts(pdata);
+ axgbe_an37_set(pdata, true, true);
+}
+
static void axgbe_an37_disable(struct axgbe_port *pdata)
{
axgbe_an37_set(pdata, false, false);
@@ -302,7 +321,7 @@ static void axgbe_an_restart(struct axgbe_port *pdata)
break;
case AXGBE_AN_MODE_CL37:
case AXGBE_AN_MODE_CL37_SGMII:
- PMD_DRV_LOG(ERR, "Unsupported AN_MODE_CL37\n");
+ axgbe_an37_restart(pdata);
break;
default:
break;
@@ -321,7 +340,7 @@ static void axgbe_an_disable(struct axgbe_port *pdata)
break;
case AXGBE_AN_MODE_CL37:
case AXGBE_AN_MODE_CL37_SGMII:
- PMD_DRV_LOG(ERR, "Unsupported AN_MODE_CL37\n");
+ axgbe_an37_disable(pdata);
break;
default:
break;
@@ -573,6 +592,53 @@ static void axgbe_an73_state_machine(struct axgbe_port *pdata)
axgbe_an73_enable_interrupts(pdata);
}
+static void axgbe_an37_state_machine(struct axgbe_port *pdata)
+{
+ enum axgbe_an cur_state = pdata->an_state;
+
+ if (!pdata->an_int)
+ return;
+ if (pdata->an_int & AXGBE_AN_CL37_INT_CMPLT) {
+ pdata->an_state = AXGBE_AN_COMPLETE;
+ pdata->an_int &= ~AXGBE_AN_CL37_INT_CMPLT;
+
+ /* If SGMII is enabled, check the link status */
+ if (pdata->an_mode == AXGBE_AN_MODE_CL37_SGMII &&
+ !(pdata->an_status & AXGBE_SGMII_AN_LINK_STATUS))
+ pdata->an_state = AXGBE_AN_NO_LINK;
+ }
+
+ cur_state = pdata->an_state;
+
+ switch (pdata->an_state) {
+ case AXGBE_AN_READY:
+ break;
+ case AXGBE_AN_COMPLETE:
+ break;
+ case AXGBE_AN_NO_LINK:
+ break;
+ default:
+ pdata->an_state = AXGBE_AN_ERROR;
+ break;
+ }
+
+ if (pdata->an_state == AXGBE_AN_ERROR) {
+ PMD_DRV_LOG(ERR, "error during auto-negotiation, state=%u\n",
+ cur_state);
+ pdata->an_int = 0;
+ axgbe_an37_clear_interrupts(pdata);
+ }
+
+ if (pdata->an_state >= AXGBE_AN_COMPLETE) {
+ pdata->an_result = pdata->an_state;
+ pdata->an_state = AXGBE_AN_READY;
+ if (pdata->phy_if.phy_impl.an_post)
+ pdata->phy_if.phy_impl.an_post(pdata);
+ }
+
+ axgbe_an37_enable_interrupts(pdata);
+}
+
static void axgbe_an73_isr(struct axgbe_port *pdata)
{
/* Disable AN interrupts */
@@ -580,6 +646,7 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
/* Save the interrupt(s) that fired */
pdata->an_int = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_INT);
+ axgbe_an73_clear_interrupts(pdata);
if (pdata->an_int) {
/* Clear the interrupt(s) that fired and process them */
@@ -593,6 +660,29 @@ static void axgbe_an73_isr(struct axgbe_port *pdata)
}
}
+static void axgbe_an37_isr(struct axgbe_port *pdata)
+{
+ unsigned int reg = 0;
+ /* Disable AN interrupts */
+ axgbe_an37_disable_interrupts(pdata);
+
+ /* Save the interrupt(s) that fired */
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT);
+ pdata->an_int = reg & AXGBE_AN_CL37_INT_MASK;
+ pdata->an_status = reg & ~AXGBE_AN_CL37_INT_MASK;
+ axgbe_an37_clear_interrupts(pdata);
+
+ if (pdata->an_int & 0x01) {
+ /* Clear the interrupt(s) that fired and process them */
+ reg &= ~AXGBE_AN_CL37_INT_MASK;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_STAT, reg);
+ axgbe_an37_state_machine(pdata);
+ } else {
+ /* Enable AN interrupts */
+ axgbe_an37_enable_interrupts(pdata);
+ }
+}
+
static void axgbe_an_isr(struct axgbe_port *pdata)
{
switch (pdata->an_mode) {
@@ -602,7 +692,7 @@ static void axgbe_an_isr(struct axgbe_port *pdata)
break;
case AXGBE_AN_MODE_CL37:
case AXGBE_AN_MODE_CL37_SGMII:
- PMD_DRV_LOG(ERR, "AN_MODE_37 not supported\n");
+ axgbe_an37_isr(pdata);
break;
default:
break;
@@ -614,6 +704,48 @@ static void axgbe_an_combined_isr(struct axgbe_port *pdata)
axgbe_an_isr(pdata);
}
+static void axgbe_an37_init(struct axgbe_port *pdata)
+{
+ unsigned int advertising;
+ unsigned int reg = 0;
+
+ advertising = pdata->phy_if.phy_impl.an_advertising(pdata);
+
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE);
+ if (advertising & ADVERTISED_Pause)
+ reg |= 0x100;
+ else
+ reg &= ~0x100;
+ if (advertising & ADVERTISED_Asym_Pause)
+ reg |= 0x80;
+ else
+ reg &= ~0x80;
+
+ /* Full duplex, but not half */
+ reg |= AXGBE_AN_CL37_FD_MASK;
+ reg &= ~AXGBE_AN_CL37_HD_MASK;
+
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_ADVERTISE, reg);
+
+ /* Set up the Control register */
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL);
+ reg &= ~AXGBE_AN_CL37_TX_CONFIG_MASK;
+ reg &= ~AXGBE_AN_CL37_PCS_MODE_MASK;
+
+ switch (pdata->an_mode) {
+ case AXGBE_AN_MODE_CL37:
+ reg |= AXGBE_AN_CL37_PCS_MODE_BASEX;
+ break;
+ case AXGBE_AN_MODE_CL37_SGMII:
+ reg |= AXGBE_AN_CL37_PCS_MODE_SGMII;
+ break;
+ default:
+ break;
+ }
+ reg |= AXGBE_AN_CL37_MII_CTRL_8BIT;
+ XMDIO_WRITE(pdata, MDIO_MMD_VEND2, MDIO_VEND2_AN_CTRL, reg);
+}
+
static void axgbe_an73_init(struct axgbe_port *pdata)
{
unsigned int advertising, reg;
@@ -673,7 +805,7 @@ static void axgbe_an_init(struct axgbe_port *pdata)
break;
case AXGBE_AN_MODE_CL37:
case AXGBE_AN_MODE_CL37_SGMII:
- PMD_DRV_LOG(ERR, "Unsupported AN_CL37\n");
+ axgbe_an37_init(pdata);
break;
default:
break;
@@ -782,9 +914,6 @@ static int __axgbe_phy_config_aneg(struct axgbe_port *pdata)
/* Disable and stop any in progress auto-negotiation */
axgbe_an_disable_all(pdata);
- /* Clear any auto-negotitation interrupts */
- axgbe_an_clear_interrupts_all(pdata);
-
pdata->an_result = AXGBE_AN_READY;
pdata->an_state = AXGBE_AN_READY;
pdata->kr_state = AXGBE_RX_BPA;
@@ -792,6 +921,7 @@ static int __axgbe_phy_config_aneg(struct axgbe_port *pdata)
/* Re-enable auto-negotiation interrupt */
rte_intr_enable(&pdata->pci_dev->intr_handle);
+ axgbe_an37_enable_interrupts(pdata);
axgbe_an_init(pdata);
axgbe_an_restart(pdata);
@@ -875,10 +1005,26 @@ static void axgbe_phy_status_result(struct axgbe_port *pdata)
axgbe_set_mode(pdata, mode);
}
+static int autoneg_time_out(unsigned long autoneg_start_time)
+{
+ unsigned long autoneg_timeout;
+ unsigned long ticks;
+
+ autoneg_timeout = autoneg_start_time + (AXGBE_LINK_TIMEOUT *
+ 2 * rte_get_timer_hz());
+ ticks = rte_get_timer_cycles();
+ if (time_after(ticks, autoneg_timeout))
+ return 1;
+ else
+ return 0;
+}
+
static void axgbe_phy_status(struct axgbe_port *pdata)
{
unsigned int link_aneg;
- int an_restart;
+ int an_restart, ret;
+ unsigned int reg = 0;
+ unsigned long autoneg_start_time;
if (axgbe_test_bit(AXGBE_LINK_ERR, &pdata->dev_state)) {
pdata->phy.link = 0;
@@ -896,8 +1042,32 @@ static void axgbe_phy_status(struct axgbe_port *pdata)
if (pdata->phy.link) {
if (link_aneg && !axgbe_phy_aneg_done(pdata)) {
- axgbe_check_link_timeout(pdata);
- return;
+ if (axgbe_cur_mode(pdata) == AXGBE_MODE_SGMII_1000) {
+ /*autoneg not complete, so re-intializing*/
+ /* and restarting it*/
+ axgbe_an_init(pdata);
+ axgbe_an_restart(pdata);
+ reg = XMDIO_READ(pdata, MDIO_MMD_VEND2,
+ MDIO_VEND2_AN_STAT);
+ autoneg_start_time = rte_get_timer_cycles();
+ /*poll for autoneg to complete*/
+ while (!(reg & AXGBE_AN_CL37_INT_CMPLT)) {
+ ret =
+ autoneg_time_out(autoneg_start_time);
+ if (ret)
+ break;
+ reg = XMDIO_READ(pdata,
+ MDIO_MMD_VEND2,
+ MDIO_VEND2_AN_STAT);
+ if (reg & AXGBE_AN_CL37_INT_CMPLT) {
+ axgbe_an37_isr(pdata);
+ break;
+ }
+ }
+ } else {
+ axgbe_check_link_timeout(pdata);
+ return;
+ }
}
axgbe_phy_status_result(pdata);
if (axgbe_test_bit(AXGBE_LINK_INIT, &pdata->dev_state))
diff --git a/drivers/net/axgbe/axgbe_phy_impl.c b/drivers/net/axgbe/axgbe_phy_impl.c
index f0dc11695..a324a2bc9 100644
--- a/drivers/net/axgbe/axgbe_phy_impl.c
+++ b/drivers/net/axgbe/axgbe_phy_impl.c
@@ -957,6 +957,41 @@ static enum axgbe_mode axgbe_phy_an73_outcome(struct axgbe_port *pdata)
return mode;
}
+static enum axgbe_mode axgbe_phy_an37_sgmii_outcome(struct axgbe_port *pdata)
+{
+ enum axgbe_mode mode;
+
+ pdata->phy.lp_advertising |= ADVERTISED_Autoneg;
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+
+ if (pdata->phy.pause_autoneg)
+ axgbe_phy_phydev_flowctrl(pdata);
+
+ switch (pdata->an_status & AXGBE_SGMII_AN_LINK_SPEED) {
+ case AXGBE_SGMII_AN_LINK_SPEED_100:
+ if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
+ pdata->phy.lp_advertising |= ADVERTISED_100baseT_Full;
+ mode = AXGBE_MODE_SGMII_100;
+ } else {
+ mode = AXGBE_MODE_UNKNOWN;
+ }
+ break;
+ case AXGBE_SGMII_AN_LINK_SPEED_1000:
+ if (pdata->an_status & AXGBE_SGMII_AN_LINK_DUPLEX) {
+ pdata->phy.lp_advertising |= ADVERTISED_1000baseT_Full;
+ mode = AXGBE_MODE_SGMII_1000;
+ } else {
+ /* Half-duplex not supported */
+ mode = AXGBE_MODE_UNKNOWN;
+ }
+ break;
+ default:
+ mode = AXGBE_MODE_UNKNOWN;
+ break;
+ }
+ return mode;
+}
+
static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata)
{
switch (pdata->an_mode) {
@@ -966,6 +1001,7 @@ static enum axgbe_mode axgbe_phy_an_outcome(struct axgbe_port *pdata)
return axgbe_phy_an73_redrv_outcome(pdata);
case AXGBE_AN_MODE_CL37:
case AXGBE_AN_MODE_CL37_SGMII:
+ return axgbe_phy_an37_sgmii_outcome(pdata);
default:
return AXGBE_MODE_UNKNOWN;
}
@@ -1957,6 +1993,7 @@ static int axgbe_phy_start(struct axgbe_port *pdata)
default:
break;
}
+ pdata->phy.advertising &= axgbe_phy_an_advertising(pdata);
return ret;
}
--
2.17.1
reply other threads:[~2020-01-10 13:00 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20200110130011.6244-1-gnandiba@amd.com \
--to=gnandiba@amd.com \
--cc=dev@dpdk.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).