realtek: Add support for clause45 PHYs
[openwrt/staging/zorun.git] / target / linux / realtek / files-5.4 / drivers / net / dsa / rtl83xx / rtl839x.c
index b9fdd2c9555c99fc2561ce61a8d0fce590fc2bd2..b2846deb1136bf05c8084e9bc988c6f891181814 100644 (file)
@@ -321,6 +321,7 @@ int rtl8390_sds_power(int mac, int val)
        return 0;
 }
 
+
 int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
 {
        u32 v;
@@ -358,10 +359,9 @@ int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val)
                return -ENOTSUPP;
 
        mutex_lock(&smi_lock);
-       /* Clear both port registers */
-       sw_w32(0, RTL839X_PHYREG_PORT_CTRL(0));
-       sw_w32(0, RTL839X_PHYREG_PORT_CTRL(0) + 4);
-       sw_w32_mask(0, BIT(port), RTL839X_PHYREG_PORT_CTRL(port));
+
+       // Set PHY to access
+       rtl839x_set_port_reg_le(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL);
 
        sw_w32_mask(0xffff0000, val << 16, RTL839X_PHYREG_DATA_CTRL);
 
@@ -383,6 +383,68 @@ int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val)
        return err;
 }
 
+/*
+ * Read an mmd register of the PHY
+ */
+int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
+{
+       int err = 0;
+       u32 v;
+
+       mutex_lock(&smi_lock);
+
+       // Set PHY to access
+       sw_w32_mask(0xffff << 16, port << 16, RTL839X_PHYREG_DATA_CTRL);
+
+       // Set MMD device number and register to write to
+       sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL);
+
+       v = BIT(2) | BIT(0); // MMD-access | EXEC
+       sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
+
+       do {
+               v = sw_r32(RTL839X_PHYREG_ACCESS_CTRL);
+       } while (v & BIT(0));
+       // There is no error-checking via BIT 1 of v, as it does not seem to be set correctly
+       *val = (sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff);
+       pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err);
+
+       mutex_unlock(&smi_lock);
+
+       return err;
+}
+
+/*
+ * Write to an mmd register of the PHY
+ */
+int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
+{
+       int err = 0;
+       u32 v;
+
+       mutex_lock(&smi_lock);
+
+       // Set PHY to access
+       rtl839x_set_port_reg_le(BIT_ULL(port), RTL839X_PHYREG_PORT_CTRL);
+
+       // Set data to write
+       sw_w32_mask(0xffff << 16, val << 16, RTL839X_PHYREG_DATA_CTRL);
+
+       // Set MMD device number and register to write to
+       sw_w32(devnum << 16 | (regnum & 0xffff), RTL839X_PHYREG_MMD_CTRL);
+
+       v = BIT(3) | BIT(2) | BIT(0); // WRITE | MMD-access | EXEC
+       sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
+
+       do {
+               v = sw_r32(RTL839X_PHYREG_ACCESS_CTRL);
+       } while (v & BIT(0));
+
+       pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err);
+       mutex_unlock(&smi_lock);
+       return err;
+}
+
 void rtl8390_get_version(struct rtl838x_switch_priv *priv)
 {
        u32 info;