[openwrt/openwrt] realtek: mdio: rtl931x: move functions over to bus

LEDE Commits lede-commits at lists.infradead.org
Tue Aug 19 11:06:13 PDT 2025


robimarko pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/070d8eb4d57038f3986027cd6d4610bd27ec2d59

commit 070d8eb4d57038f3986027cd6d4610bd27ec2d59
Author: Markus Stockhausen <markus.stockhausen at gmx.de>
AuthorDate: Mon Aug 11 04:34:00 2025 -0400

    realtek: mdio: rtl931x: move functions over to bus
    
    This commit repeats the mdio function relocation from the other targets.
    In short that means:
    
    - phy read/write functions are moved away from the phy driver
    - SerDes read/write functions are moved away from the dsa driver
    - All gets consolidated into the mdio driver (inside the ethernet driver)
    
    This is mostly a copy/paste to keep the changes small. The SerDes phy mapping
    and the simplification of the central bus functions will come later.
    
    Signed-off-by: Markus Stockhausen <markus.stockhausen at gmx.de>
    Link: https://github.com/openwrt/openwrt/pull/19743
    Signed-off-by: Robert Marko <robimarko at gmail.com>
---
 .../mips/include/asm/mach-rtl838x/mach-rtl83xx.h   |   4 -
 .../files-6.12/drivers/net/dsa/rtl83xx/common.c    |   2 -
 .../files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c   |   2 -
 .../files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c   |   1 -
 .../files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h   |   5 -
 .../files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c   |   1 -
 .../files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c   | 144 ------------
 .../files-6.12/drivers/net/ethernet/rtl838x_eth.c  | 249 ++++++++++++++++++++-
 .../files-6.12/drivers/net/ethernet/rtl838x_eth.h  |   3 +
 .../files-6.12/drivers/net/phy/rtl83xx-phy.c       | 118 +++-------
 .../files-6.12/drivers/net/phy/rtl83xx-phy.h       |   4 -
 11 files changed, 277 insertions(+), 256 deletions(-)

diff --git a/target/linux/realtek/files-6.12/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h b/target/linux/realtek/files-6.12/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h
index 808cbd245c..72abbadc1e 100644
--- a/target/linux/realtek/files-6.12/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h
+++ b/target/linux/realtek/files-6.12/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h
@@ -414,8 +414,4 @@ struct rtl83xx_soc_info {
 	int cpu_port;
 };
 
-/* rtl83xx-related functions used across subsystems */
-int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
-int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val);
-
 #endif   /* _MACH_RTL838X_H_ */
diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c
index 9ccf1e1840..eef52e4ac2 100644
--- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c
+++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/common.c
@@ -29,8 +29,6 @@ extern const struct dsa_switch_ops rtl930x_switch_ops;
 extern const struct phylink_pcs_ops rtl83xx_pcs_ops;
 extern const struct phylink_pcs_ops rtl93xx_pcs_ops;
 
-DEFINE_MUTEX(smi_lock);
-
 int rtl83xx_port_get_stp_state(struct rtl838x_switch_priv *priv, int port)
 {
 	u32 msti = 0;
diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c
index e0c8d73fa4..2fed65adab 100644
--- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c
+++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl838x.c
@@ -23,8 +23,6 @@
 #define RTL838X_VLAN_PORT_TAG_STS_CTRL_OTAG_STS_MASK		GENMASK(3,2)
 #define RTL838X_VLAN_PORT_TAG_STS_CTRL_ITAG_STS_MASK		GENMASK(1,0)
 
-extern struct mutex smi_lock;
-
 /* see_dal_maple_acl_log2PhyTmplteField and src/app/diag_v2/src/diag_acl.c */
 /* Definition of the RTL838X-specific template field IDs as used in the PIE */
 enum template_field_id {
diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c
index 87ba9e0fbc..0d433c0b56 100644
--- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c
+++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl839x.c
@@ -20,7 +20,6 @@
 #define RTL839X_VLAN_PORT_TAG_STS_CTRL_IGR_P_OTAG_KEEP_MASK	GENMASK(1,1)
 #define RTL839X_VLAN_PORT_TAG_STS_CTRL_IGR_P_ITAG_KEEP_MASK	GENMASK(0,0)
 
-extern struct mutex smi_lock;
 extern struct rtl83xx_soc_info soc_info;
 
 /* Definition of the RTL839X-specific template field IDs as used in the PIE */
diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h
index 7dff91e3b7..ef5230d92e 100644
--- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h
+++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h
@@ -192,11 +192,6 @@ void rtl931x_print_matrix(void);
 int rtl83xx_lag_add(struct dsa_switch *ds, int group, int port, struct netdev_lag_upper_info *info);
 int rtl83xx_lag_del(struct dsa_switch *ds, int group, int port);
 
-/* phy functions that will need to be moved to the future mdio driver */
-
-int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
-int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
-
 /*
  * TODO: The following functions are currently not in use. So compiler will complain if
  * they are static and not made available externally. To preserve them for future use
diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
index d7f611f943..f6a5affb43 100644
--- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
+++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
@@ -33,7 +33,6 @@
 /* get shift for given led in any set */
 #define RTL930X_LED_SET_LEDX_SHIFT(x) (16 * (x % 2))
 
-extern struct mutex smi_lock;
 extern struct rtl83xx_soc_info soc_info;
 
 /* Definition of the RTL930X-specific template field IDs as used in the PIE */
diff --git a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c
index 36103b43dd..226b7ce5d3 100644
--- a/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c
+++ b/target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl931x.c
@@ -25,7 +25,6 @@
 #define RTL931X_VLAN_PORT_TAG_ITPID_IDX_MASK			GENMASK(2,1)
 #define RTL931X_VLAN_PORT_TAG_ITPID_KEEP_MASK			GENMASK(0,0)
 
-extern struct mutex smi_lock;
 extern struct rtl83xx_soc_info soc_info;
 
 /* Definition of the RTL931X-specific template field IDs as used in the PIE */
@@ -317,149 +316,6 @@ irqreturn_t rtl931x_switch_irq(int irq, void *dev_id)
 	return IRQ_HANDLED;
 }
 
-int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val)
-{
-	u32 v;
-	int err = 0;
-
-	val &= 0xffff;
-	if (port > 63 || page > 4095 || reg > 31)
-		return -ENOTSUPP;
-
-	mutex_lock(&smi_lock);
-	pr_debug("%s: writing to phy %d %d %d %d\n", __func__, port, page, reg, val);
-	/* Clear both port registers */
-	sw_w32(0, RTL931X_SMI_INDRT_ACCESS_CTRL_2);
-	sw_w32(0, RTL931X_SMI_INDRT_ACCESS_CTRL_2 + 4);
-	sw_w32_mask(0, BIT(port % 32), RTL931X_SMI_INDRT_ACCESS_CTRL_2 + (port / 32) * 4);
-
-	sw_w32_mask(0xffff, val, RTL931X_SMI_INDRT_ACCESS_CTRL_3);
-
-	v = reg << 6 | page << 11 ;
-	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-
-	sw_w32(0x1ff, RTL931X_SMI_INDRT_ACCESS_CTRL_1);
-
-	v |= BIT(4) | 1; /* Write operation and execute */
-	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-
-	do {
-	} while (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x1);
-
-	if (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x2)
-		err = -EIO;
-
-	mutex_unlock(&smi_lock);
-
-	return err;
-}
-
-int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
-{
-	u32 v;
-
-	if (port > 63 || page > 4095 || reg > 31)
-		return -ENOTSUPP;
-
-	mutex_lock(&smi_lock);
-
-	sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL);
-
-	v = reg << 6 | page << 11 | 1;
-	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-
-	do {
-	} while (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x1);
-
-	v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-	*val = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_3);
-	*val = (*val & 0xffff0000) >> 16;
-
-	pr_debug("%s: port %d, page: %d, reg: %x, val: %x, v: %08x\n",
-		__func__, port, page, reg, *val, v);
-
-	mutex_unlock(&smi_lock);
-
-	return 0;
-}
-
-/* Read an mmd register of the PHY */
-int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
-{
-	int err = 0;
-	u32 v;
-	/* Select PHY register type
-	 * If select 1G/10G MMD register type, registers EXT_PAGE, MAIN_PAGE and REG settings are don’t care.
-	 * 0x0  Normal register (Clause 22)
-	 * 0x1: 1G MMD register (MMD via Clause 22 registers 13 and 14)
-	 * 0x2: 10G MMD register (MMD via Clause 45)
-	 */
-	int type = 2;
-
-	mutex_lock(&smi_lock);
-
-	/* Set PHY to access via port-number */
-	sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL);
-
-	/* Set MMD device number and register to write to */
-	sw_w32(devnum << 16 | regnum, RTL931X_SMI_INDRT_ACCESS_MMD_CTRL);
-
-	v = type << 2 | BIT(0); /* MMD-access-type | EXEC */
-	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-
-	do {
-		v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-	} while (v & BIT(0));
-
-	/* Check for error condition */
-	if (v & BIT(1))
-		err = -EIO;
-
-	*val = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_3) >> 16;
-
-	pr_debug("%s: port %d, dev: %x, regnum: %x, val: %x (err %d)\n", __func__,
-		 port, devnum, regnum, *val, err);
-
-	mutex_unlock(&smi_lock);
-
-	return err;
-}
-
-/* Write to an mmd register of the PHY */
-int rtl931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
-{
-	int err = 0;
-	u32 v;
-	int type = 2;
-	u64 pm;
-
-	mutex_lock(&smi_lock);
-
-	/* Set PHY to access via port-mask */
-	pm = (u64)1 << port;
-	sw_w32((u32)pm, RTL931X_SMI_INDRT_ACCESS_CTRL_2);
-	sw_w32((u32)(pm >> 32), RTL931X_SMI_INDRT_ACCESS_CTRL_2 + 4);
-
-	/* Set data to write */
-	sw_w32_mask(0xffff, val, RTL931X_SMI_INDRT_ACCESS_CTRL_3);
-
-	/* Set MMD device number and register to write to */
-	sw_w32(devnum << 16 | regnum, RTL931X_SMI_INDRT_ACCESS_MMD_CTRL);
-
-	v = BIT(4) | type << 2 | BIT(0); /* WRITE | MMD-access-type | EXEC */
-	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-
-	do {
-		v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
-	} while (v & BIT(0));
-
-	pr_debug("%s: port %d, dev: %x, regnum: %x, val: %x (err %d)\n", __func__,
-		 port, devnum, regnum, val, err);
-	mutex_unlock(&smi_lock);
-
-	return err;
-}
-
 void rtl931x_print_matrix(void)
 {
 	struct table_reg *r = rtl_table_get(RTL9310_TBL_2, 1);
diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
index cc3166340b..ddfdabacb6 100644
--- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
+++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
@@ -69,10 +69,13 @@ extern int rtl931x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v);
 #define RTMDIO_ABS		BIT(2)
 #define RTMDIO_PKG		BIT(3)
 
-#define RTMDIO_838X_BASE		(0xe780)
-#define RTMDIO_839X_BASE		(0xa000)
-#define RTMDIO_930X_SDS_INDACS_CMD	(0x03B0)
-#define RTMDIO_930X_SDS_INDACS_DATA	(0x03B4)
+/* MDIO SerDes registers */
+#define RTMDIO_838X_BASE			(0xe780)
+#define RTMDIO_839X_BASE			(0xa000)
+#define RTMDIO_930X_SDS_INDACS_CMD		(0x03B0)
+#define RTMDIO_930X_SDS_INDACS_DATA		(0x03B4)
+#define RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL	(0x5638)
+#define RTMDIO_931X_SERDES_INDRT_DATA_CTRL	(0x563C)
 
 struct p_hdr {
 	uint8_t		*buf;
@@ -2394,6 +2397,228 @@ static int rtmdio_930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
 	return err;
 }
 
+/*
+ * The RTL931x family has 14 "frontend" SerDes that are cascaded. All operations (e.g. reset) work
+ * on this frontend view while their registers are distributed over a total of least 26 background
+ * SerDes. Two types of SerDes exist:
+ *
+ * An "even" SerDes with numbers 0, 1, 2, 4, 6, 8, 10, 12 works on one background SerDes.
+ *
+ * The "odd" SerDes with numbers 3, 5, 7, 9, 11 & 13 SerDes consist of a total of 3 background
+ * SerDes (one analog and two XSGMII) each with its own page/register set. So it gives this
+ * mapping:
+
+ * Frontend SerDes  |  0  1  2  3  4  5  6  7  8  9 10 11 12 13
+ * -----------------+------------------------------------------
+ * Backend SerDes 1 |  0  1  2  3  6  7 10 11 14 15 18 19 22 23
+ * Backend SerDes 2 |  0  1  2  4  6  8 10 12 14 16 18 20 22 24
+ * Backend SerDes 3 |  0  1  2  5  6  9 10 13 14 17 18 21 22 25
+ *
+ * Align this for readability by simulating a total of 576 pages and mix them as follows.
+ *
+ * frontend page		"even" frontend SerDes		"odd" frontend SerDes
+ * page 0x000-0x03f (analog):	page 0x000-0x03f back SDS	page 0x000-0x03f back SDS
+ * page 0x100-0x13f (XSGMII1):	page 0x000-0x03f back SDS	page 0x000-0x03f back SDS+1
+ * page 0x200-0x23f (XSGMII2):	page 0x000-0x03f back SDS	page 0x000-0x03f back SDS+2
+ */ 
+
+int rtmdio_931x_read_sds_phy(int sds, int page, int regnum)
+{
+	u32 cmd = sds << 2 | page << 7 | regnum << 13 | 1;
+	int i, ret = -EIO;
+
+	pr_debug("%s: phy_addr(SDS-ID) %d, phy_reg: %d\n", __func__, sds, regnum);
+
+	mutex_lock(&rtmdio_lock_sds);
+	sw_w32(cmd, RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL);
+
+	for (i = 0; i < 100; i++) {
+		if (!(sw_r32(RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL) & 0x1))
+			break;
+		mdelay(1);
+	}
+
+	if (i < 100)
+		ret = sw_r32(RTMDIO_931X_SERDES_INDRT_DATA_CTRL) & 0xffff;
+
+	mutex_unlock(&rtmdio_lock_sds);
+
+	pr_debug("%s: returning %08x\n", __func__, ret);
+
+	return ret;
+}
+
+int rtmdio_931x_write_sds_phy(int sds, int page, int regnum, u16 val)
+{
+	u32 cmd = sds << 2 | page << 7 | regnum << 13;;
+	int i, ret = -EIO;
+
+	mutex_lock(&rtmdio_lock_sds);
+	sw_w32(cmd, RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL);
+	sw_w32(val, RTMDIO_931X_SERDES_INDRT_DATA_CTRL);
+
+	cmd = sw_r32(RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL) | 0x3;
+	sw_w32(cmd, RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL);
+
+	for (i = 0; i < 100; i++) {
+		if (!(sw_r32(RTMDIO_931X_SERDES_INDRT_ACCESS_CTRL) & 0x1))
+			break;
+		mdelay(1);
+	}
+
+	mutex_unlock(&rtmdio_lock_sds);
+
+	if (i < 100)
+		ret = 0;
+
+	return ret;
+}
+
+/* RTL931x specific MDIO functions */
+
+static int rtmdio_931x_write_phy(u32 port, u32 page, u32 reg, u32 val)
+{
+	u32 v;
+	int err = 0;
+
+	val &= 0xffff;
+	if (port > 63 || page > 4095 || reg > 31)
+		return -ENOTSUPP;
+
+	mutex_lock(&rtmdio_lock);
+	pr_debug("%s: writing to phy %d %d %d %d\n", __func__, port, page, reg, val);
+	/* Clear both port registers */
+	sw_w32(0, RTL931X_SMI_INDRT_ACCESS_CTRL_2);
+	sw_w32(0, RTL931X_SMI_INDRT_ACCESS_CTRL_2 + 4);
+	sw_w32_mask(0, BIT(port % 32), RTL931X_SMI_INDRT_ACCESS_CTRL_2 + (port / 32) * 4);
+
+	sw_w32_mask(0xffff, val, RTL931X_SMI_INDRT_ACCESS_CTRL_3);
+
+	v = reg << 6 | page << 11 ;
+	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+
+	sw_w32(0x1ff, RTL931X_SMI_INDRT_ACCESS_CTRL_1);
+
+	v |= BIT(4) | 1; /* Write operation and execute */
+	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+
+	do {
+	} while (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x1);
+
+	if (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x2)
+		err = -EIO;
+
+	mutex_unlock(&rtmdio_lock);
+
+	return err;
+}
+
+static int rtmdio_931x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
+{
+	u32 v;
+
+	if (port > 63 || page > 4095 || reg > 31)
+		return -ENOTSUPP;
+
+	mutex_lock(&rtmdio_lock);
+
+	sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL);
+
+	v = reg << 6 | page << 11 | 1;
+	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+
+	do {
+	} while (sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0) & 0x1);
+
+	v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+	*val = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_3);
+	*val = (*val & 0xffff0000) >> 16;
+
+	pr_debug("%s: port %d, page: %d, reg: %x, val: %x, v: %08x\n",
+		__func__, port, page, reg, *val, v);
+
+	mutex_unlock(&rtmdio_lock);
+
+	return 0;
+}
+
+/* Read an mmd register of the PHY */
+static int rtmdio_931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
+{
+	int err = 0;
+	u32 v;
+	/* Select PHY register type
+	 * If select 1G/10G MMD register type, registers EXT_PAGE, MAIN_PAGE and REG settings are don’t care.
+	 * 0x0  Normal register (Clause 22)
+	 * 0x1: 1G MMD register (MMD via Clause 22 registers 13 and 14)
+	 * 0x2: 10G MMD register (MMD via Clause 45)
+	 */
+	int type = 2;
+
+	mutex_lock(&rtmdio_lock);
+
+	/* Set PHY to access via port-number */
+	sw_w32(port << 5, RTL931X_SMI_INDRT_ACCESS_BC_PHYID_CTRL);
+
+	/* Set MMD device number and register to write to */
+	sw_w32(devnum << 16 | regnum, RTL931X_SMI_INDRT_ACCESS_MMD_CTRL);
+
+	v = type << 2 | BIT(0); /* MMD-access-type | EXEC */
+	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+
+	do {
+		v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+	} while (v & BIT(0));
+
+	/* Check for error condition */
+	if (v & BIT(1))
+		err = -EIO;
+
+	*val = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_3) >> 16;
+
+	pr_debug("%s: port %d, dev: %x, regnum: %x, val: %x (err %d)\n", __func__,
+		 port, devnum, regnum, *val, err);
+
+	mutex_unlock(&rtmdio_lock);
+
+	return err;
+}
+
+/* Write to an mmd register of the PHY */
+static int rtmdio_931x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
+{
+	int err = 0;
+	u32 v;
+	int type = 2;
+	u64 pm;
+
+	mutex_lock(&rtmdio_lock);
+
+	/* Set PHY to access via port-mask */
+	pm = (u64)1 << port;
+	sw_w32((u32)pm, RTL931X_SMI_INDRT_ACCESS_CTRL_2);
+	sw_w32((u32)(pm >> 32), RTL931X_SMI_INDRT_ACCESS_CTRL_2 + 4);
+
+	/* Set data to write */
+	sw_w32_mask(0xffff, val, RTL931X_SMI_INDRT_ACCESS_CTRL_3);
+
+	/* Set MMD device number and register to write to */
+	sw_w32(devnum << 16 | regnum, RTL931X_SMI_INDRT_ACCESS_MMD_CTRL);
+
+	v = BIT(4) | type << 2 | BIT(0); /* WRITE | MMD-access-type | EXEC */
+	sw_w32(v, RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+
+	do {
+		v = sw_r32(RTL931X_SMI_INDRT_ACCESS_CTRL_0);
+	} while (v & BIT(0));
+
+	pr_debug("%s: port %d, dev: %x, regnum: %x, val: %x (err %d)\n", __func__,
+		 port, devnum, regnum, val, err);
+	mutex_unlock(&rtmdio_lock);
+
+	return err;
+}
+
 /* These are the core functions of our new Realtek SoC MDIO bus. */
 
 static int rtmdio_read_c45(struct mii_bus *bus, int addr, int devnum, int regnum)
@@ -2506,8 +2731,8 @@ static int rtmdio_93xx_read(struct mii_bus *bus, int addr, int regnum)
 
 	priv->raw[addr] = (priv->page[addr] == priv->rawpage);
 	if (priv->phy_is_internal[addr]) {
-		return rtl931x_read_sds_phy(priv->sds_id[addr],
-					    priv->page[addr], regnum);
+		return rtmdio_931x_read_sds_phy(priv->sds_id[addr],
+						priv->page[addr], regnum);
 	}
 
 	err = (*priv->read_phy)(addr, priv->page[addr], regnum, &val);
@@ -2594,8 +2819,8 @@ static int rtmdio_93xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 	if (!priv->raw[addr] && (regnum != RTMDIO_PAGE_SELECT || page == priv->rawpage)) {
 		priv->raw[addr] = (page == priv->rawpage);
 		if (priv->phy_is_internal[addr]) {
-			return rtl931x_write_sds_phy(priv->sds_id[addr],
-						     page, regnum, val);
+			return rtmdio_931x_write_sds_phy(priv->sds_id[addr],
+							 page, regnum, val);
 		}
 
 		err = (*priv->write_phy)(addr, page, regnum, val);
@@ -2922,10 +3147,10 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
 		priv->mii_bus->read = rtmdio_93xx_read;
 		priv->mii_bus->write = rtmdio_93xx_write;
 		priv->mii_bus->reset = rtmdio_931x_reset;
-		bus_priv->read_mmd_phy = rtl931x_read_mmd_phy;
-		bus_priv->write_mmd_phy = rtl931x_write_mmd_phy;
-		bus_priv->read_phy = rtl931x_read_phy;
-		bus_priv->write_phy = rtl931x_write_phy;
+		bus_priv->read_mmd_phy = rtmdio_931x_read_mmd_phy;
+		bus_priv->write_mmd_phy = rtmdio_931x_write_mmd_phy;
+		bus_priv->read_phy = rtmdio_931x_read_phy;
+		bus_priv->write_phy = rtmdio_931x_write_phy;
 		bus_priv->cpu_port = RTL931X_CPU_PORT;
 		bus_priv->rawpage = 0x1fff;
 		break;
diff --git a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h
index edeea8f6e2..a24cb891d2 100644
--- a/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h
+++ b/target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.h
@@ -466,4 +466,7 @@ int rtmdio_838x_write_phy(u32 port, u32 page, u32 reg, u32 val);
 int rtmdio_930x_read_sds_phy(int sds, int page, int regnum);
 int rtmdio_930x_write_sds_phy(int sds, int page, int regnum, u16 val);
 
+int rtmdio_931x_read_sds_phy(int sds, int page, int regnum);
+int rtmdio_931x_write_sds_phy(int sds, int page, int regnum, u16 val);
+
 #endif /* _RTL838X_ETH_H */
diff --git a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
index 98066bf233..9b51a97abf 100644
--- a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
+++ b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.c
@@ -19,7 +19,7 @@
 #include "rtl83xx-phy.h"
 
 extern struct rtl83xx_soc_info soc_info;
-extern struct mutex smi_lock;
+
 extern int phy_package_port_write_paged(struct phy_device *phydev, int port, int page, u32 regnum, u16 val);
 extern int phy_package_write_paged(struct phy_device *phydev, int page, u32 regnum, u16 val);
 extern int phy_package_port_read_paged(struct phy_device *phydev, int port, int page, u32 regnum);
@@ -28,6 +28,9 @@ extern int phy_package_read_paged(struct phy_device *phydev, int page, u32 regnu
 extern int rtmdio_930x_read_sds_phy(int sds, int page, int regnum);
 extern int rtmdio_930x_write_sds_phy(int sds, int page, int regnum, u16 val);
 
+extern int rtmdio_931x_read_sds_phy(int sds, int page, int regnum);
+extern int rtmdio_931x_write_sds_phy(int sds, int page, int regnum, u16 val);
+
 #define PHY_PAGE_2	2
 #define PHY_PAGE_4	4
 
@@ -295,53 +298,6 @@ static u32 rtl9300_sds_mode_get(int sds_num)
 	return v & RTL930X_SDS_MASK;
 }
 
-int rtl931x_read_sds_phy(int phy_addr, int page, int phy_reg)
-{
-	int i;
-	u32 cmd = phy_addr << 2 | page << 7 | phy_reg << 13 | 1;
-
-	pr_debug("%s: phy_addr(SDS-ID) %d, phy_reg: %d\n", __func__, phy_addr, phy_reg);
-	sw_w32(cmd, RTL931X_SERDES_INDRT_ACCESS_CTRL);
-
-	for (i = 0; i < 100; i++) {
-		if (!(sw_r32(RTL931X_SERDES_INDRT_ACCESS_CTRL) & 0x1))
-			break;
-		mdelay(1);
-	}
-
-	if (i >= 100)
-		return -EIO;
-
-	pr_debug("%s: returning %04x\n", __func__, sw_r32(RTL931X_SERDES_INDRT_DATA_CTRL) & 0xffff);
-
-	return sw_r32(RTL931X_SERDES_INDRT_DATA_CTRL) & 0xffff;
-}
-
-int rtl931x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v)
-{
-	int i;
-	u32 cmd;
-
-	cmd = phy_addr << 2 | page << 7 | phy_reg << 13;
-	sw_w32(cmd, RTL931X_SERDES_INDRT_ACCESS_CTRL);
-
-	sw_w32(v, RTL931X_SERDES_INDRT_DATA_CTRL);
-
-	cmd =  sw_r32(RTL931X_SERDES_INDRT_ACCESS_CTRL) | 0x3;
-	sw_w32(cmd, RTL931X_SERDES_INDRT_ACCESS_CTRL);
-
-	for (i = 0; i < 100; i++) {
-		if (!(sw_r32(RTL931X_SERDES_INDRT_ACCESS_CTRL) & 0x1))
-			break;
-		mdelay(1);
-	}
-
-	if (i >= 100)
-		return -EIO;
-
-	return 0;
-}
-
 /* Read the link and speed status of the 2 internal SGMII/1000Base-X
  * ports of the RTL838x SoCs
  */
@@ -2949,18 +2905,18 @@ static void rtl9310_sds_field_w(int sds, u32 page, u32 reg, int end_bit, int sta
 	if (l < 32) {
 		u32 mask = BIT(l) - 1;
 
-		data = rtl931x_read_sds_phy(sds, page, reg);
+		data = rtmdio_931x_read_sds_phy(sds, page, reg);
 		data &= ~(mask << start_bit);
 		data |= (v & mask) << start_bit;
 	}
 
-	rtl931x_write_sds_phy(sds, page, reg, data);
+	rtmdio_931x_write_sds_phy(sds, page, reg, data);
 }
 
 static u32 rtl9310_sds_field_r(int sds, u32 page, u32 reg, int end_bit, int start_bit)
 {
 	int l = end_bit - start_bit + 1;
-	u32 v = rtl931x_read_sds_phy(sds, page, reg);
+	u32 v = rtmdio_931x_read_sds_phy(sds, page, reg);
 
 	if (l >= 32)
 		return v;
@@ -3187,9 +3143,9 @@ static void rtl931x_cmu_type_set(u32 asds, phy_interface_t mode, int chiptype)
 	        __func__, cmu_type, cmu_page, frc_cmu_spd, lane, asds);
 
 	if (cmu_type == 1) {
-		pr_info("%s A CMU page 0x28 0x7 %08x\n", __func__, rtl931x_read_sds_phy(asds, 0x28, 0x7));
+		pr_info("%s A CMU page 0x28 0x7 %08x\n", __func__, rtmdio_931x_read_sds_phy(asds, 0x28, 0x7));
 		rtl9310_sds_field_w(asds, cmu_page, 0x7, 15, 15, 0);
-		pr_info("%s B CMU page 0x28 0x7 %08x\n", __func__, rtl931x_read_sds_phy(asds, 0x28, 0x7));
+		pr_info("%s B CMU page 0x28 0x7 %08x\n", __func__, rtmdio_931x_read_sds_phy(asds, 0x28, 0x7));
 		if (chiptype) {
 			rtl9310_sds_field_w(asds, cmu_page, 0xd, 14, 14, 0);
 		}
@@ -3201,7 +3157,7 @@ static void rtl931x_cmu_type_set(u32 asds, phy_interface_t mode, int chiptype)
 		rtl9310_sds_field_w(evenSds, 0x20, 0x12, 15, 13, frc_cmu_spd);
 	}
 
-	pr_info("%s CMU page 0x28 0x7 %08x\n", __func__, rtl931x_read_sds_phy(asds, 0x28, 0x7));
+	pr_info("%s CMU page 0x28 0x7 %08x\n", __func__, rtmdio_931x_read_sds_phy(asds, 0x28, 0x7));
 	return;
 }
 
@@ -3212,15 +3168,15 @@ static void rtl931x_sds_rx_rst(u32 sds)
 	if (sds < 2)
 		return;
 
-	rtl931x_write_sds_phy(asds, 0x2e, 0x12, 0x2740);
-	rtl931x_write_sds_phy(asds, 0x2f, 0x0, 0x0);
-	rtl931x_write_sds_phy(asds, 0x2f, 0x2, 0x2010);
-	rtl931x_write_sds_phy(asds, 0x20, 0x0, 0xc10);
+	rtmdio_931x_write_sds_phy(asds, 0x2e, 0x12, 0x2740);
+	rtmdio_931x_write_sds_phy(asds, 0x2f, 0x0, 0x0);
+	rtmdio_931x_write_sds_phy(asds, 0x2f, 0x2, 0x2010);
+	rtmdio_931x_write_sds_phy(asds, 0x20, 0x0, 0xc10);
 
-	rtl931x_write_sds_phy(asds, 0x2e, 0x12, 0x27c0);
-	rtl931x_write_sds_phy(asds, 0x2f, 0x0, 0xc000);
-	rtl931x_write_sds_phy(asds, 0x2f, 0x2, 0x6010);
-	rtl931x_write_sds_phy(asds, 0x20, 0x0, 0xc30);
+	rtmdio_931x_write_sds_phy(asds, 0x2e, 0x12, 0x27c0);
+	rtmdio_931x_write_sds_phy(asds, 0x2f, 0x0, 0xc000);
+	rtmdio_931x_write_sds_phy(asds, 0x2f, 0x2, 0x6010);
+	rtmdio_931x_write_sds_phy(asds, 0x20, 0x0, 0xc30);
 
 	mdelay(50);
 }
@@ -3314,17 +3270,17 @@ void rtl931x_sds_init(u32 sds, phy_interface_t mode)
 	val = rtl9310_sds_field_r(asds, 0x1F, 0x9, 11, 6);
 
 	pr_info("%s: fibermode %08X stored mode 0x%x analog SDS %d", __func__,
-			rtl931x_read_sds_phy(asds, 0x1f, 0x9), val, asds);
+			rtmdio_931x_read_sds_phy(asds, 0x1f, 0x9), val, asds);
 	pr_info("%s: SGMII mode %08X in 0x24 0x9 analog SDS %d", __func__,
-			rtl931x_read_sds_phy(asds, 0x24, 0x9), asds);
+			rtmdio_931x_read_sds_phy(asds, 0x24, 0x9), asds);
 	pr_info("%s: CMU mode %08X stored even SDS %d", __func__,
-			rtl931x_read_sds_phy(asds & ~1, 0x20, 0x12), asds & ~1);
+			rtmdio_931x_read_sds_phy(asds & ~1, 0x20, 0x12), asds & ~1);
 	pr_info("%s: serdes_mode_ctrl %08X", __func__,  RTL931X_SERDES_MODE_CTRL + 4 * (sds >> 2));
-	pr_info("%s CMU page 0x24 0x7 %08x\n", __func__, rtl931x_read_sds_phy(asds, 0x24, 0x7));
-	pr_info("%s CMU page 0x26 0x7 %08x\n", __func__, rtl931x_read_sds_phy(asds, 0x26, 0x7));
-	pr_info("%s CMU page 0x28 0x7 %08x\n", __func__, rtl931x_read_sds_phy(asds, 0x28, 0x7));
-	pr_info("%s XSG page 0x0 0xe %08x\n", __func__, rtl931x_read_sds_phy(dSds, 0x0, 0xe));
-	pr_info("%s XSG2 page 0x0 0xe %08x\n", __func__, rtl931x_read_sds_phy(dSds + 1, 0x0, 0xe));
+	pr_info("%s CMU page 0x24 0x7 %08x\n", __func__, rtmdio_931x_read_sds_phy(asds, 0x24, 0x7));
+	pr_info("%s CMU page 0x26 0x7 %08x\n", __func__, rtmdio_931x_read_sds_phy(asds, 0x26, 0x7));
+	pr_info("%s CMU page 0x28 0x7 %08x\n", __func__, rtmdio_931x_read_sds_phy(asds, 0x28, 0x7));
+	pr_info("%s XSG page 0x0 0xe %08x\n", __func__, rtmdio_931x_read_sds_phy(dSds, 0x0, 0xe));
+	pr_info("%s XSG2 page 0x0 0xe %08x\n", __func__, rtmdio_931x_read_sds_phy(dSds + 1, 0x0, 0xe));
 
 	model_info = sw_r32(RTL93XX_MODEL_NAME_INFO);
 	if ((model_info >> 4) & 0x1) {
@@ -3340,7 +3296,7 @@ void rtl931x_sds_init(u32 sds, phy_interface_t mode)
 		dSds = (sds - 1) * 2;
 
 	pr_info("%s: 2.5gbit %08X dsds %d", __func__,
-	        rtl931x_read_sds_phy(dSds, 0x1, 0x14), dSds);
+	        rtmdio_931x_read_sds_phy(dSds, 0x1, 0x14), dSds);
 
 	pr_info("%s: RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR 0x%08X\n", __func__, sw_r32(RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR));
 	ori = sw_r32(RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR);
@@ -3377,13 +3333,13 @@ void rtl931x_sds_init(u32 sds, phy_interface_t mode)
 			rtl9310_sds_field_w(asds, 0x6, 0x2, 12, 12, 1);
 
 			for (int i = 0; i < sizeof(sds_config_10p3125g_type1) / sizeof(sds_config); ++i) {
-				rtl931x_write_sds_phy(asds, sds_config_10p3125g_type1[i].page - 0x4, sds_config_10p3125g_type1[i].reg, sds_config_10p3125g_type1[i].data);
+				rtmdio_931x_write_sds_phy(asds, sds_config_10p3125g_type1[i].page - 0x4, sds_config_10p3125g_type1[i].reg, sds_config_10p3125g_type1[i].data);
 			}
 
 			evenSds = asds - (asds % 2);
 
 			for (int i = 0; i < sizeof(sds_config_10p3125g_cmu_type1) / sizeof(sds_config); ++i) {
-				rtl931x_write_sds_phy(evenSds,
+				rtmdio_931x_write_sds_phy(evenSds,
 				                      sds_config_10p3125g_cmu_type1[i].page - 0x4, sds_config_10p3125g_cmu_type1[i].reg, sds_config_10p3125g_cmu_type1[i].data);
 			}
 
@@ -3400,13 +3356,13 @@ void rtl931x_sds_init(u32 sds, phy_interface_t mode)
 			rtl9310_sds_field_w(asds, 0x2f, 0x1, 11, 0, 0x00);
 
 			rtl9310_sds_field_w(asds, 0x2e, 0xf, 12, 6, 0x7F);
-			rtl931x_write_sds_phy(asds, 0x2f, 0x12, 0xaaa);
+			rtmdio_931x_write_sds_phy(asds, 0x2f, 0x12, 0xaaa);
 
 			rtl931x_sds_rx_rst(sds);
 
-			rtl931x_write_sds_phy(asds, 0x7, 0x10, op_code);
-			rtl931x_write_sds_phy(asds, 0x6, 0x1d, 0x0480);
-			rtl931x_write_sds_phy(asds, 0x6, 0xe, 0x0400);
+			rtmdio_931x_write_sds_phy(asds, 0x7, 0x10, op_code);
+			rtmdio_931x_write_sds_phy(asds, 0x6, 0x1d, 0x0480);
+			rtmdio_931x_write_sds_phy(asds, 0x6, 0xe, 0x0400);
 		}
 		break;
 
@@ -3458,16 +3414,16 @@ void rtl931x_sds_init(u32 sds, phy_interface_t mode)
 
 	if (sds >= 2 && sds <= 13) {
 		if (chiptype)
-			rtl931x_write_sds_phy(asds, 0x2E, 0x1, board_sds_tx_type1[sds - 2]);
+			rtmdio_931x_write_sds_phy(asds, 0x2E, 0x1, board_sds_tx_type1[sds - 2]);
 		else {
 			val = 0xa0000;
 			sw_w32(val, RTL93XX_CHIP_INFO);
 			val = sw_r32(RTL93XX_CHIP_INFO);
 			if (val & BIT(28)) /* consider 9311 etc. RTL9313_CHIP_ID == HWP_CHIP_ID(unit)) */
 			{
-				rtl931x_write_sds_phy(asds, 0x2E, 0x1, board_sds_tx2[sds - 2]);
+				rtmdio_931x_write_sds_phy(asds, 0x2E, 0x1, board_sds_tx2[sds - 2]);
 			} else {
-				rtl931x_write_sds_phy(asds, 0x2E, 0x1, board_sds_tx[sds - 2]);
+				rtmdio_931x_write_sds_phy(asds, 0x2E, 0x1, board_sds_tx[sds - 2]);
 			}
 			val = 0;
 			sw_w32(val, RTL93XX_CHIP_INFO);
@@ -3523,7 +3479,7 @@ int rtl931x_sds_cmu_band_get(int sds, phy_interface_t mode)
 	sds -= (sds % 2);
 	asds = rtl931x_get_analog_sds(sds);
 	page += 1;
-	rtl931x_write_sds_phy(asds, 0x1f, 0x02, 73);
+	rtmdio_931x_write_sds_phy(asds, 0x1f, 0x02, 73);
 
 	rtl9310_sds_field_w(asds, page, 0x5, 15, 15, 1);
 	band = rtl9310_sds_field_r(asds, 0x1f, 0x15, 8, 3);
diff --git a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.h b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.h
index f57eb50867..652e27a5c5 100644
--- a/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.h
+++ b/target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.h
@@ -60,16 +60,12 @@ struct __attribute__ ((__packed__)) fw_header {
 #define RTL930X_MAC_FORCE_MODE_CTRL		(0xCA1C)
 
 /* Registers of the internal SerDes of the 9310 */
-#define RTL931X_SERDES_INDRT_ACCESS_CTRL	(0x5638)
-#define RTL931X_SERDES_INDRT_DATA_CTRL		(0x563C)
 #define RTL931X_SERDES_MODE_CTRL		(0x13cc)
 #define RTL931X_PS_SERDES_OFF_MODE_CTRL_ADDR	(0x13F4)
 #define RTL931X_MAC_SERDES_MODE_CTRL(sds)	(0x136C + (((sds) << 2)))
 
 int rtl9300_serdes_setup(int port, int sds_num, phy_interface_t phy_mode);
 
-int rtl931x_read_sds_phy(int phy_addr, int page, int phy_reg);
-int rtl931x_write_sds_phy(int phy_addr, int page, int phy_reg, u16 v);
 int rtl931x_sds_cmu_band_get(int sds, phy_interface_t mode);
 void rtl931x_sds_init(u32 sds, phy_interface_t mode);
 




More information about the lede-commits mailing list