From ae833c01b312258c27ff2dc1c8d44b15b7028e32 Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Fri, 27 Dec 2024 15:53:23 +0100 Subject: [PATCH] realtek: Add driver for auxiliary MDIO busses Add a driver that exposes the auxiliary busses, used for the RTL8231 expanders, as a proper MDIO controller. The device must be instantiated under an MFD device, so the driver should also be compatible with SoC managed by an external CPU via SPI. Leave the driver disabled in builds until required. Signed-off-by: Sander Vanheule --- ...dd-Realtek-Otto-auxiliary-controller.patch | 193 ++++++++++++++++++ target/linux/realtek/rtl838x/config-6.6 | 1 + target/linux/realtek/rtl839x/config-6.6 | 1 + target/linux/realtek/rtl930x/config-6.6 | 1 + target/linux/realtek/rtl931x/config-6.6 | 1 + 5 files changed, 197 insertions(+) create mode 100644 target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch diff --git a/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch b/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch new file mode 100644 index 0000000000..430f8f5c00 --- /dev/null +++ b/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch @@ -0,0 +1,193 @@ +From c7ddb74c981c1a29bad82d555d08724aca93b687 Mon Sep 17 00:00:00 2001 +From: Sander Vanheule +Date: Fri, 27 Dec 2024 14:55:31 +0100 +Subject: [PATCH] net: mdio: Add Realtek Otto auxiliary controller + +SoCs in Realtek's Otto platform such as the RTL8380 and RTL8391 have a +simple auxiliary MDIO controller that is commonly used to manage RTL8231 +GPIO expanders on switch devices. + +Add a new MDIO controller driver supporting the RTL838x (maple) and +RTL839x (cypress) SoCs. + +Signed-off-by: Sander Vanheule +--- + drivers/net/mdio/Kconfig | 10 ++ + drivers/net/mdio/Makefile | 1 + + drivers/net/mdio/mdio-realtek-otto-aux.c | 129 +++++++++++++++++++++++ + 3 files changed, 140 insertions(+) + create mode 100644 drivers/net/mdio/mdio-realtek-otto-aux.c + +--- a/drivers/net/mdio/Kconfig ++++ b/drivers/net/mdio/Kconfig +@@ -207,6 +207,16 @@ config MDIO_REGMAP + regmap. Users willing to use this driver must explicitly select + REGMAP. + ++config MDIO_REALTEK_OTTO_AUX ++ tristate "Realtek Otto auxiliary MDIO interface support" ++ default MACH_REALTEK_RTL ++ depends on MACH_REALTEK_RTL ++ depends on MFD_SYSCON ++ select MDIO_DEVRES ++ help ++ This driver supports the auxilairy MDIO bus on RTL838x SoCs. This bus ++ is typically used to attach RTL8231 GPIO extenders. ++ + config MDIO_THUNDER + tristate "ThunderX SOCs MDIO buses" + depends on 64BIT +--- a/drivers/net/mdio/Makefile ++++ b/drivers/net/mdio/Makefile +@@ -20,6 +20,7 @@ obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-ms + obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o + obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o + obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o ++obj-$(CONFIG_MDIO_REALTEK_OTTO_AUX) += mdio-realtek-otto-aux.o + obj-$(CONFIG_MDIO_SMBUS) += mdio-smbus.o + obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o + obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o +--- /dev/null ++++ b/drivers/net/mdio/mdio-realtek-otto-aux.c +@@ -0,0 +1,141 @@ ++// SPDX-License-Identifier: GPL-2.0-or-later ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define RTL8380_EXT_GPIO_INDIRECT_ACCESS 0xA09C ++#define RTL8390_EXT_GPIO_INDIRECT_ACCESS 0x0224 ++ ++#define RTL83XX_AUX_MDIO_DATA GENMASK(31, 16) ++#define RTL83XX_AUX_MDIO_REG GENMASK(11, 7) ++#define RTL83XX_AUX_MDIO_PHY_ADDR GENMASK(6, 2) ++#define RTL83XX_AUX_MDIO_WRITE BIT(1) ++#define RTL83XX_AUX_MDIO_READ 0 ++#define RTL83XX_AUX_MDIO_EXEC BIT(0) ++ ++struct realtek_aux_mdio_ctrl { ++ struct device *dev; ++ struct regmap *map; ++ unsigned int cmd_reg; ++}; ++ ++#define mii_bus_to_ctrl(bus) ((struct realtek_aux_mdio_ctrl *) bus->priv) ++ ++static int rtl83xx_aux_mdio_cmd(struct realtek_aux_mdio_ctrl *ctrl, int addr, int regnum, ++ u32 rw_bit, u16 *data) ++{ ++ unsigned int mask_volatile; ++ unsigned int cmd; ++ unsigned int run; ++ int err; ++ ++ cmd = rw_bit | RTL83XX_AUX_MDIO_EXEC; ++ cmd |= FIELD_PREP(RTL83XX_AUX_MDIO_PHY_ADDR, addr); ++ cmd |= FIELD_PREP(RTL83XX_AUX_MDIO_REG, regnum); ++ ++ mask_volatile = RTL83XX_AUX_MDIO_EXEC; ++ ++ if (rw_bit == RTL83XX_AUX_MDIO_WRITE) ++ cmd |= FIELD_PREP(RTL83XX_AUX_MDIO_DATA, *data); ++ else ++ mask_volatile |= RTL83XX_AUX_MDIO_DATA; ++ ++ err = regmap_write(ctrl->map, ctrl->cmd_reg, cmd); ++ if (err) ++ return err; ++ ++ err = regmap_read_poll_timeout(ctrl->map, ctrl->cmd_reg, run, (run != cmd), 3, 100); ++ ++ if ((run & ~mask_volatile) != (cmd & ~mask_volatile)) { ++ dev_err(ctrl->dev, "Command modified. Is offloading still active?"); ++ return -EIO; ++ } ++ ++ if (!err && (rw_bit == RTL83XX_AUX_MDIO_READ)) ++ *data = FIELD_GET(RTL83XX_AUX_MDIO_DATA, run); ++ ++ return err; ++} ++ ++static int rtl83xx_aux_mdio_read(struct mii_bus *bus, int addr, int regnum) ++{ ++ struct realtek_aux_mdio_ctrl *ctrl = mii_bus_to_ctrl(bus); ++ u16 data; ++ int err; ++ ++ err = rtl83xx_aux_mdio_cmd(ctrl, addr, regnum, RTL83XX_AUX_MDIO_READ, &data); ++ ++ if (err) ++ return err; ++ else ++ return data; ++} ++ ++static int rtl83xx_aux_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val) ++{ ++ struct realtek_aux_mdio_ctrl *ctrl = mii_bus_to_ctrl(bus); ++ ++ return rtl83xx_aux_mdio_cmd(ctrl, addr, regnum, RTL83XX_AUX_MDIO_WRITE, &val); ++} ++ ++static int realtek_aux_mdio_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct realtek_aux_mdio_ctrl *ctrl; ++ struct mii_bus *bus; ++ ++ bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*ctrl)); ++ if (!bus) ++ return -ENOMEM; ++ ++ ctrl = bus->priv; ++ ctrl->dev = &pdev->dev; ++ ctrl->cmd_reg = (unsigned int) device_get_match_data(ctrl->dev); ++ ctrl->map = syscon_node_to_regmap(np->parent); ++ if (IS_ERR(ctrl->map)) ++ return PTR_ERR(ctrl->map); ++ ++ bus->name = "RTL83xx auxiliary MDIO bus"; ++ snprintf(bus->id, MII_BUS_ID_SIZE, "rtl83xx-aux-mdio") ; ++ bus->parent = ctrl->dev; ++ bus->read = rtl83xx_aux_mdio_read; ++ bus->write = rtl83xx_aux_mdio_write; ++ /* Don't have interrupts */ ++ for (unsigned int i = 0; i < PHY_MAX_ADDR; i++) ++ bus->irq[i] = PHY_POLL; ++ ++ return devm_of_mdiobus_register(ctrl->dev, bus, np); ++} ++ ++static const struct of_device_id realtek_aux_mdio_of_match[] = { ++ { ++ .compatible = "realtek,rtl8380-aux-mdio", ++ .data = (void *) RTL8380_EXT_GPIO_INDIRECT_ACCESS, ++ }, ++ { ++ .compatible = "realtek,rtl8390-aux-mdio", ++ .data = (void *) RTL8390_EXT_GPIO_INDIRECT_ACCESS, ++ }, ++ { /* sentinel */ } ++}; ++MODULE_DEVICE_TABLE(of, realtek_aux_mdio_of_match); ++ ++static struct platform_driver realtek_aux_mdio_driver = { ++ .driver = { ++ .name = "realtek-otto-aux-mdio", ++ .of_match_table = realtek_aux_mdio_of_match ++ }, ++ .probe = realtek_aux_mdio_probe, ++}; ++module_platform_driver(realtek_aux_mdio_driver); ++ ++MODULE_AUTHOR("Sander Vanheule "); ++MODULE_DESCRIPTION("Realtek RTL83xx auxiliary MDIO bus"); ++MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/rtl838x/config-6.6 b/target/linux/realtek/rtl838x/config-6.6 index a190a69ec6..6cceded5af 100644 --- a/target/linux/realtek/rtl838x/config-6.6 +++ b/target/linux/realtek/rtl838x/config-6.6 @@ -130,6 +130,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y CONFIG_MDIO_I2C=y +# CONFIG_MDIO_REALTEK_OTTO_AUX is not set CONFIG_MDIO_SMBUS=y CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y diff --git a/target/linux/realtek/rtl839x/config-6.6 b/target/linux/realtek/rtl839x/config-6.6 index 53a167e8f7..ebf473db61 100644 --- a/target/linux/realtek/rtl839x/config-6.6 +++ b/target/linux/realtek/rtl839x/config-6.6 @@ -130,6 +130,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y CONFIG_MDIO_I2C=y +# CONFIG_MDIO_REALTEK_OTTO_AUX is not set CONFIG_MDIO_SMBUS=y CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y diff --git a/target/linux/realtek/rtl930x/config-6.6 b/target/linux/realtek/rtl930x/config-6.6 index a6a23ebcff..35d088fe08 100644 --- a/target/linux/realtek/rtl930x/config-6.6 +++ b/target/linux/realtek/rtl930x/config-6.6 @@ -112,6 +112,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y CONFIG_MDIO_I2C=y +# CONFIG_MDIO_REALTEK_OTTO_AUX is not set CONFIG_MDIO_SMBUS=y CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y diff --git a/target/linux/realtek/rtl931x/config-6.6 b/target/linux/realtek/rtl931x/config-6.6 index 9d332cee27..d843382f51 100644 --- a/target/linux/realtek/rtl931x/config-6.6 +++ b/target/linux/realtek/rtl931x/config-6.6 @@ -120,6 +120,7 @@ CONFIG_MDIO_BUS=y CONFIG_MDIO_DEVICE=y CONFIG_MDIO_DEVRES=y CONFIG_MDIO_I2C=y +# CONFIG_MDIO_REALTEK_OTTO_AUX is not set CONFIG_MDIO_SMBUS=y CONFIG_MFD_SYSCON=y CONFIG_MIGRATION=y -- 2.30.2