forked from immortalwrt/immortalwrt
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
13 changed files
with
1,729 additions
and
46 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
193 changes: 193 additions & 0 deletions
193
target/linux/realtek/patches-6.6/723-net-mdio-Add-Realtek-Otto-auxiliary-controller.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
From c7ddb74c981c1a29bad82d555d08724aca93b687 Mon Sep 17 00:00:00 2001 | ||
From: Sander Vanheule <[email protected]> | ||
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 <[email protected]> | ||
--- | ||
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 <[email protected]>"); | ||
+MODULE_DESCRIPTION("Realtek RTL83xx auxiliary MDIO bus"); | ||
+MODULE_LICENSE("GPL v2"); |
56 changes: 56 additions & 0 deletions
56
target/linux/realtek/patches-6.6/800-gpio-regmap-Bypass-cache-for-shadowed-outputs.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
From b3f79468c90d8770f007d628a1e32b2d5d44a5c2 Mon Sep 17 00:00:00 2001 | ||
From: Sander Vanheule <[email protected]> | ||
Date: Sat, 15 May 2021 11:57:32 +0200 | ||
Subject: [PATCH] gpio: regmap: Bypass cache for shadowed outputs | ||
|
||
Some chips have the read-only input and write-only output data registers | ||
aliased to the same offset, but do not perform direction multiplexing on | ||
writes. Upon writing the register, this then always updates the output | ||
value, even when the pin is configured as input. As a result it is not | ||
safe to perform read-modify-writes on output pins, when other pins are | ||
still configured as input. | ||
|
||
For example, on a bit-banged I2C bus, where the lines are switched | ||
between out-low and in (with external pull-up) | ||
|
||
OUT(L) IN OUT(H) | ||
SCK ....../''''''|'''''' | ||
|
||
SDA '''''''''\.......... | ||
^ ^- SCK switches to direction to OUT, but now has a high | ||
| value, breaking the clock. | ||
| | ||
\- Perform RMW to update SDA. This reads the current input | ||
value for SCK, updates the SDA value and writes back a 1 | ||
for SCK as well. | ||
|
||
If a register is used for both the data input and data output (and is | ||
not marked as volatile) the driver should ensure the cache is not | ||
updated on register reads. This ensures proper functioning of writing | ||
the output register with regmap_update_bits(), which will then use and | ||
update the cache only on register writes. | ||
|
||
Signed-off-by: Sander Vanheule <[email protected]> | ||
--- | ||
drivers/gpio/gpio-regmap.c | 10 +++++++++- | ||
1 file changed, 9 insertions(+), 1 deletion(-) | ||
|
||
--- a/drivers/gpio/gpio-regmap.c | ||
+++ b/drivers/gpio/gpio-regmap.c | ||
@@ -74,7 +74,15 @@ static int gpio_regmap_get(struct gpio_c | ||
if (ret) | ||
return ret; | ||
|
||
- ret = regmap_read(gpio->regmap, reg, &val); | ||
+ /* | ||
+ * Ensure we don't spoil the register cache with pin input values and | ||
+ * perform a bypassed read. This way the cache (if any) is only used and | ||
+ * updated on register writes. | ||
+ */ | ||
+ if (gpio->reg_dat_base == gpio->reg_set_base) | ||
+ ret = regmap_read_bypassed(gpio->regmap, reg, &val); | ||
+ else | ||
+ ret = regmap_read(gpio->regmap, reg, &val); | ||
if (ret) | ||
return ret; | ||
|
Oops, something went wrong.