From b410f2216c7a4e6c5646f999d18b952b63c85817 Mon Sep 17 00:00:00 2001 From: Sander Vanheule Date: Tue, 28 Jan 2025 08:14:03 +0100 Subject: [PATCH] realtek: drop old RTL8231 driver The old RTL8231 driver integrated the MDIO bus access with the GPIO control ops, making this driver not very portable to newer platforms. It depended on the SoC ID instead of the compatible to determine the MDIO access register, further complicating portability. A new MFD driver is now available, which offers proper pin config as well as optional LED support, which can work on any (bitbanged) MDIO bus. Now that all devices have been migrated, we can drop the old code. Signed-off-by: Sander Vanheule --- .../files-6.6/drivers/gpio/gpio-rtl8231.c | 364 ------------------ .../301-gpio-add-rtl8231-driver.patch | 50 --- 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 - 6 files changed, 418 deletions(-) delete mode 100644 target/linux/realtek/files-6.6/drivers/gpio/gpio-rtl8231.c delete mode 100644 target/linux/realtek/patches-6.6/301-gpio-add-rtl8231-driver.patch diff --git a/target/linux/realtek/files-6.6/drivers/gpio/gpio-rtl8231.c b/target/linux/realtek/files-6.6/drivers/gpio/gpio-rtl8231.c deleted file mode 100644 index 2821591a97ed9d..00000000000000 --- a/target/linux/realtek/files-6.6/drivers/gpio/gpio-rtl8231.c +++ /dev/null @@ -1,364 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include -#include -#include -#include -#include - -/* RTL8231 registers for LED control */ -#define RTL8231_LED_FUNC0 0x0000 -#define RTL8231_LED_FUNC1 0x0001 -#define RTL8231_READY_MASK 0x03f0 -#define RTL8231_READY_VALUE 0x0370 -#define RTL8231_GPIO_PIN_SEL(gpio) ((0x0002) + ((gpio) >> 4)) -#define RTL8231_GPIO_DIR(gpio) ((0x0005) + ((gpio) >> 4)) -#define RTL8231_GPIO_DATA(gpio) ((0x001C) + ((gpio) >> 4)) - -#define USEC_TIMEOUT 5000 - -#define RTL8231_SMI_BUS_ID_MAX 0x1F - -struct rtl8231_gpios { - struct gpio_chip gc; - struct device *dev; - u32 id; - u32 smi_bus_id; - u16 reg_shadow[0x20]; - u32 reg_cached; - int ext_gpio_indrt_access; -}; - -extern struct rtl83xx_soc_info soc_info; - -DEFINE_MUTEX(miim_lock); - -static u32 rtl8231_read(struct rtl8231_gpios *gpios, u32 reg) -{ - u32 t = 0, n = 0; - - reg &= 0x1f; - - /* Calculate read register address */ - t = (gpios->smi_bus_id << 2) | (reg << 7); - - /* Set execution bit: cleared when operation completed */ - t |= 1; - - /* Start execution */ - sw_w32(t, gpios->ext_gpio_indrt_access); - do { - udelay(1); - t = sw_r32(gpios->ext_gpio_indrt_access); - n++; - } while ((t & 1) && (n < USEC_TIMEOUT)); - - if (n >= USEC_TIMEOUT) - return 0x80000000; - - pr_debug("%s: %x, %x, %x\n", __func__, gpios->smi_bus_id, - reg, (t & 0xffff0000) >> 16); - - return (t & 0xffff0000) >> 16; -} - -static int rtl8231_write(struct rtl8231_gpios *gpios, u32 reg, u32 data) -{ - u32 t = 0, n = 0; - - pr_debug("%s: %x, %x, %x\n", __func__, gpios->smi_bus_id, reg, data); - reg &= 0x1f; - - t = (gpios->smi_bus_id << 2) | (reg << 7) | (data << 16); - /* Set write bit */ - t |= 2; - - /* Set execution bit: cleared when operation completed */ - t |= 1; - - /* Start execution */ - sw_w32(t, gpios->ext_gpio_indrt_access); - do { - udelay(1); - t = sw_r32(gpios->ext_gpio_indrt_access); - } while ((t & 1) && (n < USEC_TIMEOUT)); - - if (n >= USEC_TIMEOUT) - return -1; - - return 0; -} - -static u32 rtl8231_read_cached(struct rtl8231_gpios *gpios, u32 reg) -{ - if (reg > 0x1f) - return 0; - - if (gpios->reg_cached & (1 << reg)) - return gpios->reg_shadow[reg]; - - return rtl8231_read(gpios, reg); -} - -/* Set Direction of the RTL8231 pin: - * dir 1: input - * dir 0: output - */ -static int rtl8231_pin_dir(struct rtl8231_gpios *gpios, u32 gpio, u32 dir) -{ - u32 v; - int pin_sel_addr = RTL8231_GPIO_PIN_SEL(gpio); - int pin_dir_addr = RTL8231_GPIO_DIR(gpio); - int dpin = gpio % 16; - - if (gpio > 31) { - pr_debug("WARNING: HIGH pin\n"); - dpin += 5; - pin_dir_addr = pin_sel_addr; - } - - v = rtl8231_read_cached(gpios, pin_dir_addr); - if (v & 0x80000000) { - pr_err("Error reading RTL8231\n"); - return -1; - } - - v = (v & ~(1 << dpin)) | (dir << dpin); - rtl8231_write(gpios, pin_dir_addr, v); - gpios->reg_shadow[pin_dir_addr] = v; - gpios->reg_cached |= 1 << pin_dir_addr; - - return 0; -} - -static int rtl8231_pin_dir_get(struct rtl8231_gpios *gpios, u32 gpio, u32 *dir) -{ - /* dir 1: input - * dir 0: output - */ - - u32 v; - int pin_dir_addr = RTL8231_GPIO_DIR(gpio); - int pin = gpio % 16; - - if (gpio > 31) { - pin_dir_addr = RTL8231_GPIO_PIN_SEL(gpio); - pin += 5; - } - - v = rtl8231_read(gpios, pin_dir_addr); - if (v & (1 << pin)) - *dir = 1; - else - *dir = 0; - - return 0; -} - -static int rtl8231_pin_set(struct rtl8231_gpios *gpios, u32 gpio, u32 data) -{ - u32 v = rtl8231_read(gpios, RTL8231_GPIO_DATA(gpio)); - - pr_debug("%s: %d to %d\n", __func__, gpio, data); - if (v & 0x80000000) { - pr_err("Error reading RTL8231\n"); - return -1; - } - v = (v & ~(1 << (gpio % 16))) | (data << (gpio % 16)); - rtl8231_write(gpios, RTL8231_GPIO_DATA(gpio), v); - gpios->reg_shadow[RTL8231_GPIO_DATA(gpio)] = v; - gpios->reg_cached |= 1 << RTL8231_GPIO_DATA(gpio); - - return 0; -} - -static int rtl8231_pin_get(struct rtl8231_gpios *gpios, u32 gpio, u16 *state) -{ - u32 v = rtl8231_read(gpios, RTL8231_GPIO_DATA(gpio)); - - if (v & 0x80000000) { - pr_err("Error reading RTL8231\n"); - return -1; - } - - *state = v & 0xffff; - - return 0; -} - -static int rtl8231_direction_input(struct gpio_chip *gc, unsigned int offset) -{ - int err; - struct rtl8231_gpios *gpios = gpiochip_get_data(gc); - - pr_debug("%s: %d\n", __func__, offset); - mutex_lock(&miim_lock); - err = rtl8231_pin_dir(gpios, offset, 1); - mutex_unlock(&miim_lock); - - return err; -} - -static int rtl8231_direction_output(struct gpio_chip *gc, unsigned int offset, int value) -{ - int err; - struct rtl8231_gpios *gpios = gpiochip_get_data(gc); - - pr_debug("%s: %d\n", __func__, offset); - mutex_lock(&miim_lock); - err = rtl8231_pin_dir(gpios, offset, 0); - mutex_unlock(&miim_lock); - - if (!err) - err = rtl8231_pin_set(gpios, offset, value); - - return err; -} - -static int rtl8231_get_direction(struct gpio_chip *gc, unsigned int offset) -{ - u32 v = 0; - struct rtl8231_gpios *gpios = gpiochip_get_data(gc); - - pr_debug("%s: %d\n", __func__, offset); - mutex_lock(&miim_lock); - rtl8231_pin_dir_get(gpios, offset, &v); - mutex_unlock(&miim_lock); - - return v; -} - -static int rtl8231_gpio_get(struct gpio_chip *gc, unsigned int offset) -{ - u16 state = 0; - struct rtl8231_gpios *gpios = gpiochip_get_data(gc); - - mutex_lock(&miim_lock); - rtl8231_pin_get(gpios, offset, &state); - mutex_unlock(&miim_lock); - - if (state & (1 << (offset % 16))) - return 1; - - return 0; -} - -void rtl8231_gpio_set(struct gpio_chip *gc, unsigned int offset, int value) -{ - struct rtl8231_gpios *gpios = gpiochip_get_data(gc); - - rtl8231_pin_set(gpios, offset, value); -} - -int rtl8231_init(struct rtl8231_gpios *gpios) -{ - u32 ret; - - pr_info("%s called, MDIO bus ID: %d\n", __func__, gpios->smi_bus_id); - - gpios->reg_cached = 0; - - if (soc_info.family == RTL8390_FAMILY_ID) { - /* RTL8390: Enable external gpio in global led control register */ - sw_w32_mask(0x7 << 18, 0x4 << 18, RTL839X_LED_GLB_CTRL); - } else if (soc_info.family == RTL8380_FAMILY_ID) { - /* RTL8380: Enable RTL8231 indirect access mode */ - sw_w32_mask(0, 1, RTL838X_EXTRA_GPIO_CTRL); - sw_w32_mask(3, 1, RTL838X_DMY_REG5); - } - - ret = rtl8231_read(gpios, RTL8231_LED_FUNC1); - if ((ret & 0x80000000) || ((ret & RTL8231_READY_MASK) != RTL8231_READY_VALUE)) - return -ENXIO; - - /* Select GPIO functionality and force input direction for pins 0-36 */ - rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(0), 0xffff); - rtl8231_write(gpios, RTL8231_GPIO_DIR(0), 0xffff); - rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(16), 0xffff); - rtl8231_write(gpios, RTL8231_GPIO_DIR(16), 0xffff); - rtl8231_write(gpios, RTL8231_GPIO_PIN_SEL(32), 0x03ff); - - /* Set LED_Start to enable drivers for output mode */ - rtl8231_write(gpios, RTL8231_LED_FUNC0, 1 << 1); - - return 0; -} - -static const struct of_device_id rtl8231_gpio_of_match[] = { - { .compatible = "realtek,rtl8231-gpio" }, - {}, -}; - -MODULE_DEVICE_TABLE(of, rtl8231_gpio_of_match); - -static int rtl8231_gpio_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct device_node *np = dev->of_node; - struct rtl8231_gpios *gpios; - int err; - - pr_info("Probing RTL8231 GPIOs\n"); - - if (!np) { - dev_err(&pdev->dev, "No DT found\n"); - return -EINVAL; - } - - gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); - if (!gpios) - return -ENOMEM; - - gpios->id = soc_info.id; - if (soc_info.family == RTL8380_FAMILY_ID) { - gpios->ext_gpio_indrt_access = RTL838X_EXT_GPIO_INDRT_ACCESS; - } - - if (soc_info.family == RTL8390_FAMILY_ID) { - gpios->ext_gpio_indrt_access = RTL839X_EXT_GPIO_INDRT_ACCESS; - } - - err = of_property_read_u32(np, "indirect-access-bus-id", &gpios->smi_bus_id); - if (!err && gpios->smi_bus_id > RTL8231_SMI_BUS_ID_MAX) - err = -EINVAL; - - if (err) { - dev_err(dev, "invalid or missing indirect-access-bus-id\n"); - return err; - } - - err = rtl8231_init(gpios); - if (err) { - dev_err(dev, "no device found at bus address %d\n", gpios->smi_bus_id); - return err; - } - - gpios->dev = dev; - gpios->gc.base = -1; - gpios->gc.ngpio = 37; - gpios->gc.label = "rtl8231"; - gpios->gc.parent = dev; - gpios->gc.owner = THIS_MODULE; - gpios->gc.can_sleep = true; - - gpios->gc.direction_input = rtl8231_direction_input; - gpios->gc.direction_output = rtl8231_direction_output; - gpios->gc.set = rtl8231_gpio_set; - gpios->gc.get = rtl8231_gpio_get; - gpios->gc.get_direction = rtl8231_get_direction; - - return devm_gpiochip_add_data(dev, &gpios->gc, gpios); -} - -static struct platform_driver rtl8231_gpio_driver = { - .driver = { - .name = "rtl8231-gpio", - .of_match_table = rtl8231_gpio_of_match, - }, - .probe = rtl8231_gpio_probe, -}; - -module_platform_driver(rtl8231_gpio_driver); - -MODULE_DESCRIPTION("Realtek RTL8231 GPIO expansion chip support"); -MODULE_LICENSE("GPL v2"); diff --git a/target/linux/realtek/patches-6.6/301-gpio-add-rtl8231-driver.patch b/target/linux/realtek/patches-6.6/301-gpio-add-rtl8231-driver.patch deleted file mode 100644 index f64e2cf94eff8c..00000000000000 --- a/target/linux/realtek/patches-6.6/301-gpio-add-rtl8231-driver.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001 -From: John Crispin -Date: Thu, 26 Nov 2020 12:02:21 +0100 -Subject: [PATCH] realtek: update the tree to the latest refactored version -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -* rename the target to realtek -* add refactored DSA driver -* add latest gpio driver -* lots of arch cleanups -* new irq driver -* additional boards - -Submitted-by: Bert Vermeulen -Submitted-by: Birger Koblitz -Submitted-by: Sander Vanheule -Submitted-by: Bjørn Mork -Submitted-by: John Crispin ---- - drivers/gpio/Kconfig | 6 ++++++ - drivers/gpio/Makefile | 1 + - 2 files changed, 7 insertions(+) - ---- a/drivers/gpio/Kconfig -+++ b/drivers/gpio/Kconfig -@@ -553,6 +553,12 @@ config GPIO_ROCKCHIP - help - Say yes here to support GPIO on Rockchip SoCs. - -+config GPIO_RTL8231 -+ tristate "RTL8231 GPIO" -+ depends on MACH_REALTEK_RTL -+ help -+ Say yes here to support Realtek RTL8231 GPIO expansion chips. -+ - config GPIO_SAMA5D2_PIOBU - tristate "SAMA5D2 PIOBU GPIO support" - depends on MFD_SYSCON ---- a/drivers/gpio/Makefile -+++ b/drivers/gpio/Makefile -@@ -138,6 +138,7 @@ obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc3 - obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o - obj-$(CONFIG_GPIO_REG) += gpio-reg.o - obj-$(CONFIG_GPIO_ROCKCHIP) += gpio-rockchip.o -+obj-$(CONFIG_GPIO_RTL8231) += gpio-rtl8231.o - obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o - obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o - obj-$(CONFIG_GPIO_SCH311X) += gpio-sch311x.o diff --git a/target/linux/realtek/rtl838x/config-6.6 b/target/linux/realtek/rtl838x/config-6.6 index 3a2dbae8c19ba3..3020e58a680e10 100644 --- a/target/linux/realtek/rtl838x/config-6.6 +++ b/target/linux/realtek/rtl838x/config-6.6 @@ -96,7 +96,6 @@ CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y CONFIG_GPIO_REALTEK_OTTO=y CONFIG_GPIO_REGMAP=y -CONFIG_GPIO_RTL8231=y CONFIG_GPIO_WATCHDOG=y # CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set CONFIG_GRO_CELLS=y diff --git a/target/linux/realtek/rtl839x/config-6.6 b/target/linux/realtek/rtl839x/config-6.6 index b64c46b6137904..9b9bcae6dfacf3 100644 --- a/target/linux/realtek/rtl839x/config-6.6 +++ b/target/linux/realtek/rtl839x/config-6.6 @@ -97,7 +97,6 @@ CONFIG_GPIO_PCA953X=y CONFIG_GPIO_PCA953X_IRQ=y CONFIG_GPIO_REALTEK_OTTO=y CONFIG_GPIO_REGMAP=y -CONFIG_GPIO_RTL8231=y CONFIG_GPIO_WATCHDOG=y # CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set CONFIG_GRO_CELLS=y diff --git a/target/linux/realtek/rtl930x/config-6.6 b/target/linux/realtek/rtl930x/config-6.6 index 4c53682b1b3320..a381e888248fda 100644 --- a/target/linux/realtek/rtl930x/config-6.6 +++ b/target/linux/realtek/rtl930x/config-6.6 @@ -78,7 +78,6 @@ CONFIG_GPIO_CDEV=y CONFIG_GPIO_GENERIC=y CONFIG_GPIO_PCA953X=y CONFIG_GPIO_REALTEK_OTTO=y -CONFIG_GPIO_RTL8231=y CONFIG_GRO_CELLS=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y diff --git a/target/linux/realtek/rtl931x/config-6.6 b/target/linux/realtek/rtl931x/config-6.6 index 716d805e51f73f..c9cd3ddfb4055d 100644 --- a/target/linux/realtek/rtl931x/config-6.6 +++ b/target/linux/realtek/rtl931x/config-6.6 @@ -83,7 +83,6 @@ CONFIG_GPIOLIB_IRQCHIP=y CONFIG_GPIO_CDEV=y CONFIG_GPIO_GENERIC=y CONFIG_GPIO_REALTEK_OTTO=y -CONFIG_GPIO_RTL8231=y CONFIG_GRO_CELLS=y CONFIG_HARDWARE_WATCHPOINTS=y CONFIG_HAS_DMA=y