diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/fec_mpc52xx.c | 97 | ||||
-rw-r--r-- | drivers/net/fec_mpc52xx.h | 19 |
2 files changed, 74 insertions, 42 deletions
diff --git a/drivers/net/fec_mpc52xx.c b/drivers/net/fec_mpc52xx.c index d21b7ab64bd1..5f9c42e7a7f1 100644 --- a/drivers/net/fec_mpc52xx.c +++ b/drivers/net/fec_mpc52xx.c @@ -43,6 +43,29 @@ #define DRIVER_NAME "mpc52xx-fec" +#define FEC5200_PHYADDR_NONE (-1) +#define FEC5200_PHYADDR_7WIRE (-2) + +/* Private driver data structure */ +struct mpc52xx_fec_priv { + int duplex; + int speed; + int r_irq; + int t_irq; + struct mpc52xx_fec __iomem *fec; + struct bcom_task *rx_dmatsk; + struct bcom_task *tx_dmatsk; + spinlock_t lock; + int msg_enable; + + /* MDIO link details */ + int phy_addr; + unsigned int phy_speed; + struct phy_device *phydev; + enum phy_state link; +}; + + static irqreturn_t mpc52xx_fec_interrupt(int, void *); static irqreturn_t mpc52xx_fec_rx_interrupt(int, void *); static irqreturn_t mpc52xx_fec_tx_interrupt(int, void *); @@ -223,7 +246,7 @@ static int mpc52xx_fec_phy_start(struct net_device *dev) struct mpc52xx_fec_priv *priv = netdev_priv(dev); int err; - if (!priv->has_phy) + if (priv->phy_addr < 0) return 0; err = mpc52xx_fec_init_phy(dev); @@ -243,7 +266,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev) { struct mpc52xx_fec_priv *priv = netdev_priv(dev); - if (!priv->has_phy) + if (!priv->phydev) return; phy_disconnect(priv->phydev); @@ -255,7 +278,7 @@ static void mpc52xx_fec_phy_stop(struct net_device *dev) static int mpc52xx_fec_phy_mii_ioctl(struct mpc52xx_fec_priv *priv, struct mii_ioctl_data *mii_data, int cmd) { - if (!priv->has_phy) + if (!priv->phydev) return -ENOTSUPP; return phy_mii_ioctl(priv->phydev, mii_data, cmd); @@ -265,7 +288,7 @@ static void mpc52xx_fec_phy_hw_init(struct mpc52xx_fec_priv *priv) { struct mpc52xx_fec __iomem *fec = priv->fec; - if (!priv->has_phy) + if (priv->phydev) return; out_be32(&fec->mii_speed, priv->phy_speed); @@ -704,7 +727,7 @@ static void mpc52xx_fec_start(struct net_device *dev) rcntrl = FEC_RX_BUFFER_SIZE << 16; /* max frame length */ rcntrl |= FEC_RCNTRL_FCE; - if (priv->has_phy) + if (priv->phy_addr != FEC5200_PHYADDR_7WIRE) rcntrl |= FEC_RCNTRL_MII_MODE; if (priv->duplex == DUPLEX_FULL) @@ -864,7 +887,10 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) struct net_device *ndev; struct mpc52xx_fec_priv *priv = NULL; struct resource mem; - const phandle *ph; + struct device_node *phy_node; + const phandle *phy_handle; + const u32 *prop; + int prop_size; phys_addr_t rx_fifo; phys_addr_t tx_fifo; @@ -948,26 +974,37 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) mpc52xx_fec_get_paddr(ndev, ndev->dev_addr); priv->msg_enable = netif_msg_init(debug, MPC52xx_MESSAGES_DEFAULT); - priv->duplex = DUPLEX_FULL; - - /* is the phy present in device tree? */ - ph = of_get_property(op->node, "phy-handle", NULL); - if (ph) { - const unsigned int *prop; - struct device_node *phy_dn; - priv->has_phy = 1; - phy_dn = of_find_node_by_phandle(*ph); - prop = of_get_property(phy_dn, "reg", NULL); - priv->phy_addr = *prop; + /* + * Link mode configuration + */ - of_node_put(phy_dn); + /* Start with safe defaults for link connection */ + priv->phy_addr = FEC5200_PHYADDR_NONE; + priv->speed = 100; + priv->duplex = DUPLEX_HALF; + priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; + + /* the 7-wire property means don't use MII mode */ + if (of_find_property(op->node, "fsl,7-wire-mode", NULL)) + priv->phy_addr = FEC5200_PHYADDR_7WIRE; + + /* The current speed preconfigures the speed of the MII link */ + prop = of_get_property(op->node, "current-speed", &prop_size); + if (prop && (prop_size >= sizeof(u32) * 2)) { + priv->speed = prop[0]; + priv->duplex = prop[1] ? DUPLEX_FULL : DUPLEX_HALF; + } - /* Phy speed */ - priv->phy_speed = ((mpc52xx_find_ipb_freq(op->node) >> 20) / 5) << 1; - } else { - dev_info(&ndev->dev, "can't find \"phy-handle\" in device" - " tree, using 7-wire mode\n"); + /* If there is a phy handle, setup link to that phy */ + phy_handle = of_get_property(op->node, "phy-handle", &prop_size); + if (phy_handle && (prop_size >= sizeof(phandle))) { + phy_node = of_find_node_by_phandle(*phy_handle); + prop = of_get_property(phy_node, "reg", &prop_size); + if (prop && (prop_size >= sizeof(u32))) + if ((*prop >= 0) && (*prop < PHY_MAX_ADDR)) + priv->phy_addr = *prop; + of_node_put(phy_node); } /* Hardware init */ @@ -982,6 +1019,20 @@ mpc52xx_fec_probe(struct of_device *op, const struct of_device_id *match) if (rv < 0) goto probe_error; + /* Now report the link setup */ + switch (priv->phy_addr) { + case FEC5200_PHYADDR_NONE: + dev_info(&ndev->dev, "Fixed speed MII link: %i%cD\n", + priv->speed, priv->duplex ? 'F' : 'H'); + break; + case FEC5200_PHYADDR_7WIRE: + dev_info(&ndev->dev, "using 7-wire PHY mode\n"); + break; + default: + dev_info(&ndev->dev, "Using PHY at MDIO address %i\n", + priv->phy_addr); + } + /* We're done ! */ dev_set_drvdata(&op->dev, ndev); diff --git a/drivers/net/fec_mpc52xx.h b/drivers/net/fec_mpc52xx.h index 8b1f75397b9a..a227a525bdbb 100644 --- a/drivers/net/fec_mpc52xx.h +++ b/drivers/net/fec_mpc52xx.h @@ -26,25 +26,6 @@ #define FEC_WATCHDOG_TIMEOUT ((400*HZ)/1000) -struct mpc52xx_fec_priv { - int duplex; - int r_irq; - int t_irq; - struct mpc52xx_fec __iomem *fec; - struct bcom_task *rx_dmatsk; - struct bcom_task *tx_dmatsk; - spinlock_t lock; - int msg_enable; - - int has_phy; - unsigned int phy_speed; - unsigned int phy_addr; - struct phy_device *phydev; - enum phy_state link; - int speed; -}; - - /* ======================================================================== */ /* Hardware register sets & bits */ /* ======================================================================== */ |