struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)dev->priv;
struct phy_device *phydev = NULL;
struct mii_dev *bus;
+ int phy_addr, phy_num;
+ int ret = 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;
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phy_addr = wriop_get_phy_address(priv->dpmac_id, phy_num);
+ if (phy_addr < 0)
+ continue;
+
+ phydev = phy_connect(bus, phy_addr, dev,
+ wriop_get_enet_if(priv->dpmac_id));
+ if (!phydev) {
+ printf("Failed to connect\n");
+ ret = -ENODEV;
+ break;
+ }
+ wriop_set_phy_dev(priv->dpmac_id, phy_num, phydev);
+ ret = phy_config(phydev);
+ if (ret)
+ break;
}
- priv->phydev = phydev;
+ if (ret) {
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
+ if (!phydev)
+ continue;
- return phy_config(phydev);
+ free(phydev);
+ wriop_set_phy_dev(priv->dpmac_id, phy_num, NULL);
+ }
+ }
+
+ return ret;
}
#endif
return err;
}
+static int ldpaa_get_dpmac_state(struct ldpaa_eth_priv *priv,
+ struct dpmac_link_state *state)
+{
+ struct phy_device *phydev = NULL;
+ phy_interface_t enet_if;
+ int phy_num, phys_detected;
+ int err;
+
+ /* let's start off with maximum capabilities */
+ enet_if = wriop_get_enet_if(priv->dpmac_id);
+ switch (enet_if) {
+ case PHY_INTERFACE_MODE_XGMII:
+ state->rate = SPEED_10000;
+ break;
+ default:
+ state->rate = SPEED_1000;
+ break;
+ }
+ state->up = 1;
+
+ phys_detected = 0;
+#ifdef CONFIG_PHYLIB
+ state->options |= DPMAC_LINK_OPT_AUTONEG;
+
+ /* start the phy devices one by one and update the dpmac state */
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
+ if (!phydev)
+ continue;
+
+ phys_detected++;
+ err = phy_startup(phydev);
+ if (err) {
+ printf("%s: Could not initialize\n", phydev->dev->name);
+ state->up = 0;
+ break;
+ }
+ if (phydev->link) {
+ state->rate = min(state->rate, (uint32_t)phydev->speed);
+ if (!phydev->duplex)
+ state->options |= DPMAC_LINK_OPT_HALF_DUPLEX;
+ if (!phydev->autoneg)
+ state->options &= ~DPMAC_LINK_OPT_AUTONEG;
+ } else {
+ /* break out of loop even if one phy is down */
+ state->up = 0;
+ break;
+ }
+ }
+#endif
+ if (!phys_detected)
+ state->options &= ~DPMAC_LINK_OPT_AUTONEG;
+
+ if (!state->up) {
+ state->rate = 0;
+ state->options = 0;
+ return -ENOLINK;
+ }
+
+ return 0;
+}
+
static int ldpaa_eth_open(struct eth_device *net_dev, bd_t *bd)
{
struct ldpaa_eth_priv *priv = (struct ldpaa_eth_priv *)net_dev->priv;
struct dpni_link_state link_state;
#endif
int err = 0;
- struct mii_dev *bus;
- phy_interface_t enet_if;
struct dpni_queue d_queue;
if (net_dev->state == ETH_STATE_ACTIVE)
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_dpmac_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;
+ err = ldpaa_get_dpmac_state(priv, &dpmac_link_state);
+ if (err < 0)
goto err_dpmac_bind;
- }
/* DPMAC binding DPNI */
err = ldpaa_dpmac_bind(priv);
return err;
}
- 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) {
goto err_qdid;
}
- return priv->phydev->link;
+ return dpmac_link_state.up;
err_qdid:
err_get_queue:
{
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
+ struct phy_device *phydev = NULL;
+ int phy_num;
if ((net_dev->state == ETH_STATE_PASSIVE) ||
(net_dev->state == ETH_STATE_INIT))
printf("dpni_disable() failed\n");
#ifdef CONFIG_PHYLIB
- if (priv->phydev && bus != NULL)
- phy_shutdown(priv->phydev);
- else {
- free(priv->phydev);
- priv->phydev = NULL;
+ for (phy_num = 0; phy_num < WRIOP_MAX_PHY_NUM; phy_num++) {
+ phydev = wriop_get_phy_dev(priv->dpmac_id, phy_num);
+ if (phydev)
+ phy_shutdown(phydev);
}
#endif