realtek: Add driver for auxiliary MDIO busses
authorSander Vanheule <sander@svanheule.net>
Fri, 27 Dec 2024 14:53:23 +0000 (15:53 +0100)
committerSander Vanheule <sander@svanheule.net>
Wed, 15 Jan 2025 12:03:53 +0000 (13:03 +0100)
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 <sander@svanheule.net>
(cherry picked from commit ae833c01b312258c27ff2dc1c8d44b15b7028e32)

target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch [new file with mode: 0644]
target/linux/realtek/rtl838x/config-6.6
target/linux/realtek/rtl839x/config-6.6
target/linux/realtek/rtl930x/config-6.6
target/linux/realtek/rtl931x/config-6.6

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 (file)
index 0000000..430f8f5
--- /dev/null
@@ -0,0 +1,193 @@
+From c7ddb74c981c1a29bad82d555d08724aca93b687 Mon Sep 17 00:00:00 2001
+From: Sander Vanheule <sander@svanheule.net>
+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 <sander@svanheule.net>
+---
+ 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 <linux/mfd/core.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of.h>
++#include <linux/of_mdio.h>
++#include <linux/of_platform.h>
++#include <linux/phy.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++
++#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 <sander@svanheule.net>");
++MODULE_DESCRIPTION("Realtek RTL83xx auxiliary MDIO bus");
++MODULE_LICENSE("GPL v2");
index 44c1d7e0645c9d15db313faa1fa3f59df71f1bd8..d031965cea41b74b2d61f7e7e3485f65f9182aba 100644 (file)
@@ -122,6 +122,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_MEMFD_CREATE=y
 CONFIG_MFD_SYSCON=y
index 630027bf8133bbd957a8d1efbce24df69b954b19..4612a73e4ad9ec3ee777093d4fa1a40ef0aea2e1 100644 (file)
@@ -121,6 +121,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_MEMFD_CREATE=y
 CONFIG_MFD_SYSCON=y
index 5a29bdc3c1ba78944399cfc2a691172209e436c2..694f10019ebbe2a0ff3fc14d3ca41d3092113306 100644 (file)
@@ -103,6 +103,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_MEMFD_CREATE=y
 CONFIG_MFD_SYSCON=y
index df235defe83c84706f21032ecab551d84d97dd55..9ab93d4fe760e0a14cd66d86663d0bc18025af95 100644 (file)
@@ -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_MEMFD_CREATE=y
 CONFIG_MFD_SYSCON=y