net: phy: broadcom: add helper to write/read RDB registers
authorMichael Walle <michael@walle.cc>
Mon, 20 Apr 2020 18:21:11 +0000 (20:21 +0200)
committerDavid S. Miller <davem@davemloft.net>
Wed, 22 Apr 2020 19:14:18 +0000 (12:14 -0700)
RDB (Register Data Base) registers are used on newer Broadcom PHYs. Add
helper to read, write and modify these registers.

Signed-off-by: Michael Walle <michael@walle.cc>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/bcm-phy-lib.c
drivers/net/phy/bcm-phy-lib.h
include/linux/brcmphy.h

index e77b274..d5f9a27 100644 (file)
@@ -155,6 +155,86 @@ int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
 }
 EXPORT_SYMBOL_GPL(bcm_phy_write_shadow);
 
+int __bcm_phy_read_rdb(struct phy_device *phydev, u16 rdb)
+{
+       int val;
+
+       val = __phy_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
+       if (val < 0)
+               return val;
+
+       return __phy_read(phydev, MII_BCM54XX_RDB_DATA);
+}
+EXPORT_SYMBOL_GPL(__bcm_phy_read_rdb);
+
+int bcm_phy_read_rdb(struct phy_device *phydev, u16 rdb)
+{
+       int ret;
+
+       phy_lock_mdio_bus(phydev);
+       ret = __bcm_phy_read_rdb(phydev, rdb);
+       phy_unlock_mdio_bus(phydev);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_read_rdb);
+
+int __bcm_phy_write_rdb(struct phy_device *phydev, u16 rdb, u16 val)
+{
+       int ret;
+
+       ret = __phy_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
+       if (ret < 0)
+               return ret;
+
+       return __phy_write(phydev, MII_BCM54XX_RDB_DATA, val);
+}
+EXPORT_SYMBOL_GPL(__bcm_phy_write_rdb);
+
+int bcm_phy_write_rdb(struct phy_device *phydev, u16 rdb, u16 val)
+{
+       int ret;
+
+       phy_lock_mdio_bus(phydev);
+       ret = __bcm_phy_write_rdb(phydev, rdb, val);
+       phy_unlock_mdio_bus(phydev);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_write_rdb);
+
+int __bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask, u16 set)
+{
+       int new, ret;
+
+       ret = __phy_write(phydev, MII_BCM54XX_RDB_ADDR, rdb);
+       if (ret < 0)
+               return ret;
+
+       ret = __phy_read(phydev, MII_BCM54XX_RDB_DATA);
+       if (ret < 0)
+               return ret;
+
+       new = (ret & ~mask) | set;
+       if (new == ret)
+               return 0;
+
+       return __phy_write(phydev, MII_BCM54XX_RDB_DATA, new);
+}
+EXPORT_SYMBOL_GPL(__bcm_phy_modify_rdb);
+
+int bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask, u16 set)
+{
+       int ret;
+
+       phy_lock_mdio_bus(phydev);
+       ret = __bcm_phy_modify_rdb(phydev, rdb, mask, set);
+       phy_unlock_mdio_bus(phydev);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(bcm_phy_modify_rdb);
+
 int bcm_phy_enable_apd(struct phy_device *phydev, bool dll_pwr_down)
 {
        int val;
index 129df81..4d3de91 100644 (file)
@@ -48,6 +48,15 @@ int bcm_phy_write_shadow(struct phy_device *phydev, u16 shadow,
                         u16 val);
 int bcm_phy_read_shadow(struct phy_device *phydev, u16 shadow);
 
+int __bcm_phy_write_rdb(struct phy_device *phydev, u16 rdb, u16 val);
+int bcm_phy_write_rdb(struct phy_device *phydev, u16 rdb, u16 val);
+int __bcm_phy_read_rdb(struct phy_device *phydev, u16 rdb);
+int bcm_phy_read_rdb(struct phy_device *phydev, u16 rdb);
+int __bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask,
+                        u16 set);
+int bcm_phy_modify_rdb(struct phy_device *phydev, u16 rdb, u16 mask,
+                      u16 set);
+
 int bcm_phy_ack_intr(struct phy_device *phydev);
 int bcm_phy_config_intr(struct phy_device *phydev);
 
index 7e1d857..897b693 100644 (file)
 #define MII_BCM54XX_SHD_VAL(x) ((x & 0x1f) << 10)
 #define MII_BCM54XX_SHD_DATA(x)        ((x & 0x3ff) << 0)
 
+#define MII_BCM54XX_RDB_ADDR   0x1e
+#define MII_BCM54XX_RDB_DATA   0x1f
+
 /*
  * AUXILIARY CONTROL SHADOW ACCESS REGISTERS.  (PHY REG 0x18)
  */