--- /dev/null
+From 474400cf3f9faec064a35a7725c72a52f5ec6e5f Mon Sep 17 00:00:00 2001
+From: Markus Stockhausen <markus.stockhausen@gmx.de>
+Date: Sun, 7 Jun 2026 09:10:20 +0200
+Subject: [PATCH 04/15] net: mdio: realtek-rtl9300: Add prefix to register
+ field defines
+
+The current Realtek Otto MDIO driver has some define leftovers without
+a SoC prefix. When adding new devices there will be an overlap for some
+of them. Sort this out as follows:
+
+- PHY_CTRL_CMD/PHY_CTRL_MMD_DEVAD/PHY_CTRL_MMD_REG are common for all
+ series. Leave them as is but move them into a separate block.
+- Add RTL9300 prefix to all other defines and adapt the callers.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
+---
+ drivers/net/mdio/mdio-realtek-rtl9300.c | 63 +++++++++++++------------
+ 1 file changed, 32 insertions(+), 31 deletions(-)
+
+--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
++++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
+@@ -59,23 +59,24 @@
+ #define RTL9300_SMI_PORT0_15_POLLING_SEL 0xca08
+ #define RTL9300_SMI_ACCESS_PHY_CTRL_0 0xcb70
+ #define RTL9300_SMI_ACCESS_PHY_CTRL_1 0xcb74
+-#define PHY_CTRL_REG_ADDR GENMASK(24, 20)
+-#define PHY_CTRL_PARK_PAGE GENMASK(19, 15)
+-#define PHY_CTRL_MAIN_PAGE GENMASK(14, 3)
+-#define PHY_CTRL_WRITE BIT(2)
+-#define PHY_CTRL_READ 0
+-#define PHY_CTRL_TYPE_C45 BIT(1)
+-#define PHY_CTRL_TYPE_C22 0
+-#define PHY_CTRL_CMD BIT(0)
+-#define PHY_CTRL_FAIL BIT(25)
++#define RTL9300_PHY_CTRL_REG_ADDR GENMASK(24, 20)
++#define RTL9300_PHY_CTRL_PARK_PAGE GENMASK(19, 15)
++#define RTL9300_PHY_CTRL_MAIN_PAGE GENMASK(14, 3)
++#define RTL9300_PHY_CTRL_WRITE BIT(2)
++#define RTL9300_PHY_CTRL_READ 0
++#define RTL9300_PHY_CTRL_TYPE_C45 BIT(1)
++#define RTL9300_PHY_CTRL_TYPE_C22 0
++#define RTL9300_PHY_CTRL_FAIL BIT(25)
+ #define RTL9300_SMI_ACCESS_PHY_CTRL_2 0xcb78
+-#define PHY_CTRL_INDATA GENMASK(31, 16)
+-#define PHY_CTRL_DATA GENMASK(15, 0)
++#define RTL9300_PHY_CTRL_INDATA GENMASK(31, 16)
++#define RTL9300_PHY_CTRL_DATA GENMASK(15, 0)
+ #define RTL9300_SMI_ACCESS_PHY_CTRL_3 0xcb7c
+-#define PHY_CTRL_MMD_DEVAD GENMASK(20, 16)
+-#define PHY_CTRL_MMD_REG GENMASK(15, 0)
+ #define RTL9300_SMI_PORT0_5_ADDR_CTRL 0xcb80
+
++#define PHY_CTRL_CMD BIT(0)
++#define PHY_CTRL_MMD_DEVAD GENMASK(20, 16)
++#define PHY_CTRL_MMD_REG GENMASK(15, 0)
++
+ #define MAP_ADDRS_PER_REG 6
+ #define MAP_BITS_PER_ADDR 5
+ #define MAP_BITS_PER_BUS 2
+@@ -204,7 +205,7 @@ static int otto_emdio_read_cmd(struct mi
+ if (ret)
+ return ret;
+
+- *value = FIELD_GET(PHY_CTRL_DATA, *value);
++ *value = FIELD_GET(RTL9300_PHY_CTRL_DATA, *value);
+
+ return 0;
+ }
+@@ -223,27 +224,27 @@ static int otto_emdio_9300_read_c22(stru
+ {
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+ struct otto_emdio_cmd_regs cmd_data = {
+- .c22_data = FIELD_PREP(PHY_CTRL_REG_ADDR, regnum) |
+- FIELD_PREP(PHY_CTRL_PARK_PAGE, 0x1f) |
+- FIELD_PREP(PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
+- .io_data = FIELD_PREP(PHY_CTRL_INDATA, port),
++ .c22_data = FIELD_PREP(RTL9300_PHY_CTRL_REG_ADDR, regnum) |
++ FIELD_PREP(RTL9300_PHY_CTRL_PARK_PAGE, 0x1f) |
++ FIELD_PREP(RTL9300_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
++ .io_data = FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
+ };
+
+- return otto_emdio_read_cmd(bus, PHY_CTRL_TYPE_C22, &cmd_data, value);
++ return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data, value);
+ }
+
+ static int otto_emdio_9300_write_c22(struct mii_bus *bus, int port, int regnum, u16 value)
+ {
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+ struct otto_emdio_cmd_regs cmd_data = {
+- .c22_data = FIELD_PREP(PHY_CTRL_REG_ADDR, regnum) |
+- FIELD_PREP(PHY_CTRL_PARK_PAGE, 0x1f) |
+- FIELD_PREP(PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
+- .io_data = FIELD_PREP(PHY_CTRL_INDATA, value),
++ .c22_data = FIELD_PREP(RTL9300_PHY_CTRL_REG_ADDR, regnum) |
++ FIELD_PREP(RTL9300_PHY_CTRL_PARK_PAGE, 0x1f) |
++ FIELD_PREP(RTL9300_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
++ .io_data = FIELD_PREP(RTL9300_PHY_CTRL_INDATA, value),
+ .port_mask_low = BIT(port),
+ };
+
+- return otto_emdio_write_cmd(bus, PHY_CTRL_TYPE_C22, &cmd_data);
++ return otto_emdio_write_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data);
+ }
+
+ static int otto_emdio_9300_read_c45(struct mii_bus *bus, int port,
+@@ -252,10 +253,10 @@ static int otto_emdio_9300_read_c45(stru
+ struct otto_emdio_cmd_regs cmd_data = {
+ .c45_data = FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
+ FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
+- .io_data = FIELD_PREP(PHY_CTRL_INDATA, port),
++ .io_data = FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
+ };
+
+- return otto_emdio_read_cmd(bus, PHY_CTRL_TYPE_C45, &cmd_data, value);
++ return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data, value);
+ }
+
+ static int otto_emdio_9300_write_c45(struct mii_bus *bus, int port,
+@@ -264,11 +265,11 @@ static int otto_emdio_9300_write_c45(str
+ struct otto_emdio_cmd_regs cmd_data = {
+ .c45_data = FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
+ FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
+- .io_data = FIELD_PREP(PHY_CTRL_INDATA, value),
++ .io_data = FIELD_PREP(RTL9300_PHY_CTRL_INDATA, value),
+ .port_mask_low = BIT(port),
+ };
+
+- return otto_emdio_write_cmd(bus, PHY_CTRL_TYPE_C45, &cmd_data);
++ return otto_emdio_write_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data);
+ }
+
+ static int otto_emdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
+@@ -582,9 +583,9 @@ static int otto_emdio_probe(struct platf
+ static const struct otto_emdio_info otto_emdio_9300_info = {
+ .addr_map_base = RTL9300_SMI_PORT0_5_ADDR_CTRL,
+ .bus_map_base = RTL9300_SMI_PORT0_15_POLLING_SEL,
+- .cmd_fail = PHY_CTRL_FAIL,
+- .cmd_read = PHY_CTRL_READ,
+- .cmd_write = PHY_CTRL_WRITE,
++ .cmd_fail = RTL9300_PHY_CTRL_FAIL,
++ .cmd_read = RTL9300_PHY_CTRL_READ,
++ .cmd_write = RTL9300_PHY_CTRL_WRITE,
+ .cmd_regs = {
+ .c22_data = RTL9300_SMI_ACCESS_PHY_CTRL_1,
+ .c45_data = RTL9300_SMI_ACCESS_PHY_CTRL_3,
--- /dev/null
+From 2b24f54b8751e483a67443f93941a81c05ccce67 Mon Sep 17 00:00:00 2001
+From: Markus Stockhausen <markus.stockhausen@gmx.de>
+Date: Sun, 7 Jun 2026 10:12:51 +0200
+Subject: [PATCH 05/15] net: mdio: realtek-rtl9300: Make otto_emdio_read_cmd()
+ generic
+
+The otto_emdio_read_cmd() helper still uses RTL9300 specific properties.
+This cannot be made generic as the I/O register has different layouts for
+the different SoCs. E.g.
+
+- RTL930x: data in bits 31-16, data out bits 15-0
+- RTL931x: data in bits 15-0, data out bits 31-16
+
+Add a mask parameter to the function signature and fill it properly
+in the callers. As the masks will always have bits set from constant
+defines, there is no need for a consistency check.
+
+Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
+Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
+---
+ drivers/net/mdio/mdio-realtek-rtl9300.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
++++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
+@@ -191,7 +191,7 @@ static int otto_emdio_run_cmd(struct mii
+ }
+
+ static int otto_emdio_read_cmd(struct mii_bus *bus, u32 cmd,
+- struct otto_emdio_cmd_regs *cmd_data, u32 *value)
++ struct otto_emdio_cmd_regs *cmd_data, u32 mask, u32 *value)
+ {
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+ int ret;
+@@ -205,7 +205,7 @@ static int otto_emdio_read_cmd(struct mi
+ if (ret)
+ return ret;
+
+- *value = FIELD_GET(RTL9300_PHY_CTRL_DATA, *value);
++ *value = field_get(mask, *value);
+
+ return 0;
+ }
+@@ -230,7 +230,8 @@ static int otto_emdio_9300_read_c22(stru
+ .io_data = FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
+ };
+
+- return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data, value);
++ return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C22, &cmd_data,
++ RTL9300_PHY_CTRL_DATA, value);
+ }
+
+ static int otto_emdio_9300_write_c22(struct mii_bus *bus, int port, int regnum, u16 value)
+@@ -256,7 +257,8 @@ static int otto_emdio_9300_read_c45(stru
+ .io_data = FIELD_PREP(RTL9300_PHY_CTRL_INDATA, port),
+ };
+
+- return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data, value);
++ return otto_emdio_read_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data,
++ RTL9300_PHY_CTRL_DATA, value);
+ }
+
+ static int otto_emdio_9300_write_c45(struct mii_bus *bus, int port,
--- /dev/null
+From 2628d4b57215ff57c062644523badbabeb22a095 Mon Sep 17 00:00:00 2001
+From: Markus Stockhausen <markus.stockhausen@gmx.de>
+Date: Sun, 7 Jun 2026 09:24:09 +0200
+Subject: [PATCH 06/15] net: mdio: realtek-rtl9300: Add registers for high port
+ count models
+
+The high port count models of the Realtek Otto switches have additional
+registers to instrument the MDIO controller. These are:
+
+- High port mask: A bitfield that extends the already existing low port
+ mask to select ports starting from 32.
+- Broadcast: This takes the port number during reads on the RTL931x.
+- Extended page: Some additional page info. The SDK does not give much
+ information about this. Basically some fixed value must be written
+ into it during access.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
+---
+ drivers/net/mdio/mdio-realtek-rtl9300.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
++++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
+@@ -91,6 +91,10 @@ struct otto_emdio_cmd_regs {
+ u32 c45_data;
+ u32 io_data;
+ u32 port_mask_low;
++ /* additional registers for high port count models RTL839x/RTL931x */
++ u32 port_mask_high;
++ u32 broadcast;
++ u32 ext_page;
+ };
+
+ struct otto_emdio_priv {
+@@ -164,6 +168,22 @@ static int otto_emdio_run_cmd(struct mii
+ return ret;
+
+ /* Fill all registers. Hardware will read only the needed bits depending on command */
++ if (info->cmd_regs.port_mask_high) {
++ /* Fill extra registers for high port count models */
++ ret = regmap_write(priv->regmap, info->cmd_regs.broadcast, cmd_data->broadcast);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(priv->regmap, info->cmd_regs.ext_page, cmd_data->ext_page);
++ if (ret)
++ return ret;
++
++ ret = regmap_write(priv->regmap,
++ info->cmd_regs.port_mask_high, cmd_data->port_mask_high);
++ if (ret)
++ return ret;
++ }
++
+ ret = regmap_write(priv->regmap, info->cmd_regs.port_mask_low, cmd_data->port_mask_low);
+ if (ret)
+ return ret;
--- /dev/null
+From 390dfbbd1ead27523853a21fd587b1285006a4ef Mon Sep 17 00:00:00 2001
+From: Markus Stockhausen <markus.stockhausen@gmx.de>
+Date: Sun, 7 Jun 2026 10:09:44 +0200
+Subject: [PATCH 07/15] net: mdio: realtek-rtl9300: Add support for RTL931x
+
+The MDIO driver has been prepared for multiple device support. Add all
+required bits for the RTL931x (aka mango) series. This is straightforward
+but some things are worth to be mentioned.
+
+- In contrast to RTL930x the I/O register has the input/output fields
+ swapped. Upper 16 bits are for read/outputs, and the lower 16 bits
+ are for write/inputs.
+- The supported "pages" are 8192 and thus the raw page is 8191
+- The devices support up to 56 ports. Thus the MAX_PORTS definition
+ is increased by this commit.
+- There are multiple global SMI controller registers with a different
+ layout from RTL930x devices. Therefore a separate setup_controller()
+ callback is added.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
+---
+ drivers/net/mdio/mdio-realtek-rtl9300.c | 123 +++++++++++++++++++++++-
+ 1 file changed, 122 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
++++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
+@@ -73,6 +73,31 @@
+ #define RTL9300_SMI_ACCESS_PHY_CTRL_3 0xcb7c
+ #define RTL9300_SMI_PORT0_5_ADDR_CTRL 0xcb80
+
++#define RTL9310_NUM_BUSES 4
++#define RTL9310_NUM_PAGES 8192
++#define RTL9310_NUM_PORTS 56
++#define RTL9310_SMI_GLB_CTRL1 0x0cbc
++#define RTL9310_SMI_GLB_FMT_SEL_C45(intf) BIT((intf) * 2 + 1)
++#define RTL9310_SMI_INDRT_ACCESS_CTRL_0 0x0c00
++#define RTL9310_PHY_CTRL_REG_ADDR GENMASK(10, 6)
++#define RTL9310_PHY_CTRL_MAIN_PAGE GENMASK(23, 11)
++#define RTL9310_PHY_CTRL_READ 0
++#define RTL9310_PHY_CTRL_WRITE BIT(4)
++#define RTL9310_PHY_CTRL_TYPE_C45 BIT(3)
++#define RTL9310_PHY_CTRL_TYPE_C22 0
++#define RTL9310_PHY_CTRL_FAIL BIT(1)
++#define RTL9310_SMI_INDRT_ACCESS_BC_PHYID_CTRL 0x0c14
++#define RTL9310_BC_PORT_ID GENMASK(10, 5)
++#define RTL9310_SMI_INDRT_ACCESS_CTRL_1 0x0c04
++#define RTL9310_SMI_INDRT_ACCESS_CTRL_2_LOW 0x0c08
++#define RTL9310_SMI_INDRT_ACCESS_CTRL_2_HIGH 0x0c0c
++#define RTL9310_SMI_INDRT_ACCESS_CTRL_3 0x0c10 /* I/O fields flipped */
++#define RTL9310_PHY_CTRL_DATA GENMASK(31, 16)
++#define RTL9310_PHY_CTRL_INDATA GENMASK(15, 0)
++#define RTL9310_SMI_INDRT_ACCESS_MMD_CTRL 0x0c18
++#define RTL9310_SMI_PORT_ADDR_CTRL 0x0c74
++#define RTL9310_SMI_PORT_POLLING_SEL 0x0c9c
++
+ #define PHY_CTRL_CMD BIT(0)
+ #define PHY_CTRL_MMD_DEVAD GENMASK(20, 16)
+ #define PHY_CTRL_MMD_REG GENMASK(15, 0)
+@@ -81,7 +106,7 @@
+ #define MAP_BITS_PER_ADDR 5
+ #define MAP_BITS_PER_BUS 2
+ #define MAP_BUSES_PER_REG 16
+-#define MAX_PORTS 28
++#define MAX_PORTS 56
+ #define MAX_SMI_BUSSES 4
+ #define RAW_PAGE(priv) ((priv)->info->num_pages - 1)
+
+@@ -294,6 +319,60 @@ static int otto_emdio_9300_write_c45(str
+ return otto_emdio_write_cmd(bus, RTL9300_PHY_CTRL_TYPE_C45, &cmd_data);
+ }
+
++static int otto_emdio_9310_read_c22(struct mii_bus *bus, int port, int regnum, u32 *value)
++{
++ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
++ struct otto_emdio_cmd_regs cmd_data = {
++ .broadcast = FIELD_PREP(RTL9310_BC_PORT_ID, port),
++ .c22_data = FIELD_PREP(RTL9310_PHY_CTRL_REG_ADDR, regnum) |
++ FIELD_PREP(RTL9310_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
++ };
++
++ return otto_emdio_read_cmd(bus, RTL9310_PHY_CTRL_TYPE_C22, &cmd_data,
++ RTL9310_PHY_CTRL_DATA, value);
++}
++
++static int otto_emdio_9310_write_c22(struct mii_bus *bus, int port, int regnum, u16 value)
++{
++ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
++ struct otto_emdio_cmd_regs cmd_data = {
++ .c22_data = FIELD_PREP(RTL9310_PHY_CTRL_REG_ADDR, regnum) |
++ FIELD_PREP(RTL9310_PHY_CTRL_MAIN_PAGE, RAW_PAGE(priv)),
++ .io_data = FIELD_PREP(RTL9310_PHY_CTRL_INDATA, value),
++ .port_mask_high = (u32)(BIT_ULL(port) >> 32),
++ .port_mask_low = (u32)(BIT_ULL(port)),
++ };
++
++ return otto_emdio_write_cmd(bus, RTL9310_PHY_CTRL_TYPE_C22, &cmd_data);
++}
++
++static int otto_emdio_9310_read_c45(struct mii_bus *bus, int port,
++ int dev_addr, int regnum, u32 *value)
++{
++ struct otto_emdio_cmd_regs cmd_data = {
++ .broadcast = FIELD_PREP(RTL9310_BC_PORT_ID, port),
++ .c45_data = FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
++ FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
++ };
++
++ return otto_emdio_read_cmd(bus, RTL9310_PHY_CTRL_TYPE_C45, &cmd_data,
++ RTL9310_PHY_CTRL_DATA, value);
++}
++
++static int otto_emdio_9310_write_c45(struct mii_bus *bus, int port,
++ int dev_addr, int regnum, u16 value)
++{
++ struct otto_emdio_cmd_regs cmd_data = {
++ .c45_data = FIELD_PREP(PHY_CTRL_MMD_DEVAD, dev_addr) |
++ FIELD_PREP(PHY_CTRL_MMD_REG, regnum),
++ .io_data = FIELD_PREP(RTL9310_PHY_CTRL_INDATA, value),
++ .port_mask_high = (u32)(BIT_ULL(port) >> 32),
++ .port_mask_low = (u32)(BIT_ULL(port)),
++ };
++
++ return otto_emdio_write_cmd(bus, RTL9310_PHY_CTRL_TYPE_C45, &cmd_data);
++}
++
+ static int otto_emdio_read_c22(struct mii_bus *bus, int phy_id, int regnum)
+ {
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+@@ -413,6 +492,22 @@ static int otto_emdio_9300_setup_control
+ return 0;
+ }
+
++static int otto_emdio_9310_setup_controller(struct otto_emdio_priv *priv)
++{
++ int i, err;
++
++ /* Put the interfaces into C45 mode if required */
++ for (i = 0; i < priv->info->num_buses; i++) {
++ err = regmap_assign_bits(priv->regmap, RTL9310_SMI_GLB_CTRL1,
++ RTL9310_SMI_GLB_FMT_SEL_C45(i),
++ priv->smi_bus_is_c45[i]);
++ if (err)
++ return err;
++ }
++
++ return 0;
++}
++
+ static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv,
+ struct fwnode_handle *node)
+ {
+@@ -624,8 +719,34 @@ static const struct otto_emdio_info otto
+ .write_c45 = otto_emdio_9300_write_c45,
+ };
+
++static const struct otto_emdio_info otto_emdio_9310_info = {
++ .addr_map_base = RTL9310_SMI_PORT_ADDR_CTRL,
++ .bus_map_base = RTL9310_SMI_PORT_POLLING_SEL,
++ .cmd_fail = RTL9310_PHY_CTRL_FAIL,
++ .cmd_read = RTL9310_PHY_CTRL_READ,
++ .cmd_write = RTL9310_PHY_CTRL_WRITE,
++ .cmd_regs = {
++ .broadcast = RTL9310_SMI_INDRT_ACCESS_BC_PHYID_CTRL,
++ .c22_data = RTL9310_SMI_INDRT_ACCESS_CTRL_0,
++ .c45_data = RTL9310_SMI_INDRT_ACCESS_MMD_CTRL,
++ .ext_page = RTL9310_SMI_INDRT_ACCESS_CTRL_1,
++ .io_data = RTL9310_SMI_INDRT_ACCESS_CTRL_3,
++ .port_mask_low = RTL9310_SMI_INDRT_ACCESS_CTRL_2_LOW,
++ .port_mask_high = RTL9310_SMI_INDRT_ACCESS_CTRL_2_HIGH,
++ },
++ .num_buses = RTL9310_NUM_BUSES,
++ .num_pages = RTL9310_NUM_PAGES,
++ .num_ports = RTL9310_NUM_PORTS,
++ .setup_controller = otto_emdio_9310_setup_controller,
++ .read_c22 = otto_emdio_9310_read_c22,
++ .read_c45 = otto_emdio_9310_read_c45,
++ .write_c22 = otto_emdio_9310_write_c22,
++ .write_c45 = otto_emdio_9310_write_c45,
++};
++
+ static const struct of_device_id otto_emdio_ids[] = {
+ { .compatible = "realtek,rtl9301-mdio", .data = &otto_emdio_9300_info },
++ { .compatible = "realtek,rtl9311-mdio", .data = &otto_emdio_9310_info },
+ {}
+ };
+ MODULE_DEVICE_TABLE(of, otto_emdio_ids);