[U-Boot] [PATCH 1/2] driver: net: ldpaa_eth: Add support of PHY framework

This patch integrate DPAA2 ethernet driver existing PHY framework.
Call phy_connect and phy_config as per available DPMAC id defined in SerDes Protcol.
Signed-off-by: Pratiyush Mohan Srivastava pratiyush.srivastava@nxp.com Signed-off-by: Prabhakar Kushwaha prabhakar.kushwaha@nxp.com --- drivers/net/ldpaa_eth/ldpaa_eth.c | 116 ++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 3857122..0a82bc6 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -14,15 +14,34 @@ #include <linux/compat.h> #include <fsl-mc/fsl_dpmac.h>
+#include <fsl-mc/ldpaa_wriop.h> #include "ldpaa_eth.h"
-#undef CONFIG_PHYLIB +#ifdef CONFIG_PHYLIB static int init_phy(struct eth_device *dev) { - /*TODO for external PHY */ + struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv; + struct phy_device *phydev = NULL; + struct mii_dev *bus; + + bus = wriop_get_mdio(priv->dpmac_id); + if (bus == NULL) + return 0; + + phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id), + dev, wriop_get_enet_if(priv->dpmac_id)); + if (!phydev) { + printf("Failed to connect\n"); + return -1; + } + + priv->phydev = phydev; + + phy_config(phydev);
return 0; } +#endif
#ifdef DEBUG static void ldpaa_eth_get_dpni_counter(void) @@ -303,7 +322,9 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) #ifdef DEBUG struct dpni_link_state link_state; #endif - int err; + int err = 0; + struct mii_dev *bus; + phy_interface_t enet_if;
if (net_dev->state == ETH_STATE_ACTIVE) return 0; @@ -317,11 +338,48 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) printf("ERROR (DPL is deployed. No device available)\n"); return -ENODEV; } + /* DPMAC initialization */ err = ldpaa_dpmac_setup(priv); if (err < 0) goto err_dpmac_setup;
+#ifdef CONFIG_PHYLIB + if (priv->phydev) + err = phy_startup(priv->phydev); + if (err) { + printf("%s: Could not initialize\n", + priv->phydev->dev->name); + goto err_dpamc_bind; + } +#else + priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device)); + memset(priv->phydev, 0, sizeof(struct phy_device)); + + priv->phydev->speed = SPEED_1000; + priv->phydev->link = 1; + priv->phydev->duplex = DUPLEX_FULL; +#endif + + bus = wriop_get_mdio(priv->dpmac_id); + enet_if = wriop_get_enet_if(priv->dpmac_id); + if ((bus == NULL) && + (enet_if == PHY_INTERFACE_MODE_XGMII)) { + priv->phydev = (struct phy_device *) + malloc(sizeof(struct phy_device)); + memset(priv->phydev, 0, sizeof(struct phy_device)); + + priv->phydev->speed = SPEED_10000; + priv->phydev->link = 1; + priv->phydev->duplex = DUPLEX_FULL; + } + + if (!priv->phydev->link) { + printf("%s: No link.\n", priv->phydev->dev->name); + err = -1; + goto err_dpamc_bind; + } + /* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); if (err) @@ -348,28 +406,24 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; }
-#ifdef CONFIG_PHYLIB - /* TODO Check this path */ - err = phy_startup(priv->phydev); - if (err) { - printf("%s: Could not initialize\n", priv->phydev->dev->name); - return err; - } -#else - priv->phydev->speed = SPEED_1000; - priv->phydev->link = 1; - priv->phydev->duplex = DUPLEX_FULL; -#endif - err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); if (err < 0) { printf("dpni_enable() failed\n"); return err; }
- dpmac_link_state.rate = SPEED_1000; - dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG; - dpmac_link_state.up = 1; + dpmac_link_state.rate = priv->phydev->speed; + + if (priv->phydev->autoneg == AUTONEG_DISABLE) + dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG; + else + dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG; + + if (priv->phydev->duplex == DUPLEX_HALF) + dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX; + + dpmac_link_state.up = priv->phydev->link; + err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) { @@ -407,10 +461,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; }
- if (!priv->phydev->link) - printf("%s: No link.\n", priv->phydev->dev->name); - - return priv->phydev->link ? 0 : -1; + return priv->phydev->link;
err_qdid: err_rx_flow: @@ -418,9 +469,10 @@ err_rx_flow: err_dpni_bind: ldpaa_dpbp_free(); err_dpbp_setup: -err_dpamc_bind: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: +err_dpamc_bind: + dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle); err_dpmac_setup: return err; } @@ -429,6 +481,9 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; +#ifdef CONFIG_PHYLIB + struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id); +#endif
if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT)) @@ -453,7 +508,10 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n");
#ifdef CONFIG_PHYLIB - phy_shutdown(priv->phydev); + if (priv->phydev && bus != NULL) + phy_shutdown(priv->phydev); + else + free(priv->phydev); #endif
ldpaa_dpbp_free(); @@ -798,15 +856,11 @@ static int ldpaa_eth_netdev_init(struct eth_device *net_dev, net_dev->halt = ldpaa_eth_stop; net_dev->send = ldpaa_eth_tx; net_dev->recv = ldpaa_eth_pull_dequeue_rx; -/* - TODO: PHY MDIO information - priv->bus = info->bus; - priv->phyaddr = info->phy_addr; - priv->enet_if = info->enet_if; -*/
+#ifdef CONFIG_PHYLIB if (init_phy(net_dev)) return 0; +#endif
err = eth_register(net_dev); if (err < 0) {

On 01/19/2016 10:35 PM, Prabhakar Kushwaha wrote:
This patch integrate DPAA2 ethernet driver existing PHY framework.
Call phy_connect and phy_config as per available DPMAC id defined in SerDes Protcol.
Signed-off-by: Pratiyush Mohan Srivastava pratiyush.srivastava@nxp.com Signed-off-by: Prabhakar Kushwaha prabhakar.kushwaha@nxp.com
For future patches related to network, please CC Joe so he is aware your change.
York

On Wed, Jan 20, 2016 at 12:34 AM, Prabhakar Kushwaha prabhakar.kushwaha@nxp.com wrote:
This patch integrate DPAA2 ethernet driver existing PHY framework.
Call phy_connect and phy_config as per available DPMAC id defined in SerDes Protcol.
Signed-off-by: Pratiyush Mohan Srivastava pratiyush.srivastava@nxp.com Signed-off-by: Prabhakar Kushwaha prabhakar.kushwaha@nxp.com
drivers/net/ldpaa_eth/ldpaa_eth.c | 116 ++++++++++++++++++++++++++++---------- 1 file changed, 85 insertions(+), 31 deletions(-)
diff --git a/drivers/net/ldpaa_eth/ldpaa_eth.c b/drivers/net/ldpaa_eth/ldpaa_eth.c index 3857122..0a82bc6 100644 --- a/drivers/net/ldpaa_eth/ldpaa_eth.c +++ b/drivers/net/ldpaa_eth/ldpaa_eth.c @@ -14,15 +14,34 @@ #include <linux/compat.h> #include <fsl-mc/fsl_dpmac.h>
+#include <fsl-mc/ldpaa_wriop.h> #include "ldpaa_eth.h"
-#undef CONFIG_PHYLIB +#ifdef CONFIG_PHYLIB static int init_phy(struct eth_device *dev) {
/*TODO for external PHY */
struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
struct phy_device *phydev = NULL;
struct mii_dev *bus;
bus = wriop_get_mdio(priv->dpmac_id);
if (bus == NULL)
return 0;
phydev = phy_connect(bus, wriop_get_phy_address(priv->dpmac_id),
dev, wriop_get_enet_if(priv->dpmac_id));
if (!phydev) {
printf("Failed to connect\n");
return -1;
}
priv->phydev = phydev;
phy_config(phydev);
Seems you should be returning the value from this call.
return 0;
Instead of 0.
} +#endif
#ifdef DEBUG static void ldpaa_eth_get_dpni_counter(void) @@ -303,7 +322,9 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) #ifdef DEBUG struct dpni_link_state link_state; #endif
int err;
int err = 0;
struct mii_dev *bus;
phy_interface_t enet_if; if (net_dev->state == ETH_STATE_ACTIVE) return 0;
@@ -317,11 +338,48 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) printf("ERROR (DPL is deployed. No device available)\n"); return -ENODEV; }
/* DPMAC initialization */ err = ldpaa_dpmac_setup(priv); if (err < 0) goto err_dpmac_setup;
+#ifdef CONFIG_PHYLIB
if (priv->phydev)
err = phy_startup(priv->phydev);
if (err) {
printf("%s: Could not initialize\n",
priv->phydev->dev->name);
goto err_dpamc_bind;
}
+#else
Is there actually a reason to support !CONFIG_PHYLIB?
priv->phydev = (struct phy_device *)malloc(sizeof(struct phy_device));
memset(priv->phydev, 0, sizeof(struct phy_device));
priv->phydev->speed = SPEED_1000;
priv->phydev->link = 1;
priv->phydev->duplex = DUPLEX_FULL;
+#endif
bus = wriop_get_mdio(priv->dpmac_id);
enet_if = wriop_get_enet_if(priv->dpmac_id);
if ((bus == NULL) &&
(enet_if == PHY_INTERFACE_MODE_XGMII)) {
priv->phydev = (struct phy_device *)
malloc(sizeof(struct phy_device));
memset(priv->phydev, 0, sizeof(struct phy_device));
priv->phydev->speed = SPEED_10000;
priv->phydev->link = 1;
priv->phydev->duplex = DUPLEX_FULL;
}
if (!priv->phydev->link) {
printf("%s: No link.\n", priv->phydev->dev->name);
err = -1;
goto err_dpamc_bind;
}
/* DPMAC binding DPNI */ err = ldpaa_dpmac_bind(priv); if (err)
@@ -348,28 +406,24 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) return err; }
-#ifdef CONFIG_PHYLIB
/* TODO Check this path */
err = phy_startup(priv->phydev);
if (err) {
printf("%s: Could not initialize\n", priv->phydev->dev->name);
return err;
}
-#else
priv->phydev->speed = SPEED_1000;
priv->phydev->link = 1;
priv->phydev->duplex = DUPLEX_FULL;
-#endif
err = dpni_enable(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); if (err < 0) { printf("dpni_enable() failed\n"); return err; }
dpmac_link_state.rate = SPEED_1000;
dpmac_link_state.options = DPMAC_LINK_OPT_AUTONEG;
dpmac_link_state.up = 1;
dpmac_link_state.rate = priv->phydev->speed;
if (priv->phydev->autoneg == AUTONEG_DISABLE)
dpmac_link_state.options &= ~DPMAC_LINK_OPT_AUTONEG;
else
dpmac_link_state.options |= DPMAC_LINK_OPT_AUTONEG;
if (priv->phydev->duplex == DUPLEX_HALF)
dpmac_link_state.options |= DPMAC_LINK_OPT_HALF_DUPLEX;
dpmac_link_state.up = priv->phydev->link;
err = dpmac_set_link_state(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle, &dpmac_link_state); if (err < 0) {
@@ -407,10 +461,7 @@ static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd) goto err_qdid; }
if (!priv->phydev->link)
printf("%s: No link.\n", priv->phydev->dev->name);
return priv->phydev->link ? 0 : -1;
return priv->phydev->link;
err_qdid: err_rx_flow: @@ -418,9 +469,10 @@ err_rx_flow: err_dpni_bind: ldpaa_dpbp_free(); err_dpbp_setup: -err_dpamc_bind: dpni_close(dflt_mc_io, MC_CMD_NO_FLAGS, dflt_dpni->dpni_handle); err_dpni_setup: +err_dpamc_bind:
dpmac_destroy(dflt_mc_io, MC_CMD_NO_FLAGS, priv->dpmac_handle);
err_dpmac_setup: return err; } @@ -429,6 +481,9 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) { struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv; int err = 0; +#ifdef CONFIG_PHYLIB
struct mii_dev *bus = wriop_get_mdio(priv->dpmac_id);
+#endif
if ((net_dev->state == ETH_STATE_PASSIVE) || (net_dev->state == ETH_STATE_INIT))
@@ -453,7 +508,10 @@ static void ldpaa_eth_stop(struct eth_device *net_dev) printf("dpni_disable() failed\n");
#ifdef CONFIG_PHYLIB
phy_shutdown(priv->phydev);
if (priv->phydev && bus != NULL)
phy_shutdown(priv->phydev);
else
free(priv->phydev);
#endif
ldpaa_dpbp_free();
@@ -798,15 +856,11 @@ static int ldpaa_eth_netdev_init(struct eth_device *net_dev, net_dev->halt = ldpaa_eth_stop; net_dev->send = ldpaa_eth_tx; net_dev->recv = ldpaa_eth_pull_dequeue_rx; -/*
TODO: PHY MDIO information
priv->bus = info->bus;
priv->phyaddr = info->phy_addr;
priv->enet_if = info->enet_if;
-*/
+#ifdef CONFIG_PHYLIB if (init_phy(net_dev)) return 0;
It seems like you should be returning an error if your new phy connection fails.
+#endif
err = eth_register(net_dev); if (err < 0) {
-- 1.9.1
U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot
participants (3)
-
Joe Hershberger
-
Prabhakar Kushwaha
-
york sun