mirror of
https://github.com/openwrt/openwrt.git
synced 2025-01-19 03:06:35 +00:00
realtek: Update aux-mdio driver
For RTL839x, the driver was producing frequent timeouts on bus accesses. Increasing the timeout to the one from a recent Realtek SDK resolves these timeouts. To minimize overhead on different SoCs, each controller can specify their own timeout. This also add support for the register format as used on RTL93xx. Support is added for the RTL930x "ext gpio" controller. Signed-off-by: Sander Vanheule <sander@svanheule.net>
This commit is contained in:
parent
7482296ebf
commit
52ffef6471
@ -1,21 +1,21 @@
|
||||
From c7ddb74c981c1a29bad82d555d08724aca93b687 Mon Sep 17 00:00:00 2001
|
||||
From ffb7da9aa25765b2115e7ff3ee4f6dafa60f5421 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.
|
||||
SoCs in Realtek's Otto platform such as the RTL8380, RTL8391, and
|
||||
RTL9302 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.
|
||||
Add a new MDIO controller driver supporting the RTL838x (maple), RTL839x
|
||||
(cypress), and RTL930x (longan) 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(+)
|
||||
drivers/net/mdio/mdio-realtek-otto-aux.c | 175 +++++++++++++++++++++++
|
||||
3 files changed, 186 insertions(+)
|
||||
create mode 100644 drivers/net/mdio/mdio-realtek-otto-aux.c
|
||||
|
||||
--- a/drivers/net/mdio/Kconfig
|
||||
@ -49,7 +49,7 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/mdio/mdio-realtek-otto-aux.c
|
||||
@@ -0,0 +1,141 @@
|
||||
@@ -0,0 +1,175 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+
|
||||
+#include <linux/mfd/core.h>
|
||||
@ -64,65 +64,95 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
+
|
||||
+#define RTL8380_EXT_GPIO_INDIRECT_ACCESS 0xA09C
|
||||
+#define RTL8390_EXT_GPIO_INDIRECT_ACCESS 0x0224
|
||||
+#define RTL9300_EXT_GPIO_INDIRECT_ACCESS 0xC620
|
||||
+
|
||||
+#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)
|
||||
+#define RTL83XX_AUX_MDIO_DATA_OFFSET 16
|
||||
+#define RTL83XX_AUX_MDIO_RCMD_FAIL 0
|
||||
+
|
||||
+#define RTL93XX_AUX_MDIO_DATA_OFFSET 12
|
||||
+#define RTL93XX_AUX_MDIO_RCMD_FAIL BIT(28)
|
||||
+
|
||||
+#define REALTEK_AUX_MDIO_REG GENMASK(11, 7)
|
||||
+#define REALTEK_AUX_MDIO_PHY_ADDR GENMASK(6, 2)
|
||||
+#define REALTEK_AUX_MDIO_WRITE BIT(1)
|
||||
+#define REALTEK_AUX_MDIO_READ 0
|
||||
+#define REALTEK_AUX_MDIO_EXEC BIT(0)
|
||||
+
|
||||
+struct realtek_aux_mdio_info {
|
||||
+ unsigned int cmd_reg;
|
||||
+ unsigned int data_offset;
|
||||
+ unsigned int rcmd_fail_mask;
|
||||
+ unsigned int timeout_us;
|
||||
+};
|
||||
+
|
||||
+static const struct realtek_aux_mdio_info info_rtl838x = {
|
||||
+ .cmd_reg = RTL8380_EXT_GPIO_INDIRECT_ACCESS,
|
||||
+ .data_offset = RTL83XX_AUX_MDIO_DATA_OFFSET,
|
||||
+ .rcmd_fail_mask = RTL83XX_AUX_MDIO_RCMD_FAIL,
|
||||
+ .timeout_us = 1700,
|
||||
+};
|
||||
+
|
||||
+static const struct realtek_aux_mdio_info info_rtl839x = {
|
||||
+ .cmd_reg = RTL8390_EXT_GPIO_INDIRECT_ACCESS,
|
||||
+ .data_offset = RTL83XX_AUX_MDIO_DATA_OFFSET,
|
||||
+ .rcmd_fail_mask = RTL83XX_AUX_MDIO_RCMD_FAIL,
|
||||
+ .timeout_us = 4120,
|
||||
+};
|
||||
+
|
||||
+static const struct realtek_aux_mdio_info info_rtl930x = {
|
||||
+ .cmd_reg = RTL9300_EXT_GPIO_INDIRECT_ACCESS,
|
||||
+ .data_offset = RTL93XX_AUX_MDIO_DATA_OFFSET,
|
||||
+ .rcmd_fail_mask = RTL93XX_AUX_MDIO_RCMD_FAIL,
|
||||
+ .timeout_us = 19000,
|
||||
+};
|
||||
+
|
||||
+struct realtek_aux_mdio_ctrl {
|
||||
+ struct device *dev;
|
||||
+ struct regmap *map;
|
||||
+ unsigned int cmd_reg;
|
||||
+ const struct realtek_aux_mdio_info *info;
|
||||
+};
|
||||
+
|
||||
+#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,
|
||||
+static int realtek_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);
|
||||
+ cmd = rw_bit | REALTEK_AUX_MDIO_EXEC;
|
||||
+ cmd |= FIELD_PREP(REALTEK_AUX_MDIO_PHY_ADDR, addr);
|
||||
+ cmd |= FIELD_PREP(REALTEK_AUX_MDIO_REG, regnum);
|
||||
+
|
||||
+ mask_volatile = RTL83XX_AUX_MDIO_EXEC;
|
||||
+ if (rw_bit == REALTEK_AUX_MDIO_WRITE)
|
||||
+ cmd |= *data << ctrl->info->data_offset;
|
||||
+
|
||||
+ 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);
|
||||
+ err = regmap_write(ctrl->map, ctrl->info->cmd_reg, cmd);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = regmap_read_poll_timeout_atomic(ctrl->map, ctrl->cmd_reg, run, (run != cmd), 3, 100);
|
||||
+ err = regmap_read_poll_timeout_atomic(ctrl->map, ctrl->info->cmd_reg, cmd,
|
||||
+ !(cmd & REALTEK_AUX_MDIO_EXEC), 3, ctrl->info->timeout_us);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ if ((run & ~mask_volatile) != (cmd & ~mask_volatile)) {
|
||||
+ dev_err(ctrl->dev, "Command modified. Is offloading still active?");
|
||||
+ return -EIO;
|
||||
+ if (rw_bit == REALTEK_AUX_MDIO_READ) {
|
||||
+ if (cmd & ctrl->info->rcmd_fail_mask)
|
||||
+ return -EIO;
|
||||
+
|
||||
+ *data = (cmd >> ctrl->info->data_offset) & GENMASK(15, 0);
|
||||
+ }
|
||||
+
|
||||
+ if (!err && (rw_bit == RTL83XX_AUX_MDIO_READ))
|
||||
+ *data = FIELD_GET(RTL83XX_AUX_MDIO_DATA, run);
|
||||
+
|
||||
+ return err;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int rtl83xx_aux_mdio_read(struct mii_bus *bus, int addr, int regnum)
|
||||
+static int realtek_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);
|
||||
+ err = realtek_aux_mdio_cmd(ctrl, addr, regnum, REALTEK_AUX_MDIO_READ, &data);
|
||||
+
|
||||
+ if (err)
|
||||
+ return err;
|
||||
@ -130,11 +160,11 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
+ return data;
|
||||
+}
|
||||
+
|
||||
+static int rtl83xx_aux_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
|
||||
+static int realtek_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);
|
||||
+ return realtek_aux_mdio_cmd(ctrl, addr, regnum, REALTEK_AUX_MDIO_WRITE, &val);
|
||||
+}
|
||||
+
|
||||
+static int realtek_aux_mdio_probe(struct platform_device *pdev)
|
||||
@ -149,16 +179,16 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
+
|
||||
+ ctrl = bus->priv;
|
||||
+ ctrl->dev = &pdev->dev;
|
||||
+ ctrl->cmd_reg = (unsigned int) device_get_match_data(ctrl->dev);
|
||||
+ ctrl->info = (const struct realtek_aux_mdio_info *) 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->name = "Realtek auxiliary MDIO bus";
|
||||
+ snprintf(bus->id, MII_BUS_ID_SIZE, "realtek-aux-mdio") ;
|
||||
+ bus->parent = ctrl->dev;
|
||||
+ bus->read = rtl83xx_aux_mdio_read;
|
||||
+ bus->write = rtl83xx_aux_mdio_write;
|
||||
+ bus->read = realtek_aux_mdio_read;
|
||||
+ bus->write = realtek_aux_mdio_write;
|
||||
+ /* Don't have interrupts */
|
||||
+ for (unsigned int i = 0; i < PHY_MAX_ADDR; i++)
|
||||
+ bus->irq[i] = PHY_POLL;
|
||||
@ -169,11 +199,15 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
+static const struct of_device_id realtek_aux_mdio_of_match[] = {
|
||||
+ {
|
||||
+ .compatible = "realtek,rtl8380-aux-mdio",
|
||||
+ .data = (void *) RTL8380_EXT_GPIO_INDIRECT_ACCESS,
|
||||
+ .data = &info_rtl838x,
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "realtek,rtl8390-aux-mdio",
|
||||
+ .data = (void *) RTL8390_EXT_GPIO_INDIRECT_ACCESS,
|
||||
+ .data = &info_rtl839x,
|
||||
+ },
|
||||
+ {
|
||||
+ .compatible = "realtek,rtl9300-aux-mdio",
|
||||
+ .data = &info_rtl930x,
|
||||
+ },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
@ -189,5 +223,5 @@ Signed-off-by: Sander Vanheule <sander@svanheule.net>
|
||||
+module_platform_driver(realtek_aux_mdio_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
|
||||
+MODULE_DESCRIPTION("Realtek RTL83xx auxiliary MDIO bus");
|
||||
+MODULE_DESCRIPTION("Realtek otto auxiliary MDIO bus");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
|
Loading…
Reference in New Issue
Block a user