]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
realtek: RTL930x: reorganize mdio functions and SerDes register layout 19692/head
authorMarkus Stockhausen <markus.stockhausen@gmx.de>
Wed, 6 Aug 2025 10:42:00 +0000 (06:42 -0400)
committerRobert Marko <robimarko@gmail.com>
Sun, 10 Aug 2025 09:47:30 +0000 (11:47 +0200)
The RTL930x mdio functions are scattered around the code. Relocate
them to the bus (still inside the ethernet driver). With this change
the phy identification looks into the proper registers. The SerDes
phy identifier (register 2/3) must be changed.

Additionally provide a consistent SerDes register access through the
mdio bus. Until now when a SerDes directly drives a SFP module there
is no clear rule of how to handle its register set that consists of
two parts:

- c22 phy registers 0-15 live in the fiber page (2) of the SerDes
- other SerDes specific registers exist in pages before and after

The mdio bus and other SerDes functions are a wild mix of directly
looking into page 2 or just using self defined methods to access
data.

Adapt the bus to the new consistent phy interface that mixes the
SerDes register set like classic Realtek phys do it.

- Use register 31 as page select (already in the bus)
- Always keep the common registers 0-15 in place and read fiber page
- Map the SerDes internal registers into the upper vendor specific
  registers 16-23 according to the page select register (31).

That gives a register mapping as follows:

+-----------------------+-----------------------+---------------+-------------+
| reg 0x00-0x0f         | reg 0x10-0x17         | reg 0x18-0x1e | reg 0x1f    |
+-----------------------+-----------------------+---------------+-------------+
| SerDes fiber page (3) | real SerDes registers | zero          | SerDes page |
| registers 0 - 15      | in packages of 8      |               | select reg  |
+-----------------------+-----------------------+---------------+-------------+

Example to make it as clear as possible.

SerDes registers on a RTL930x show

Page / Reg   | 0x00 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0A 0x0B ...
-------------+----------------------------------------------------------------
0 - SDS      | 0C03 0F00 7060 7106 074D 0EBF 0F0F 0359 5248 0000 0F80 0000 ...
1 - SDS_EXT  | 0000 0000 85FA 8C6D 5CCC 0000 20D8 0003 79AA 8C64 00C3 1482 ...
2 - FIB      | 1140 6189 001C CA40 01A0 0000 0000 0004 0000 0000 0000 0000 ...
3 - FIB_EXT  | 1140 6109 001C CA40 01A0 0000 0000 0004 0000 0000 0000 0000 ...

This translates to this phy layout

             | SerDes fiber registers  normal SerDes registers  zero     p.sel
Page / Reg   | 0x00 0x01 0x02 0x03 ... 0x10 0x11 0x12 0x13 ...  0x18 ... 0x1f
-------------+---------------------------------------------------------------
0            | 1140 6189 001C CA40 ... 0C03 0F00 7060 7106 ...  0000 ... 0000
1            | 1140 6189 001C CA40 ... 5248 0000 0F80 0000 ...  0000 ... 0001
...
4            | 1140 6189 001C CA40 ... 0000 0000 85FA 8C6D ...  0000 ... 0004

Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Link: https://github.com/openwrt/openwrt/pull/19692
Signed-off-by: Robert Marko <robimarko@gmail.com>
target/linux/realtek/files-6.12/arch/mips/include/asm/mach-rtl838x/mach-rtl83xx.h
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl83xx.h
target/linux/realtek/files-6.12/drivers/net/dsa/rtl83xx/rtl930x.c
target/linux/realtek/files-6.12/drivers/net/ethernet/rtl838x_eth.c
target/linux/realtek/files-6.12/drivers/net/phy/rtl83xx-phy.h

index 2946674036e4e55f153ca50e6feb2ef2c302e012..808cbd245c602b96b61f5ae0b0d4d5ba9864e101 100644 (file)
@@ -415,13 +415,6 @@ struct rtl83xx_soc_info {
 };
 
 /* rtl83xx-related functions used across subsystems */
-int rtl838x_smi_wait_op(int timeout);
-int rtl838x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
-int rtl838x_write_phy(u32 port, u32 page, u32 reg, u32 val);
-int rtl839x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
-int rtl839x_write_phy(u32 port, u32 page, u32 reg, u32 val);
-int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
-int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val);
 int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
 int rtl931x_write_phy(u32 port, u32 page, u32 reg, u32 val);
 
index 07cd98572a53dd8a3a3278d72d64ff855dc5cc30..7dff91e3b75215a792393989832ca166d0cace4a 100644 (file)
@@ -194,9 +194,6 @@ 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 rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
-int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
-
 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);
 
index 034b5c09f059d40c5cb03bd7930f62f06576daa3..d7f611f943bfa7d0ce71f435226acbc10ace6d95 100644 (file)
@@ -741,125 +741,6 @@ irqreturn_t rtldsa_930x_switch_irq(int irq, void *dev_id)
        return IRQ_HANDLED;
 }
 
-int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val)
-{
-       u32 v;
-       int err = 0;
-
-       pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, val);
-
-       if (port > 63 || page > 4095 || reg > 31)
-               return -ENOTSUPP;
-
-       val &= 0xffff;
-       mutex_lock(&smi_lock);
-
-       sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0);
-       sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
-       v = reg << 20 | page << 3 | 0x1f << 15 | BIT(2) | BIT(0);
-       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
-
-       do {
-               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
-       } while (v & 0x1);
-
-       if (v & 0x2)
-               err = -EIO;
-
-       mutex_unlock(&smi_lock);
-
-       return err;
-}
-
-int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
-{
-       u32 v;
-       int err = 0;
-
-       if (port > 63 || page > 4095 || reg > 31)
-               return -ENOTSUPP;
-
-       mutex_lock(&smi_lock);
-
-       sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
-       v = reg << 20 | page << 3 | 0x1f << 15 | 1;
-       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
-
-       do {
-               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
-       } while ( v & 0x1);
-
-       if (v & BIT(25)) {
-               pr_debug("Error reading phy %d, register %d\n", port, reg);
-               err = -EIO;
-       }
-       *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff);
-
-       pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, *val);
-
-       mutex_unlock(&smi_lock);
-
-       return err;
-}
-
-/* Write to an mmd register of the PHY */
-int rtl930x_write_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(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0);
-
-       /* Set data to write */
-       sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
-
-       /* Set MMD device number and register to write to */
-       sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3);
-
-       v = BIT(2) | BIT(1) | BIT(0); /* WRITE | MMD-access | EXEC */
-       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
-
-       do {
-               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
-       } 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;
-}
-
-/* Read an mmd register of the PHY */
-int rtl930x_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, RTL930X_SMI_ACCESS_PHY_CTRL_2);
-
-       /* Set MMD device number and register to write to */
-       sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3);
-
-       v = BIT(1) | BIT(0); /* MMD-access | EXEC */
-       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
-
-       do {
-               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
-       } while (v & BIT(0));
-       /* There is no error-checking via BIT 25 of v, as it does not seem to be set correctly */
-       *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff);
-       pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, *val, err);
-
-       mutex_unlock(&smi_lock);
-
-       return err;
-}
-
 /* Calculate both the block 0 and the block 1 hash, and return in
  * lower and higher word of the return value since only 12 bit of
  * the hash are significant
index 66e06bbb31ef5cae0439ff999cbec6b36a8d142b..66b808dba913a619b0b03b2827d7799f31086476 100644 (file)
@@ -27,11 +27,6 @@ extern struct rtl83xx_soc_info soc_info;
 
 extern int rtl83xx_setup_tc(struct net_device *dev, enum tc_setup_type type, void *type_data);
 
-extern int rtl930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
-extern int rtl930x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
-extern int rtl930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val);
-extern int rtl930x_write_phy(u32 port, u32 page, u32 reg, u32 val);
-
 extern int rtl931x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val);
 extern int rtl931x_read_phy(u32 port, u32 page, u32 reg, u32 *val);
 extern int rtl931x_read_sds_phy(int phy_addr, int page, int phy_reg);
@@ -2276,6 +2271,127 @@ int rtmdio_930x_write_sds_phy(int sds, int page, int regnum, u16 val)
        return ret;
 }
 
+/* RTL930x specific MDIO functions */
+
+static int rtmdio_930x_write_phy(u32 port, u32 page, u32 reg, u32 val)
+{
+       u32 v;
+       int err = 0;
+
+       pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, val);
+
+       if (port > 63 || page > 4095 || reg > 31)
+               return -ENOTSUPP;
+
+       val &= 0xffff;
+       mutex_lock(&rtmdio_lock);
+
+       sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0);
+       sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
+       v = reg << 20 | page << 3 | 0x1f << 15 | BIT(2) | BIT(0);
+       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
+
+       do {
+               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
+       } while (v & 0x1);
+
+       if (v & 0x2)
+               err = -EIO;
+
+       mutex_unlock(&rtmdio_lock);
+
+       return err;
+}
+
+static int rtmdio_930x_read_phy(u32 port, u32 page, u32 reg, u32 *val)
+{
+       u32 v;
+       int err = 0;
+
+       if (port > 63 || page > 4095 || reg > 31)
+               return -ENOTSUPP;
+
+       mutex_lock(&rtmdio_lock);
+
+       sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
+       v = reg << 20 | page << 3 | 0x1f << 15 | 1;
+       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
+
+       do {
+               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
+       } while ( v & 0x1);
+
+       if (v & BIT(25)) {
+               pr_debug("Error reading phy %d, register %d\n", port, reg);
+               err = -EIO;
+       }
+       *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff);
+
+       pr_debug("%s: port %d, page: %d, reg: %x, val: %x\n", __func__, port, page, reg, *val);
+
+       mutex_unlock(&rtmdio_lock);
+
+       return err;
+}
+
+/* Write to an mmd register of the PHY */
+static int rtmdio_930x_write_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 val)
+{
+       int err = 0;
+       u32 v;
+
+       mutex_lock(&rtmdio_lock);
+
+       /* Set PHY to access */
+       sw_w32(BIT(port), RTL930X_SMI_ACCESS_PHY_CTRL_0);
+
+       /* Set data to write */
+       sw_w32_mask(0xffff << 16, val << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
+
+       /* Set MMD device number and register to write to */
+       sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3);
+
+       v = BIT(2) | BIT(1) | BIT(0); /* WRITE | MMD-access | EXEC */
+       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
+
+       do {
+               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
+       } while (v & BIT(0));
+
+       pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, regnum, val, err);
+       mutex_unlock(&rtmdio_lock);
+       return err;
+}
+
+/* Read an mmd register of the PHY */
+static int rtmdio_930x_read_mmd_phy(u32 port, u32 devnum, u32 regnum, u32 *val)
+{
+       int err = 0;
+       u32 v;
+
+       mutex_lock(&rtmdio_lock);
+
+       /* Set PHY to access */
+       sw_w32_mask(0xffff << 16, port << 16, RTL930X_SMI_ACCESS_PHY_CTRL_2);
+
+       /* Set MMD device number and register to write to */
+       sw_w32(devnum << 16 | (regnum & 0xffff), RTL930X_SMI_ACCESS_PHY_CTRL_3);
+
+       v = BIT(1) | BIT(0); /* MMD-access | EXEC */
+       sw_w32(v, RTL930X_SMI_ACCESS_PHY_CTRL_1);
+
+       do {
+               v = sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_1);
+       } while (v & BIT(0));
+       /* There is no error-checking via BIT 25 of v, as it does not seem to be set correctly */
+       *val = (sw_r32(RTL930X_SMI_ACCESS_PHY_CTRL_2) & 0xffff);
+       pr_debug("%s: port %d, regnum: %x, val: %x (err %d)\n", __func__, port, 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)
@@ -2347,7 +2463,7 @@ static int rtmdio_write_sds_phy(struct rtmdio_bus_priv *priv, int sds, int page,
        return ret;
 }
 
-static int rtmdio_83xx_read(struct mii_bus *bus, int addr, int regnum)
+static int rtmdio_read(struct mii_bus *bus, int addr, int regnum)
 {
        struct rtmdio_bus_priv *priv = bus->priv;
        int err, val;
@@ -2388,12 +2504,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]) {
-               if (priv->family_id == RTL9300_FAMILY_ID)
-                       return rtmdio_930x_read_sds_phy(priv->sds_id[addr],
-                                                       priv->page[addr], regnum);
-               else
-                       return rtl931x_read_sds_phy(priv->sds_id[addr],
-                                                   priv->page[addr], regnum);
+               return rtl931x_read_sds_phy(priv->sds_id[addr],
+                                           priv->page[addr], regnum);
        }
 
        err = (*priv->read_phy)(addr, priv->page[addr], regnum, &val);
@@ -2419,7 +2531,7 @@ static int rtmdio_write_c45(struct mii_bus *bus, int addr, int devnum, int regnu
        return err;
 }
 
-static int rtmdio_83xx_write(struct mii_bus *bus, int addr, int regnum, u16 val)
+static int rtmdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
        struct rtmdio_bus_priv *priv = bus->priv;
        int err, page;
@@ -2480,12 +2592,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]) {
-                       if (priv->family_id == RTL9300_FAMILY_ID)
-                               return rtmdio_930x_write_sds_phy(priv->sds_id[addr],
-                                                                page, regnum, val);
-                       else
-                               return rtl931x_write_sds_phy(priv->sds_id[addr],
-                                                            page, regnum, val);
+                       return rtl931x_write_sds_phy(priv->sds_id[addr],
+                                                    page, regnum, val);
                }
 
                err = (*priv->write_phy)(addr, page, regnum, val);
@@ -2767,8 +2875,8 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
        switch(priv->family_id) {
        case RTL8380_FAMILY_ID:
                priv->mii_bus->name = "rtl838x-eth-mdio";
-               priv->mii_bus->read = rtmdio_83xx_read;
-               priv->mii_bus->write = rtmdio_83xx_write;
+               priv->mii_bus->read = rtmdio_read;
+               priv->mii_bus->write = rtmdio_write;
                priv->mii_bus->reset = rtmdio_838x_reset;
                bus_priv->read_sds_phy = rtmdio_838x_read_sds_phy;
                bus_priv->write_sds_phy = rtmdio_838x_write_sds_phy;
@@ -2781,8 +2889,8 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
                break;
        case RTL8390_FAMILY_ID:
                priv->mii_bus->name = "rtl839x-eth-mdio";
-               priv->mii_bus->read = rtmdio_83xx_read;
-               priv->mii_bus->write = rtmdio_83xx_write;
+               priv->mii_bus->read = rtmdio_read;
+               priv->mii_bus->write = rtmdio_write;
                priv->mii_bus->reset = rtmdio_839x_reset;
                bus_priv->read_sds_phy = rtmdio_839x_read_sds_phy;
                bus_priv->write_sds_phy = rtmdio_839x_write_sds_phy;
@@ -2795,13 +2903,15 @@ static int rtl838x_mdio_init(struct rtl838x_eth_priv *priv)
                break;
        case RTL9300_FAMILY_ID:
                priv->mii_bus->name = "rtl930x-eth-mdio";
-               priv->mii_bus->read = rtmdio_93xx_read;
-               priv->mii_bus->write = rtmdio_93xx_write;
+               priv->mii_bus->read = rtmdio_read;
+               priv->mii_bus->write = rtmdio_write;
                priv->mii_bus->reset = rtmdio_930x_reset;
-               bus_priv->read_mmd_phy = rtl930x_read_mmd_phy;
-               bus_priv->write_mmd_phy = rtl930x_write_mmd_phy;
-               bus_priv->read_phy = rtl930x_read_phy;
-               bus_priv->write_phy = rtl930x_write_phy;
+               bus_priv->read_sds_phy = rtmdio_930x_read_sds_phy;
+               bus_priv->write_sds_phy = rtmdio_930x_write_sds_phy;
+               bus_priv->read_mmd_phy = rtmdio_930x_read_mmd_phy;
+               bus_priv->write_mmd_phy = rtmdio_930x_write_mmd_phy;
+               bus_priv->read_phy = rtmdio_930x_read_phy;
+               bus_priv->write_phy = rtmdio_930x_write_phy;
                bus_priv->cpu_port = RTL930X_CPU_PORT;
                bus_priv->rawpage = 0xfff;
                break;
index 7fca3bb8c5b017d476ac891ac190bdf5feb53dea..f57eb508675f6b2af21fe3b22aca1ea9d7d2e433 100644 (file)
@@ -32,7 +32,7 @@ struct __attribute__ ((__packed__)) fw_header {
 #define PHY_ID_RTL8226                         0x001cc838
 #define PHY_ID_RTL8390_GENERIC                 0x001ccab0
 #define PHY_ID_RTL8393_I                       0x001c8393
-#define PHY_ID_RTL9300_I                       0x70d03106
+#define PHY_ID_RTL9300_I                       0x338002a0
 
 /* These PHYs share the same id (0x001cc981) */
 #define PHY_IS_NOT_RTL821X                     0