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>
Reviewed-by: York Sun <york.sun@nxp.com>
master
Prabhakar Kushwaha 9 years ago committed by York Sun
parent b2b877306c
commit 6c2b520a37
  1. 121
      drivers/net/ldpaa_eth/ldpaa_eth.c

@ -14,15 +14,32 @@
#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;
return 0;
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;
return phy_config(phydev);
}
#endif
#ifdef DEBUG
static void ldpaa_eth_get_dpni_counter(void)
@ -380,7 +397,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;
@ -394,11 +413,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)
@ -425,28 +481,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) {
@ -484,10 +536,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:
@ -495,9 +544,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;
}
@ -506,6 +556,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))
@ -531,7 +584,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();
@ -914,15 +970,12 @@ 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;
*/
if (init_phy(net_dev))
return 0;
#ifdef CONFIG_PHYLIB
err = init_phy(net_dev);
if (err < 0)
return err;
#endif
err = eth_register(net_dev);
if (err < 0) {

Loading…
Cancel
Save