aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c')
-rw-r--r--target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c70
1 files changed, 66 insertions, 4 deletions
diff --git a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c
index b9fdd2c955..b2846deb11 100644
--- a/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c
+++ b/target/linux/realtek/files-5.4/drivers/net/dsa/rtl83xx/rtl839x.c
@@ -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;