Merge branch 'mv88e6171_indirect_phy'
authorDavid S. Miller <davem@davemloft.net>
Thu, 19 Feb 2015 20:52:33 +0000 (15:52 -0500)
committerDavid S. Miller <davem@davemloft.net>
Thu, 19 Feb 2015 20:52:33 +0000 (15:52 -0500)
Andrew Lunn says:

====================
Indirect phy access for mv88e6171

These two patches allow the mv88e6171 driver to access the port phys
using indirect addressing. Depending on pin strapping, the switch
either uses a single address on the host MDIO bus, requiring the port
phys are accessed indirectly, or the switch uses a number of addresses
on the host bus and the phys can be directly accessed.

The 370RD, the first supported platform to use the 6171 uses multiple
addresses, so this indirect mode was not required. However the
WRT1900AC has the switch configured to use a single address, and so
indirect access is needed.

The mv88e6352 already has all the needed code. Refactor it into the
shared mv88e6xxx and then use it in the mv88e6171 driver.

Tested on the 370RD and WRT1900AC.

It would be good if Guenter Roeck could test on his platform to ensure
i've not broken anything for the mv88e6352.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/dsa/mv88e6171.c
drivers/net/dsa/mv88e6352.c
drivers/net/dsa/mv88e6xxx.c
drivers/net/dsa/mv88e6xxx.h

index aa33d16f2e22ec6b48f6332db928c9899ce82817..9808c860a797f713bbe0bc9b5d3a92e598848922 100644 (file)
@@ -51,8 +51,11 @@ static int mv88e6171_switch_reset(struct dsa_switch *ds)
        /* Wait for transmit queues to drain. */
        usleep_range(2000, 4000);
 
-       /* Reset the switch. */
-       REG_WRITE(REG_GLOBAL, 0x04, 0xc400);
+       /* Reset the switch. Keep PPU active.  The PPU needs to be
+        * active to support indirect phy register accesses through
+        * global registers 0x18 and 0x19.
+        */
+       REG_WRITE(REG_GLOBAL, 0x04, 0xc000);
 
        /* Wait up to one second for reset to complete. */
        timeout = jiffies + 1 * HZ;
@@ -83,11 +86,10 @@ static int mv88e6171_setup_global(struct dsa_switch *ds)
        int ret;
        int i;
 
-       /* Disable the PHY polling unit (since there won't be any
-        * external PHYs to poll), don't discard packets with
-        * excessive collisions, and mask all interrupt sources.
+       /* Discard packets with excessive collisions, mask all
+        * interrupt sources, enable PPU.
         */
-       REG_WRITE(REG_GLOBAL, 0x04, 0x0000);
+       REG_WRITE(REG_GLOBAL, 0x04, 0x6000);
 
        /* Set the default address aging time to 5 minutes, and
         * enable address learn messages to be sent to all message
@@ -336,7 +338,7 @@ mv88e6171_phy_read(struct dsa_switch *ds, int port, int regnum)
        int ret;
 
        mutex_lock(&ps->phy_mutex);
-       ret = mv88e6xxx_phy_read(ds, addr, regnum);
+       ret = mv88e6xxx_phy_read_indirect(ds, addr, regnum);
        mutex_unlock(&ps->phy_mutex);
        return ret;
 }
@@ -350,7 +352,7 @@ mv88e6171_phy_write(struct dsa_switch *ds,
        int ret;
 
        mutex_lock(&ps->phy_mutex);
-       ret = mv88e6xxx_phy_write(ds, addr, regnum, val);
+       ret = mv88e6xxx_phy_write_indirect(ds, addr, regnum, val);
        mutex_unlock(&ps->phy_mutex);
        return ret;
 }
index e13adc7b3ddaf4cc5742d99b68340f152ba50184..1ebd8f96072a1b00e943ca0247acdd2d5f5d40ab 100644 (file)
 #include <net/dsa.h>
 #include "mv88e6xxx.h"
 
-static int mv88e6352_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
-{
-       unsigned long timeout = jiffies + HZ / 10;
-
-       while (time_before(jiffies, timeout)) {
-               int ret;
-
-               ret = REG_READ(reg, offset);
-               if (!(ret & mask))
-                       return 0;
-
-               usleep_range(1000, 2000);
-       }
-       return -ETIMEDOUT;
-}
-
-static inline int mv88e6352_phy_wait(struct dsa_switch *ds)
-{
-       return mv88e6352_wait(ds, REG_GLOBAL2, 0x18, 0x8000);
-}
-
-static inline int mv88e6352_eeprom_load_wait(struct dsa_switch *ds)
-{
-       return mv88e6352_wait(ds, REG_GLOBAL2, 0x14, 0x0800);
-}
-
-static inline int mv88e6352_eeprom_busy_wait(struct dsa_switch *ds)
-{
-       return mv88e6352_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
-}
-
-static int __mv88e6352_phy_read(struct dsa_switch *ds, int addr, int regnum)
-{
-       int ret;
-
-       REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum);
-
-       ret = mv88e6352_phy_wait(ds);
-       if (ret < 0)
-               return ret;
-
-       return REG_READ(REG_GLOBAL2, 0x19);
-}
-
-static int __mv88e6352_phy_write(struct dsa_switch *ds, int addr, int regnum,
-                                u16 val)
-{
-       REG_WRITE(REG_GLOBAL2, 0x19, val);
-       REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum);
-
-       return mv88e6352_phy_wait(ds);
-}
-
 static char *mv88e6352_probe(struct device *host_dev, int sw_addr)
 {
        struct mii_bus *bus = dsa_host_dev_to_mii_bus(host_dev);
@@ -346,12 +293,12 @@ static int mv88e6352_phy_page_read(struct dsa_switch *ds,
        int ret;
 
        mutex_lock(&ps->phy_mutex);
-       ret = __mv88e6352_phy_write(ds, port, 0x16, page);
+       ret = mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
        if (ret < 0)
                goto error;
-       ret = __mv88e6352_phy_read(ds, port, reg);
+       ret = mv88e6xxx_phy_read_indirect(ds, port, reg);
 error:
-       __mv88e6352_phy_write(ds, port, 0x16, 0x0);
+       mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
        mutex_unlock(&ps->phy_mutex);
        return ret;
 }
@@ -363,13 +310,13 @@ static int mv88e6352_phy_page_write(struct dsa_switch *ds,
        int ret;
 
        mutex_lock(&ps->phy_mutex);
-       ret = __mv88e6352_phy_write(ds, port, 0x16, page);
+       ret = mv88e6xxx_phy_write_indirect(ds, port, 0x16, page);
        if (ret < 0)
                goto error;
 
-       ret = __mv88e6352_phy_write(ds, port, reg, val);
+       ret = mv88e6xxx_phy_write_indirect(ds, port, reg, val);
 error:
-       __mv88e6352_phy_write(ds, port, 0x16, 0x0);
+       mv88e6xxx_phy_write_indirect(ds, port, 0x16, 0x0);
        mutex_unlock(&ps->phy_mutex);
        return ret;
 }
@@ -482,7 +429,7 @@ mv88e6352_phy_read(struct dsa_switch *ds, int port, int regnum)
                return addr;
 
        mutex_lock(&ps->phy_mutex);
-       ret = __mv88e6352_phy_read(ds, addr, regnum);
+       ret = mv88e6xxx_phy_read_indirect(ds, addr, regnum);
        mutex_unlock(&ps->phy_mutex);
 
        return ret;
@@ -499,7 +446,7 @@ mv88e6352_phy_write(struct dsa_switch *ds, int port, int regnum, u16 val)
                return addr;
 
        mutex_lock(&ps->phy_mutex);
-       ret = __mv88e6352_phy_write(ds, addr, regnum, val);
+       ret = mv88e6xxx_phy_write_indirect(ds, addr, regnum, val);
        mutex_unlock(&ps->phy_mutex);
 
        return ret;
@@ -553,7 +500,7 @@ static int mv88e6352_read_eeprom_word(struct dsa_switch *ds, int addr)
        if (ret < 0)
                goto error;
 
-       ret = mv88e6352_eeprom_busy_wait(ds);
+       ret = mv88e6xxx_eeprom_busy_wait(ds);
        if (ret < 0)
                goto error;
 
@@ -576,7 +523,7 @@ static int mv88e6352_get_eeprom(struct dsa_switch *ds,
 
        eeprom->magic = 0xc3ec4951;
 
-       ret = mv88e6352_eeprom_load_wait(ds);
+       ret = mv88e6xxx_eeprom_load_wait(ds);
        if (ret < 0)
                return ret;
 
@@ -657,7 +604,7 @@ static int mv88e6352_write_eeprom_word(struct dsa_switch *ds, int addr,
        if (ret < 0)
                goto error;
 
-       ret = mv88e6352_eeprom_busy_wait(ds);
+       ret = mv88e6xxx_eeprom_busy_wait(ds);
 error:
        mutex_unlock(&ps->eeprom_mutex);
        return ret;
@@ -681,7 +628,7 @@ static int mv88e6352_set_eeprom(struct dsa_switch *ds,
        len = eeprom->len;
        eeprom->len = 0;
 
-       ret = mv88e6352_eeprom_load_wait(ds);
+       ret = mv88e6xxx_eeprom_load_wait(ds);
        if (ret < 0)
                return ret;
 
index 3e7e31a6abb73f28ea44c9314c4f3628337edab7..a83ace0803e79638d510ab8d2024a9dbcc0e055d 100644 (file)
@@ -596,6 +596,59 @@ error:
 }
 #endif /* CONFIG_NET_DSA_HWMON */
 
+static int mv88e6xxx_wait(struct dsa_switch *ds, int reg, int offset, u16 mask)
+{
+       unsigned long timeout = jiffies + HZ / 10;
+
+       while (time_before(jiffies, timeout)) {
+               int ret;
+
+               ret = REG_READ(reg, offset);
+               if (!(ret & mask))
+                       return 0;
+
+               usleep_range(1000, 2000);
+       }
+       return -ETIMEDOUT;
+}
+
+int mv88e6xxx_phy_wait(struct dsa_switch *ds)
+{
+       return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x18, 0x8000);
+}
+
+int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds)
+{
+       return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x0800);
+}
+
+int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds)
+{
+       return mv88e6xxx_wait(ds, REG_GLOBAL2, 0x14, 0x8000);
+}
+
+int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum)
+{
+       int ret;
+
+       REG_WRITE(REG_GLOBAL2, 0x18, 0x9800 | (addr << 5) | regnum);
+
+       ret = mv88e6xxx_phy_wait(ds);
+       if (ret < 0)
+               return ret;
+
+       return REG_READ(REG_GLOBAL2, 0x19);
+}
+
+int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
+                                u16 val)
+{
+       REG_WRITE(REG_GLOBAL2, 0x19, val);
+       REG_WRITE(REG_GLOBAL2, 0x18, 0x9400 | (addr << 5) | regnum);
+
+       return mv88e6xxx_phy_wait(ds);
+}
+
 static int __init mv88e6xxx_init(void)
 {
 #if IS_ENABLED(CONFIG_NET_DSA_MV88E6131)
index 03e397efde36949810503a16b601f3df61f3396c..72942271bb67ed988484e09c780a3ae46e54251c 100644 (file)
@@ -82,6 +82,12 @@ int mv88e6xxx_get_regs_len(struct dsa_switch *ds, int port);
 void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
                        struct ethtool_regs *regs, void *_p);
 int  mv88e6xxx_get_temp(struct dsa_switch *ds, int *temp);
+int mv88e6xxx_phy_wait(struct dsa_switch *ds);
+int mv88e6xxx_eeprom_load_wait(struct dsa_switch *ds);
+int mv88e6xxx_eeprom_busy_wait(struct dsa_switch *ds);
+int mv88e6xxx_phy_read_indirect(struct dsa_switch *ds, int addr, int regnum);
+int mv88e6xxx_phy_write_indirect(struct dsa_switch *ds, int addr, int regnum,
+                                u16 val);
 
 extern struct dsa_switch_driver mv88e6131_switch_driver;
 extern struct dsa_switch_driver mv88e6123_61_65_switch_driver;