Merge branch 'master' of git://git.denx.de/u-boot-ti
[oweals/u-boot.git] / drivers / net / cpsw.c
index dc0a2be23bccf21cbd366861e774a68c33183817..52f8da67e1d9049da108238e8955ae2de3d0fce5 100644 (file)
@@ -211,6 +211,8 @@ struct cpdma_chan {
 #define chan_read(chan, fld)           __raw_readl((chan)->fld)
 #define chan_read_ptr(chan, fld)       ((void *)__raw_readl((chan)->fld))
 
+#define for_active_slave(slave, priv) \
+       slave = (priv)->slaves + (priv)->data.active_slave; if (slave)
 #define for_each_slave(slave, priv) \
        for (slave = (priv)->slaves; slave != (priv)->slaves + \
                                (priv)->data.slaves; slave++)
@@ -233,7 +235,6 @@ struct cpsw_priv {
        struct phy_device               *phydev;
        struct mii_dev                  *bus;
 
-       u32                             mdio_link;
        u32                             phy_mask;
 };
 
@@ -487,7 +488,7 @@ static inline void wait_for_idle(void)
 static int cpsw_mdio_read(struct mii_dev *bus, int phy_id,
                                int dev_addr, int phy_reg)
 {
-       unsigned short data;
+       int data;
        u32 reg;
 
        if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
@@ -568,9 +569,14 @@ static void cpsw_set_slave_mac(struct cpsw_slave *slave,
 static void cpsw_slave_update_link(struct cpsw_slave *slave,
                                   struct cpsw_priv *priv, int *link)
 {
-       struct phy_device *phy = priv->phydev;
+       struct phy_device *phy;
        u32 mac_control = 0;
 
+       phy = priv->phydev;
+
+       if (!phy)
+               return;
+
        phy_startup(phy);
        *link = phy->link;
 
@@ -604,21 +610,10 @@ static int cpsw_update_link(struct cpsw_priv *priv)
        int link = 0;
        struct cpsw_slave *slave;
 
-       for_each_slave(slave, priv)
+       for_active_slave(slave, priv)
                cpsw_slave_update_link(slave, priv, &link);
-       priv->mdio_link = readl(&mdio_regs->link);
-       return link;
-}
-
-static int cpsw_check_link(struct cpsw_priv *priv)
-{
-       u32 link = 0;
 
-       link = __raw_readl(&mdio_regs->link) & priv->phy_mask;
-       if ((link) && (link == priv->mdio_link))
-               return 1;
-
-       return cpsw_update_link(priv);
+       return link;
 }
 
 static inline u32  cpsw_get_slave_port(struct cpsw_priv *priv, u32 slave_num)
@@ -651,7 +646,7 @@ static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv)
 
        cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << slave_port);
 
-       priv->phy_mask |= 1 << slave->data->phy_id;
+       priv->phy_mask |= 1 << slave->data->phy_addr;
 }
 
 static struct cpdma_desc *cpdma_desc_alloc(struct cpsw_priv *priv)
@@ -772,6 +767,7 @@ static int cpsw_init(struct eth_device *dev, bd_t *bis)
 
        /* enable statistics collection only on the host port */
        __raw_writel(BIT(priv->host_port), &priv->regs->stat_port_en);
+       __raw_writel(0x7, &priv->regs->stat_port_en);
 
        cpsw_ale_port_state(priv, priv->host_port, ALE_PORT_STATE_FORWARD);
 
@@ -779,7 +775,7 @@ static int cpsw_init(struct eth_device *dev, bd_t *bis)
                           ALE_SECURE);
        cpsw_ale_add_mcast(priv, NetBcastAddr, 1 << priv->host_port);
 
-       for_each_slave(slave, priv)
+       for_active_slave(slave, priv)
                cpsw_slave_init(slave, priv);
 
        cpsw_update_link(priv);
@@ -883,9 +879,6 @@ static int cpsw_send(struct eth_device *dev, void *packet, int length)
        int len;
        int timeout = CPDMA_TIMEOUT;
 
-       if (!cpsw_check_link(priv))
-               return -EIO;
-
        flush_dcache_range((unsigned long)packet,
                           (unsigned long)packet + length);
 
@@ -908,8 +901,6 @@ static int cpsw_recv(struct eth_device *dev)
        void *buffer;
        int len;
 
-       cpsw_update_link(priv);
-
        while (cpdma_process(priv, &priv->rx_chan, &buffer, &len) >= 0) {
                invalidate_dcache_range((unsigned long)buffer,
                                        (unsigned long)buffer + PKTSIZE_ALIGN);
@@ -935,17 +926,16 @@ static int cpsw_phy_init(struct eth_device *dev, struct cpsw_slave *slave)
 {
        struct cpsw_priv *priv = (struct cpsw_priv *)dev->priv;
        struct phy_device *phydev;
-       u32 supported = (SUPPORTED_10baseT_Half |
-                       SUPPORTED_10baseT_Full |
-                       SUPPORTED_100baseT_Half |
-                       SUPPORTED_100baseT_Full |
-                       SUPPORTED_1000baseT_Full);
+       u32 supported = PHY_GBIT_FEATURES;
 
        phydev = phy_connect(priv->bus,
-                       CONFIG_PHY_ADDR,
+                       slave->data->phy_addr,
                        dev,
                        slave->data->phy_if);
 
+       if (!phydev)
+               return -1;
+
        phydev->supported &= supported;
        phydev->advertising = phydev->supported;
 
@@ -1008,7 +998,7 @@ int cpsw_register(struct cpsw_platform_data *data)
 
        cpsw_mdio_init(dev->name, data->mdio_base, data->mdio_div);
        priv->bus = miiphy_get_dev_by_name(dev->name);
-       for_each_slave(slave, priv)
+       for_active_slave(slave, priv)
                cpsw_phy_init(dev, slave);
 
        return 1;