From 31dc599a2b48f3825fae95e57816b576c8d0fdd2 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. Signed-off-by: Sander Vanheule --- ...dd-Realtek-Otto-auxiliary-controller.patch | 181 ++++++++++++++++++ 1 file changed, 181 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..0b417a7348 --- /dev/null +++ b/target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch @@ -0,0 +1,181 @@ +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,129 @@ ++// 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 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) ++{ ++ int err; ++ u32 cmd; ++ ++ cmd = rw_bit | RTL83XX_AUX_MDIO_EXEC; ++ cmd |= FIELD_PREP(RTL83XX_AUX_MDIO_PHY_ADDR, addr); ++ cmd |= FIELD_PREP(RTL83XX_AUX_MDIO_REG, regnum); ++ ++ if (rw_bit == RTL83XX_AUX_MDIO_WRITE) ++ cmd |= FIELD_PREP(RTL83XX_AUX_MDIO_DATA, *data); ++ ++ err = regmap_write(ctrl->map, ctrl->cmd_reg, cmd); ++ if (err) ++ return err; ++ ++ err = regmap_read_poll_timeout(ctrl->map, ctrl->cmd_reg, cmd, ++ !(cmd & RTL83XX_AUX_MDIO_EXEC), 3, 100); ++ ++ if (rw_bit == RTL83XX_AUX_MDIO_READ && !err) ++ *data = FIELD_GET(RTL83XX_AUX_MDIO_DATA, cmd); ++ ++ 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->cmd_reg = (unsigned int) device_get_match_data(&pdev->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 = &pdev->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(&pdev->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"); -- 2.30.2