From: Markus Stockhausen Date: Wed, 10 Jun 2026 19:41:45 +0000 (+0200) Subject: net: mdio: realtek-rtl9300: Add support for RTL931x X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5ebdcac59affbbc044cc362200b9b03abe1c8345;p=thirdparty%2Flinux.git 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 Signed-off-by: Markus Stockhausen Link: https://patch.msgid.link/20260610194145.4153668-6-markus.stockhausen@gmx.de Signed-off-by: Jakub Kicinski --- diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c index 1cdf2049cfa5..892ed3780a65 100644 --- 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(struct mii_bus *bus, int port, 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_controller(struct otto_emdio_priv *priv) 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_emdio_9300_info = { .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);