aboutsummaryrefslogtreecommitdiffstats
path: root/target
diff options
context:
space:
mode:
authorJan Hoffmann <jan@3e8.eu>2022-10-14 23:06:14 +0200
committerSander Vanheule <sander@svanheule.net>2022-10-23 22:33:08 +0200
commit4657a5301eb5512b335de696d6a719c280826d46 (patch)
treeafc194a10c62d34f5b19f60e3607ed2223699c24 /target
parentb295c7140bc39aa58993171fe1ef4345b3e9838d (diff)
downloadupstream-4657a5301eb5512b335de696d6a719c280826d46.tar.gz
upstream-4657a5301eb5512b335de696d6a719c280826d46.tar.bz2
upstream-4657a5301eb5512b335de696d6a719c280826d46.zip
realtek: avoid busy waiting for RTL839x PHY read/write
Switch to a polling implementation similar to the one for RTL838x, to allow other kernel tasks to run while waiting. Signed-off-by: Jan Hoffmann <jan@3e8.eu>
Diffstat (limited to 'target')
-rw-r--r--target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
index 199ba347da..29912257e8 100644
--- a/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
+++ b/target/linux/realtek/files-5.10/drivers/net/dsa/rtl83xx/rtl839x.c
@@ -630,9 +630,23 @@ int rtl8390_sds_power(int mac, int val)
return 0;
}
+static int rtl839x_smi_wait_op(int timeout)
+{
+ int ret = 0;
+ u32 val;
+
+ ret = readx_poll_timeout(sw_r32, RTL839X_PHYREG_ACCESS_CTRL,
+ val, !(val & 0x1), 20, timeout);
+ if (ret)
+ pr_err("%s: timeout\n", __func__);
+
+ return ret;
+}
+
int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
{
u32 v;
+ int err = 0;
if (port > 63 || page > 4095 || reg > 31)
return -ENOTSUPP;
@@ -652,13 +666,15 @@ int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
v |= 1;
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
- do {
- } while (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x1);
+ err = rtl839x_smi_wait_op(100000);
+ if (err)
+ goto errout;
*val = sw_r32(RTL839X_PHYREG_DATA_CTRL) & 0xffff;
+errout:
mutex_unlock(&smi_lock);
- return 0;
+ return err;
}
int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val)
@@ -689,12 +705,14 @@ int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val)
v |= BIT(3) | 1; /* Write operation and execute */
sw_w32(v, RTL839X_PHYREG_ACCESS_CTRL);
- do {
- } while (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x1);
+ err = rtl839x_smi_wait_op(100000);
+ if (err)
+ goto errout;
if (sw_r32(RTL839X_PHYREG_ACCESS_CTRL) & 0x2)
err = -EIO;
+errout:
mutex_unlock(&smi_lock);
return err;
}
@@ -722,15 +740,16 @@ int rtl839x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
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));
+ err = rtl839x_smi_wait_op(100000);
+ if (err)
+ goto errout;
+
// 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);
+errout:
mutex_unlock(&smi_lock);
-
return err;
}
@@ -760,11 +779,13 @@ int rtl839x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
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));
+ err = rtl839x_smi_wait_op(100000);
+ if (err)
+ goto errout;
pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err);
+
+errout:
mutex_unlock(&smi_lock);
return err;
}