aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/realtek/patches-5.10
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/realtek/patches-5.10')
-rw-r--r--target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch103
-rw-r--r--target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch394
-rw-r--r--target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch57
-rw-r--r--target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch248
-rw-r--r--target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch78
-rw-r--r--target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch211
-rw-r--r--target/linux/realtek/patches-5.10/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch22
-rw-r--r--target/linux/realtek/patches-5.10/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch467
-rw-r--r--target/linux/realtek/patches-5.10/020-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch53
-rw-r--r--target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch123
-rw-r--r--target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch153
-rw-r--r--target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch29
-rw-r--r--target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch30
-rw-r--r--target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch97
-rw-r--r--target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch50
-rw-r--r--target/linux/realtek/patches-5.10/302-clocksource-add-otto-driver.patch93
-rw-r--r--target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch25
-rw-r--r--target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch25
-rw-r--r--target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch22
-rw-r--r--target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch32
-rw-r--r--target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch28
-rw-r--r--target/linux/realtek/patches-5.10/309-cevt-rtl9300-support.patch54
-rw-r--r--target/linux/realtek/patches-5.10/310-add-i2c-rtl9300-support.patch46
-rw-r--r--target/linux/realtek/patches-5.10/311-add-i2c-mux-rtl9300-support.patch46
-rw-r--r--target/linux/realtek/patches-5.10/315-irqchip-irq-realtek-rtl-add-VPE-support.patch407
-rw-r--r--target/linux/realtek/patches-5.10/316-otto-gpio-uniprocessor-irq-mask.patch51
-rw-r--r--target/linux/realtek/patches-5.10/317-gpio-realtek-otto-switch-to-32-bit-I-O.patch373
-rw-r--r--target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch33
-rw-r--r--target/linux/realtek/patches-5.10/319-irqchip-irq-realtek-rtl-fix-VPE-affinity.patch159
-rw-r--r--target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch40
-rw-r--r--target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch61
-rw-r--r--target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch32
-rw-r--r--target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch48
-rw-r--r--target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch34
-rw-r--r--target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch61
-rw-r--r--target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch33
-rw-r--r--target/linux/realtek/patches-5.10/705-add-rtl-phy.patch39
-rw-r--r--target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch32
-rw-r--r--target/linux/realtek/patches-5.10/708-brflood-api.patch162
-rw-r--r--target/linux/realtek/patches-5.10/709-lag-offloading.patch781
-rw-r--r--target/linux/realtek/patches-5.10/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch26
-rw-r--r--target/linux/realtek/patches-5.10/711-net-phy-add-an-MDIO-SMBus-library.patch168
-rw-r--r--target/linux/realtek/patches-5.10/712-net-phy-sfp-add-support-for-SMBus.patch99
-rw-r--r--target/linux/realtek/patches-5.10/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch148
-rw-r--r--target/linux/realtek/patches-5.10/800-net-mdio-support-hardware-assisted-indirect-access.patch840
45 files changed, 0 insertions, 6113 deletions
diff --git a/target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch b/target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch
deleted file mode 100644
index 80b806d89f..0000000000
--- a/target/linux/realtek/patches-5.10/001-5.13-dt-bindings-gpio-binding-for-realtek-otto-gpio.patch
+++ /dev/null
@@ -1,103 +0,0 @@
-From a362c0ce64866939c3daa17c76943cfed555b065 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Tue, 30 Mar 2021 19:48:42 +0200
-Subject: dt-bindings: gpio: Binding for Realtek Otto GPIO
-
-Add a binding description for Realtek's GPIO controller found on several
-of their MIPS-based SoCs (codenamed Otto), such as the RTL838x and
-RTL839x series of switch SoCs.
-
-A fallback binding 'realtek,otto-gpio' is provided for cases where the
-actual port ordering is not known yet, and enabling the interrupt
-controller may result in uncaught interrupts.
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
-Reviewed-by: Rob Herring <robh@kernel.org>
-Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
----
- .../bindings/gpio/realtek,otto-gpio.yaml | 78 ++++++++++++++++++++++
- 1 file changed, 78 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/gpio/realtek,otto-gpio.yaml
-@@ -0,0 +1,78 @@
-+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/gpio/realtek,otto-gpio.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Realtek Otto GPIO controller
-+
-+maintainers:
-+ - Sander Vanheule <sander@svanheule.net>
-+ - Bert Vermeulen <bert@biot.com>
-+
-+description: |
-+ Realtek's GPIO controller on their MIPS switch SoCs (Otto platform) consists
-+ of two banks of 32 GPIOs. These GPIOs can generate edge-triggered interrupts.
-+ Each bank's interrupts are cascased into one interrupt line on the parent
-+ interrupt controller, if provided.
-+ This binding allows defining a single bank in the devicetree. The interrupt
-+ controller is not supported on the fallback compatible name, which only
-+ allows for GPIO port use.
-+
-+properties:
-+ $nodename:
-+ pattern: "^gpio@[0-9a-f]+$"
-+
-+ compatible:
-+ items:
-+ - enum:
-+ - realtek,rtl8380-gpio
-+ - realtek,rtl8390-gpio
-+ - const: realtek,otto-gpio
-+
-+ reg:
-+ maxItems: 1
-+
-+ "#gpio-cells":
-+ const: 2
-+
-+ gpio-controller: true
-+
-+ ngpios:
-+ minimum: 1
-+ maximum: 32
-+
-+ interrupt-controller: true
-+
-+ "#interrupt-cells":
-+ const: 2
-+
-+ interrupts:
-+ maxItems: 1
-+
-+required:
-+ - compatible
-+ - reg
-+ - "#gpio-cells"
-+ - gpio-controller
-+
-+additionalProperties: false
-+
-+dependencies:
-+ interrupt-controller: [ interrupts ]
-+
-+examples:
-+ - |
-+ gpio@3500 {
-+ compatible = "realtek,rtl8380-gpio", "realtek,otto-gpio";
-+ reg = <0x3500 0x1c>;
-+ gpio-controller;
-+ #gpio-cells = <2>;
-+ ngpios = <24>;
-+ interrupt-controller;
-+ #interrupt-cells = <2>;
-+ interrupt-parent = <&rtlintc>;
-+ interrupts = <23>;
-+ };
-+
-+...
diff --git a/target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch b/target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch
deleted file mode 100644
index 62e4338cbb..0000000000
--- a/target/linux/realtek/patches-5.10/002-5.13-gpio-add-realtek-otto-gpio-support.patch
+++ /dev/null
@@ -1,394 +0,0 @@
-From f0f7d662e8514169c90d3d84cd6df773b2983088 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Tue, 30 Mar 2021 19:48:43 +0200
-Subject: gpio: Add Realtek Otto GPIO support
-
-Realtek MIPS SoCs (platform name Otto) have GPIO controllers with up to
-64 GPIOs, divided over two banks. Each bank has a set of registers for
-32 GPIOs, with support for edge-triggered interrupts.
-
-Each GPIO bank consists of four 8-bit GPIO ports (ABCD and EFGH). Most
-registers pack one bit per GPIO, except for the IMR register, which
-packs two bits per GPIO (AB-CD).
-
-Although the byte order is currently assumed to have port A..D at offset
-0x0..0x3, this has been observed to be reversed on other, Lexra-based,
-SoCs (e.g. RTL8196E/97D/97F).
-
-Interrupt support is disabled for the fallback devicetree-compatible
-'realtek,otto-gpio'. This allows for quick support of GPIO banks in
-which the byte order would be unknown. In this case, the port ordering
-in the IMR registers may not match the reversed order in the other
-registers (DCBA, and BA-DC or DC-BA).
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
-Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
-Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com>
----
- drivers/gpio/Kconfig | 13 ++
- drivers/gpio/Makefile | 1 +
- drivers/gpio/gpio-realtek-otto.c | 325 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 339 insertions(+)
- create mode 100644 drivers/gpio/gpio-realtek-otto.c
-
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -489,6 +489,19 @@ config GPIO_RDA
- help
- Say Y here to support RDA Micro GPIO controller.
-
-+config GPIO_REALTEK_OTTO
-+ tristate "Realtek Otto GPIO support"
-+ depends on MACH_REALTEK_RTL
-+ default MACH_REALTEK_RTL
-+ select GPIO_GENERIC
-+ select GPIOLIB_IRQCHIP
-+ help
-+ The GPIO controller on the Otto MIPS platform supports up to two
-+ banks of 32 GPIOs, with edge triggered interrupts. The 32 GPIOs
-+ are grouped in four 8-bit wide ports.
-+
-+ When built as a module, the module will be called realtek_otto_gpio.
-+
- config GPIO_REG
- bool
- help
---- a/drivers/gpio/Makefile
-+++ b/drivers/gpio/Makefile
-@@ -125,6 +125,7 @@ obj-$(CONFIG_GPIO_RC5T583) += gpio-rc5t
- obj-$(CONFIG_GPIO_RCAR) += gpio-rcar.o
- obj-$(CONFIG_GPIO_RDA) += gpio-rda.o
- obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
-+obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
- obj-$(CONFIG_GPIO_REG) += gpio-reg.o
- obj-$(CONFIG_ARCH_SA1100) += gpio-sa1100.o
- obj-$(CONFIG_GPIO_SAMA5D2_PIOBU) += gpio-sama5d2-piobu.o
---- /dev/null
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -0,0 +1,325 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+
-+#include <linux/gpio/driver.h>
-+#include <linux/irq.h>
-+#include <linux/minmax.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/property.h>
-+
-+/*
-+ * Total register block size is 0x1C for one bank of four ports (A, B, C, D).
-+ * An optional second bank, with ports E, F, G, and H, may be present, starting
-+ * at register offset 0x1C.
-+ */
-+
-+/*
-+ * Pin select: (0) "normal", (1) "dedicate peripheral"
-+ * Not used on RTL8380/RTL8390, peripheral selection is managed by control bits
-+ * in the peripheral registers.
-+ */
-+#define REALTEK_GPIO_REG_CNR 0x00
-+/* Clear bit (0) for input, set bit (1) for output */
-+#define REALTEK_GPIO_REG_DIR 0x08
-+#define REALTEK_GPIO_REG_DATA 0x0C
-+/* Read bit for IRQ status, write 1 to clear IRQ */
-+#define REALTEK_GPIO_REG_ISR 0x10
-+/* Two bits per GPIO in IMR registers */
-+#define REALTEK_GPIO_REG_IMR 0x14
-+#define REALTEK_GPIO_REG_IMR_AB 0x14
-+#define REALTEK_GPIO_REG_IMR_CD 0x18
-+#define REALTEK_GPIO_IMR_LINE_MASK GENMASK(1, 0)
-+#define REALTEK_GPIO_IRQ_EDGE_FALLING 1
-+#define REALTEK_GPIO_IRQ_EDGE_RISING 2
-+#define REALTEK_GPIO_IRQ_EDGE_BOTH 3
-+
-+#define REALTEK_GPIO_MAX 32
-+#define REALTEK_GPIO_PORTS_PER_BANK 4
-+
-+/**
-+ * realtek_gpio_ctrl - Realtek Otto GPIO driver data
-+ *
-+ * @gc: Associated gpio_chip instance
-+ * @base: Base address of the register block for a GPIO bank
-+ * @lock: Lock for accessing the IRQ registers and values
-+ * @intr_mask: Mask for interrupts lines
-+ * @intr_type: Interrupt type selection
-+ *
-+ * Because the interrupt mask register (IMR) combines the function of IRQ type
-+ * selection and masking, two extra values are stored. @intr_mask is used to
-+ * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
-+ * the selected interrupt types. The logical AND of these values is written to
-+ * IMR on changes.
-+ */
-+struct realtek_gpio_ctrl {
-+ struct gpio_chip gc;
-+ void __iomem *base;
-+ raw_spinlock_t lock;
-+ u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
-+ u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
-+};
-+
-+/* Expand with more flags as devices with other quirks are added */
-+enum realtek_gpio_flags {
-+ /*
-+ * Allow disabling interrupts, for cases where the port order is
-+ * unknown. This may result in a port mismatch between ISR and IMR.
-+ * An interrupt would appear to come from a different line than the
-+ * line the IRQ handler was assigned to, causing uncaught interrupts.
-+ */
-+ GPIO_INTERRUPTS_DISABLED = BIT(0),
-+};
-+
-+static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
-+{
-+ struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
-+
-+ return container_of(gc, struct realtek_gpio_ctrl, gc);
-+}
-+
-+/*
-+ * Normal port order register access
-+ *
-+ * Port information is stored with the first port at offset 0, followed by the
-+ * second, etc. Most registers store one bit per GPIO and use a u8 value per
-+ * port. The two interrupt mask registers store two bits per GPIO, so use u16
-+ * values.
-+ */
-+static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
-+ unsigned int port, u16 irq_type, u16 irq_mask)
-+{
-+ iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
-+}
-+
-+static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
-+ unsigned int port, u8 mask)
-+{
-+ iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
-+}
-+
-+static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
-+{
-+ return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
-+}
-+
-+/* Set the rising and falling edge mask bits for a GPIO port pin */
-+static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
-+{
-+ return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
-+}
-+
-+static void realtek_gpio_irq_ack(struct irq_data *data)
-+{
-+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
-+ irq_hw_number_t line = irqd_to_hwirq(data);
-+ unsigned int port = line / 8;
-+ unsigned int port_pin = line % 8;
-+
-+ realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
-+}
-+
-+static void realtek_gpio_irq_unmask(struct irq_data *data)
-+{
-+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
-+ unsigned int line = irqd_to_hwirq(data);
-+ unsigned int port = line / 8;
-+ unsigned int port_pin = line % 8;
-+ unsigned long flags;
-+ u16 m;
-+
-+ raw_spin_lock_irqsave(&ctrl->lock, flags);
-+ m = ctrl->intr_mask[port];
-+ m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-+ ctrl->intr_mask[port] = m;
-+ realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
-+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-+}
-+
-+static void realtek_gpio_irq_mask(struct irq_data *data)
-+{
-+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
-+ unsigned int line = irqd_to_hwirq(data);
-+ unsigned int port = line / 8;
-+ unsigned int port_pin = line % 8;
-+ unsigned long flags;
-+ u16 m;
-+
-+ raw_spin_lock_irqsave(&ctrl->lock, flags);
-+ m = ctrl->intr_mask[port];
-+ m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-+ ctrl->intr_mask[port] = m;
-+ realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
-+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-+}
-+
-+static int realtek_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
-+{
-+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
-+ unsigned int line = irqd_to_hwirq(data);
-+ unsigned int port = line / 8;
-+ unsigned int port_pin = line % 8;
-+ unsigned long flags;
-+ u16 type, t;
-+
-+ switch (flow_type & IRQ_TYPE_SENSE_MASK) {
-+ case IRQ_TYPE_EDGE_FALLING:
-+ type = REALTEK_GPIO_IRQ_EDGE_FALLING;
-+ break;
-+ case IRQ_TYPE_EDGE_RISING:
-+ type = REALTEK_GPIO_IRQ_EDGE_RISING;
-+ break;
-+ case IRQ_TYPE_EDGE_BOTH:
-+ type = REALTEK_GPIO_IRQ_EDGE_BOTH;
-+ break;
-+ default:
-+ return -EINVAL;
-+ }
-+
-+ irq_set_handler_locked(data, handle_edge_irq);
-+
-+ raw_spin_lock_irqsave(&ctrl->lock, flags);
-+ t = ctrl->intr_type[port];
-+ t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-+ t |= realtek_gpio_imr_bits(port_pin, type);
-+ ctrl->intr_type[port] = t;
-+ realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
-+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-+
-+ return 0;
-+}
-+
-+static void realtek_gpio_irq_handler(struct irq_desc *desc)
-+{
-+ struct gpio_chip *gc = irq_desc_get_handler_data(desc);
-+ struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
-+ struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-+ unsigned int lines_done;
-+ unsigned int port_pin_count;
-+ unsigned int irq;
-+ unsigned long status;
-+ int offset;
-+
-+ chained_irq_enter(irq_chip, desc);
-+
-+ for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
-+ status = realtek_gpio_read_isr(ctrl, lines_done / 8);
-+ port_pin_count = min(gc->ngpio - lines_done, 8U);
-+ for_each_set_bit(offset, &status, port_pin_count) {
-+ irq = irq_find_mapping(gc->irq.domain, offset);
-+ generic_handle_irq(irq);
-+ }
-+ }
-+
-+ chained_irq_exit(irq_chip, desc);
-+}
-+
-+static int realtek_gpio_irq_init(struct gpio_chip *gc)
-+{
-+ struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
-+ unsigned int port;
-+
-+ for (port = 0; (port * 8) < gc->ngpio; port++) {
-+ realtek_gpio_write_imr(ctrl, port, 0, 0);
-+ realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
-+ }
-+
-+ return 0;
-+}
-+
-+static struct irq_chip realtek_gpio_irq_chip = {
-+ .name = "realtek-otto-gpio",
-+ .irq_ack = realtek_gpio_irq_ack,
-+ .irq_mask = realtek_gpio_irq_mask,
-+ .irq_unmask = realtek_gpio_irq_unmask,
-+ .irq_set_type = realtek_gpio_irq_set_type,
-+};
-+
-+static const struct of_device_id realtek_gpio_of_match[] = {
-+ {
-+ .compatible = "realtek,otto-gpio",
-+ .data = (void *)GPIO_INTERRUPTS_DISABLED,
-+ },
-+ {
-+ .compatible = "realtek,rtl8380-gpio",
-+ },
-+ {
-+ .compatible = "realtek,rtl8390-gpio",
-+ },
-+ {}
-+};
-+MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
-+
-+static int realtek_gpio_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ unsigned int dev_flags;
-+ struct gpio_irq_chip *girq;
-+ struct realtek_gpio_ctrl *ctrl;
-+ u32 ngpios;
-+ int err, irq;
-+
-+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
-+ if (!ctrl)
-+ return -ENOMEM;
-+
-+ dev_flags = (unsigned int) device_get_match_data(dev);
-+
-+ ngpios = REALTEK_GPIO_MAX;
-+ device_property_read_u32(dev, "ngpios", &ngpios);
-+
-+ if (ngpios > REALTEK_GPIO_MAX) {
-+ dev_err(&pdev->dev, "invalid ngpios (max. %d)\n",
-+ REALTEK_GPIO_MAX);
-+ return -EINVAL;
-+ }
-+
-+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);
-+ if (IS_ERR(ctrl->base))
-+ return PTR_ERR(ctrl->base);
-+
-+ raw_spin_lock_init(&ctrl->lock);
-+
-+ err = bgpio_init(&ctrl->gc, dev, 4,
-+ ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
-+ ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
-+ BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-+ if (err) {
-+ dev_err(dev, "unable to init generic GPIO");
-+ return err;
-+ }
-+
-+ ctrl->gc.ngpio = ngpios;
-+ ctrl->gc.owner = THIS_MODULE;
-+
-+ irq = platform_get_irq_optional(pdev, 0);
-+ if (!(dev_flags & GPIO_INTERRUPTS_DISABLED) && irq > 0) {
-+ girq = &ctrl->gc.irq;
-+ girq->chip = &realtek_gpio_irq_chip;
-+ girq->default_type = IRQ_TYPE_NONE;
-+ girq->handler = handle_bad_irq;
-+ girq->parent_handler = realtek_gpio_irq_handler;
-+ girq->num_parents = 1;
-+ girq->parents = devm_kcalloc(dev, girq->num_parents,
-+ sizeof(*girq->parents), GFP_KERNEL);
-+ if (!girq->parents)
-+ return -ENOMEM;
-+ girq->parents[0] = irq;
-+ girq->init_hw = realtek_gpio_irq_init;
-+ }
-+
-+ return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
-+}
-+
-+static struct platform_driver realtek_gpio_driver = {
-+ .driver = {
-+ .name = "realtek-otto-gpio",
-+ .of_match_table = realtek_gpio_of_match,
-+ },
-+ .probe = realtek_gpio_probe,
-+};
-+module_platform_driver(realtek_gpio_driver);
-+
-+MODULE_DESCRIPTION("Realtek Otto GPIO support");
-+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
-+MODULE_LICENSE("GPL v2");
diff --git a/target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch b/target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch
deleted file mode 100644
index 325e904994..0000000000
--- a/target/linux/realtek/patches-5.10/003-5.12-spi-realtek-rtl838x-rtl839x-spi-controller.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From 6acbd614c2c8d3b8de5fb7605d6e24b9b3a8a17b Mon Sep 17 00:00:00 2001
-From: Bert Vermeulen <bert@biot.com>
-Date: Wed, 20 Jan 2021 14:59:27 +0100
-Subject: spi: Realtek RTL838x/RTL839x SPI controller
-
-Signed-off-by: Bert Vermeulen <bert@biot.com>
-Link: https://lore.kernel.org/r/20210120135928.246054-2-bert@biot.com
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- .../devicetree/bindings/spi/realtek,rtl-spi.yaml | 41 ++++++++++++++++++++++
- 1 file changed, 41 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/spi/realtek,rtl-spi.yaml
-@@ -0,0 +1,41 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/spi/realtek,rtl-spi.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Realtek RTL838x/RTL839x SPI controller
-+
-+maintainers:
-+ - Bert Vermeulen <bert@biot.com>
-+ - Birger Koblitz <mail@birger-koblitz.de>
-+
-+allOf:
-+ - $ref: "spi-controller.yaml#"
-+
-+properties:
-+ compatible:
-+ oneOf:
-+ - const: realtek,rtl8380-spi
-+ - const: realtek,rtl8382-spi
-+ - const: realtek,rtl8391-spi
-+ - const: realtek,rtl8392-spi
-+ - const: realtek,rtl8393-spi
-+
-+ reg:
-+ maxItems: 1
-+
-+required:
-+ - compatible
-+ - reg
-+
-+unevaluatedProperties: false
-+
-+examples:
-+ - |
-+ spi: spi@1200 {
-+ compatible = "realtek,rtl8382-spi";
-+ reg = <0x1200 0x100>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ };
diff --git a/target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch b/target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch
deleted file mode 100644
index 090847baad..0000000000
--- a/target/linux/realtek/patches-5.10/004-5.12-spi-realtek-rtl-add-support-for-realtek-rtl838x-rtl839x-spi-controllers.patch
+++ /dev/null
@@ -1,248 +0,0 @@
-From a8af5cc2ff1e804694629a8ef320935629dd15ba Mon Sep 17 00:00:00 2001
-From: Bert Vermeulen <bert@biot.com>
-Date: Wed, 20 Jan 2021 14:59:28 +0100
-Subject: spi: realtek-rtl: Add support for Realtek RTL838x/RTL839x SPI
- controllers
-
-This driver likely also supports earlier (RTL8196) and later (RTL93xx)
-SoCs.
-
-The SPI hardware in these SoCs is specifically intended for connecting NOR
-bootflash chips, and only used for that in dozens of examined devices.
-However boiled down to basics, it's really just a half-duplex SPI
-controller.
-
-The hardware appears to have a vestigial second chip-select control, but
-it hasn't been seen in the wild and is thus not supported.
-
-Signed-off-by: Bert Vermeulen <bert@biot.com>
-Link: https://lore.kernel.org/r/20210120135928.246054-3-bert@biot.com
-Signed-off-by: Mark Brown <broonie@kernel.org>
----
- drivers/spi/Makefile | 1 +
- drivers/spi/spi-realtek-rtl.c | 209 ++++++++++++++++++++++++++++++++++++++++++
- 2 files changed, 210 insertions(+)
- create mode 100644 drivers/spi/spi-realtek-rtl.c
-
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -94,6 +94,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom
- obj-$(CONFIG_SPI_QUP) += spi-qup.o
- obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
- obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
-+obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
- obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
- obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
- obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
---- /dev/null
-+++ b/drivers/spi/spi-realtek-rtl.c
-@@ -0,0 +1,209 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/spi/spi.h>
-+
-+struct rtspi {
-+ void __iomem *base;
-+};
-+
-+/* SPI Flash Configuration Register */
-+#define RTL_SPI_SFCR 0x00
-+#define RTL_SPI_SFCR_RBO BIT(28)
-+#define RTL_SPI_SFCR_WBO BIT(27)
-+
-+/* SPI Flash Control and Status Register */
-+#define RTL_SPI_SFCSR 0x08
-+#define RTL_SPI_SFCSR_CSB0 BIT(31)
-+#define RTL_SPI_SFCSR_CSB1 BIT(30)
-+#define RTL_SPI_SFCSR_RDY BIT(27)
-+#define RTL_SPI_SFCSR_CS BIT(24)
-+#define RTL_SPI_SFCSR_LEN_MASK ~(0x03 << 28)
-+#define RTL_SPI_SFCSR_LEN1 (0x00 << 28)
-+#define RTL_SPI_SFCSR_LEN4 (0x03 << 28)
-+
-+/* SPI Flash Data Register */
-+#define RTL_SPI_SFDR 0x0c
-+
-+#define REG(x) (rtspi->base + x)
-+
-+
-+static void rt_set_cs(struct spi_device *spi, bool active)
-+{
-+ struct rtspi *rtspi = spi_controller_get_devdata(spi->controller);
-+ u32 value;
-+
-+ /* CS0 bit is active low */
-+ value = readl(REG(RTL_SPI_SFCSR));
-+ if (active)
-+ value |= RTL_SPI_SFCSR_CSB0;
-+ else
-+ value &= ~RTL_SPI_SFCSR_CSB0;
-+ writel(value, REG(RTL_SPI_SFCSR));
-+}
-+
-+static void set_size(struct rtspi *rtspi, int size)
-+{
-+ u32 value;
-+
-+ value = readl(REG(RTL_SPI_SFCSR));
-+ value &= RTL_SPI_SFCSR_LEN_MASK;
-+ if (size == 4)
-+ value |= RTL_SPI_SFCSR_LEN4;
-+ else if (size == 1)
-+ value |= RTL_SPI_SFCSR_LEN1;
-+ writel(value, REG(RTL_SPI_SFCSR));
-+}
-+
-+static inline void wait_ready(struct rtspi *rtspi)
-+{
-+ while (!(readl(REG(RTL_SPI_SFCSR)) & RTL_SPI_SFCSR_RDY))
-+ cpu_relax();
-+}
-+static void send4(struct rtspi *rtspi, const u32 *buf)
-+{
-+ wait_ready(rtspi);
-+ set_size(rtspi, 4);
-+ writel(*buf, REG(RTL_SPI_SFDR));
-+}
-+
-+static void send1(struct rtspi *rtspi, const u8 *buf)
-+{
-+ wait_ready(rtspi);
-+ set_size(rtspi, 1);
-+ writel(buf[0] << 24, REG(RTL_SPI_SFDR));
-+}
-+
-+static void rcv4(struct rtspi *rtspi, u32 *buf)
-+{
-+ wait_ready(rtspi);
-+ set_size(rtspi, 4);
-+ *buf = readl(REG(RTL_SPI_SFDR));
-+}
-+
-+static void rcv1(struct rtspi *rtspi, u8 *buf)
-+{
-+ wait_ready(rtspi);
-+ set_size(rtspi, 1);
-+ *buf = readl(REG(RTL_SPI_SFDR)) >> 24;
-+}
-+
-+static int transfer_one(struct spi_controller *ctrl, struct spi_device *spi,
-+ struct spi_transfer *xfer)
-+{
-+ struct rtspi *rtspi = spi_controller_get_devdata(ctrl);
-+ void *rx_buf;
-+ const void *tx_buf;
-+ int cnt;
-+
-+ tx_buf = xfer->tx_buf;
-+ rx_buf = xfer->rx_buf;
-+ cnt = xfer->len;
-+ if (tx_buf) {
-+ while (cnt >= 4) {
-+ send4(rtspi, tx_buf);
-+ tx_buf += 4;
-+ cnt -= 4;
-+ }
-+ while (cnt) {
-+ send1(rtspi, tx_buf);
-+ tx_buf++;
-+ cnt--;
-+ }
-+ } else if (rx_buf) {
-+ while (cnt >= 4) {
-+ rcv4(rtspi, rx_buf);
-+ rx_buf += 4;
-+ cnt -= 4;
-+ }
-+ while (cnt) {
-+ rcv1(rtspi, rx_buf);
-+ rx_buf++;
-+ cnt--;
-+ }
-+ }
-+
-+ spi_finalize_current_transfer(ctrl);
-+
-+ return 0;
-+}
-+
-+static void init_hw(struct rtspi *rtspi)
-+{
-+ u32 value;
-+
-+ /* Turn on big-endian byte ordering */
-+ value = readl(REG(RTL_SPI_SFCR));
-+ value |= RTL_SPI_SFCR_RBO | RTL_SPI_SFCR_WBO;
-+ writel(value, REG(RTL_SPI_SFCR));
-+
-+ value = readl(REG(RTL_SPI_SFCSR));
-+ /* Permanently disable CS1, since it's never used */
-+ value |= RTL_SPI_SFCSR_CSB1;
-+ /* Select CS0 for use */
-+ value &= RTL_SPI_SFCSR_CS;
-+ writel(value, REG(RTL_SPI_SFCSR));
-+}
-+
-+static int realtek_rtl_spi_probe(struct platform_device *pdev)
-+{
-+ struct spi_controller *ctrl;
-+ struct rtspi *rtspi;
-+ int err;
-+
-+ ctrl = devm_spi_alloc_master(&pdev->dev, sizeof(*rtspi));
-+ if (!ctrl) {
-+ dev_err(&pdev->dev, "Error allocating SPI controller\n");
-+ return -ENOMEM;
-+ }
-+ platform_set_drvdata(pdev, ctrl);
-+ rtspi = spi_controller_get_devdata(ctrl);
-+
-+ rtspi->base = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
-+ if (IS_ERR(rtspi->base)) {
-+ dev_err(&pdev->dev, "Could not map SPI register address");
-+ return -ENOMEM;
-+ }
-+
-+ init_hw(rtspi);
-+
-+ ctrl->dev.of_node = pdev->dev.of_node;
-+ ctrl->flags = SPI_CONTROLLER_HALF_DUPLEX;
-+ ctrl->set_cs = rt_set_cs;
-+ ctrl->transfer_one = transfer_one;
-+
-+ err = devm_spi_register_controller(&pdev->dev, ctrl);
-+ if (err) {
-+ dev_err(&pdev->dev, "Could not register SPI controller\n");
-+ return -ENODEV;
-+ }
-+
-+ return 0;
-+}
-+
-+
-+static const struct of_device_id realtek_rtl_spi_of_ids[] = {
-+ { .compatible = "realtek,rtl8380-spi" },
-+ { .compatible = "realtek,rtl8382-spi" },
-+ { .compatible = "realtek,rtl8391-spi" },
-+ { .compatible = "realtek,rtl8392-spi" },
-+ { .compatible = "realtek,rtl8393-spi" },
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, realtek_rtl_spi_of_ids);
-+
-+static struct platform_driver realtek_rtl_spi_driver = {
-+ .probe = realtek_rtl_spi_probe,
-+ .driver = {
-+ .name = "realtek-rtl-spi",
-+ .of_match_table = realtek_rtl_spi_of_ids,
-+ },
-+};
-+
-+module_platform_driver(realtek_rtl_spi_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Bert Vermeulen <bert@biot.com>");
-+MODULE_DESCRIPTION("Realtek RTL SPI driver");
diff --git a/target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch b/target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch
deleted file mode 100644
index 165545a220..0000000000
--- a/target/linux/realtek/patches-5.10/005-5.12-dt-bindings-interrupt-controller-add-realtek-rtl838x-rtl839x-support.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From 4a2b92a5d3519fc2c1edda4d4aa0e05bff41e8de Mon Sep 17 00:00:00 2001
-From: Bert Vermeulen <bert@biot.com>
-Date: Fri, 22 Jan 2021 21:42:23 +0100
-Subject: dt-bindings: interrupt-controller: Add Realtek RTL838x/RTL839x
- support
-
-Document the binding for the Realtek RTL838x/RTL839x interrupt controller.
-
-Reviewed-by: Rob Herring <robh@kernel.org>
-Signed-off-by: Bert Vermeulen <bert@biot.com>
-[maz: Add a commit message, as the author couldn't be bothered...]
-Signed-off-by: Marc Zyngier <maz@kernel.org>
-Link: https://lore.kernel.org/r/20210122204224.509124-2-bert@biot.com
----
- .../interrupt-controller/realtek,rtl-intc.yaml | 57 ++++++++++++++++++++++
- 1 file changed, 57 insertions(+)
- create mode 100644 Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
-
---- /dev/null
-+++ b/Documentation/devicetree/bindings/interrupt-controller/realtek,rtl-intc.yaml
-@@ -0,0 +1,57 @@
-+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-+%YAML 1.2
-+---
-+$id: http://devicetree.org/schemas/interrupt-controller/realtek,rtl-intc.yaml#
-+$schema: http://devicetree.org/meta-schemas/core.yaml#
-+
-+title: Realtek RTL SoC interrupt controller devicetree bindings
-+
-+maintainers:
-+ - Birger Koblitz <mail@birger-koblitz.de>
-+ - Bert Vermeulen <bert@biot.com>
-+ - John Crispin <john@phrozen.org>
-+
-+properties:
-+ compatible:
-+ const: realtek,rtl-intc
-+
-+ "#interrupt-cells":
-+ const: 1
-+
-+ reg:
-+ maxItems: 1
-+
-+ interrupts:
-+ maxItems: 1
-+
-+ interrupt-controller: true
-+
-+ "#address-cells":
-+ const: 0
-+
-+ interrupt-map:
-+ description: Describes mapping from SoC interrupts to CPU interrupts
-+
-+required:
-+ - compatible
-+ - reg
-+ - "#interrupt-cells"
-+ - interrupt-controller
-+ - "#address-cells"
-+ - interrupt-map
-+
-+additionalProperties: false
-+
-+examples:
-+ - |
-+ intc: interrupt-controller@3000 {
-+ compatible = "realtek,rtl-intc";
-+ #interrupt-cells = <1>;
-+ interrupt-controller;
-+ reg = <0x3000 0x20>;
-+ #address-cells = <0>;
-+ interrupt-map =
-+ <31 &cpuintc 2>,
-+ <30 &cpuintc 1>,
-+ <29 &cpuintc 5>;
-+ };
diff --git a/target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch b/target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch
deleted file mode 100644
index 753c41eb2f..0000000000
--- a/target/linux/realtek/patches-5.10/006-5.12-irqchip-add-support-for-realtek-rtl838x-rtl839x-interrupt-controller.patch
+++ /dev/null
@@ -1,211 +0,0 @@
-From 9f3a0f34b84ad1b9a8f2bdae44b66f16685b2143 Mon Sep 17 00:00:00 2001
-From: Bert Vermeulen <bert@biot.com>
-Date: Fri, 22 Jan 2021 21:42:24 +0100
-Subject: irqchip: Add support for Realtek RTL838x/RTL839x interrupt controller
-
-This is a standard IRQ driver with only status and mask registers.
-
-The mapping from SoC interrupts (18-31) to MIPS core interrupts is
-done via an interrupt-map in device tree.
-
-Signed-off-by: Bert Vermeulen <bert@biot.com>
-Signed-off-by: Birger Koblitz <mail@birger-koblitz.de>
-Acked-by: John Crispin <john@phrozen.org>
-Signed-off-by: Marc Zyngier <maz@kernel.org>
-Link: https://lore.kernel.org/r/20210122204224.509124-3-bert@biot.com
----
- drivers/irqchip/Makefile | 1 +
- drivers/irqchip/irq-realtek-rtl.c | 180 ++++++++++++++++++++++++++++++++++++++
- 2 files changed, 181 insertions(+)
- create mode 100644 drivers/irqchip/irq-realtek-rtl.c
-
---- a/drivers/irqchip/Makefile
-+++ b/drivers/irqchip/Makefile
-@@ -114,3 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-l
- obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o
- obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o
- obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o
-+obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o
---- /dev/null
-+++ b/drivers/irqchip/irq-realtek-rtl.c
-@@ -0,0 +1,180 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copyright (C) 2020 Birger Koblitz <mail@birger-koblitz.de>
-+ * Copyright (C) 2020 Bert Vermeulen <bert@biot.com>
-+ * Copyright (C) 2020 John Crispin <john@phrozen.org>
-+ */
-+
-+#include <linux/of_irq.h>
-+#include <linux/irqchip.h>
-+#include <linux/spinlock.h>
-+#include <linux/of_address.h>
-+#include <linux/irqchip/chained_irq.h>
-+
-+/* Global Interrupt Mask Register */
-+#define RTL_ICTL_GIMR 0x00
-+/* Global Interrupt Status Register */
-+#define RTL_ICTL_GISR 0x04
-+/* Interrupt Routing Registers */
-+#define RTL_ICTL_IRR0 0x08
-+#define RTL_ICTL_IRR1 0x0c
-+#define RTL_ICTL_IRR2 0x10
-+#define RTL_ICTL_IRR3 0x14
-+
-+#define REG(x) (realtek_ictl_base + x)
-+
-+static DEFINE_RAW_SPINLOCK(irq_lock);
-+static void __iomem *realtek_ictl_base;
-+
-+static void realtek_ictl_unmask_irq(struct irq_data *i)
-+{
-+ unsigned long flags;
-+ u32 value;
-+
-+ raw_spin_lock_irqsave(&irq_lock, flags);
-+
-+ value = readl(REG(RTL_ICTL_GIMR));
-+ value |= BIT(i->hwirq);
-+ writel(value, REG(RTL_ICTL_GIMR));
-+
-+ raw_spin_unlock_irqrestore(&irq_lock, flags);
-+}
-+
-+static void realtek_ictl_mask_irq(struct irq_data *i)
-+{
-+ unsigned long flags;
-+ u32 value;
-+
-+ raw_spin_lock_irqsave(&irq_lock, flags);
-+
-+ value = readl(REG(RTL_ICTL_GIMR));
-+ value &= ~BIT(i->hwirq);
-+ writel(value, REG(RTL_ICTL_GIMR));
-+
-+ raw_spin_unlock_irqrestore(&irq_lock, flags);
-+}
-+
-+static struct irq_chip realtek_ictl_irq = {
-+ .name = "realtek-rtl-intc",
-+ .irq_mask = realtek_ictl_mask_irq,
-+ .irq_unmask = realtek_ictl_unmask_irq,
-+};
-+
-+static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
-+{
-+ irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq);
-+
-+ return 0;
-+}
-+
-+static const struct irq_domain_ops irq_domain_ops = {
-+ .map = intc_map,
-+ .xlate = irq_domain_xlate_onecell,
-+};
-+
-+static void realtek_irq_dispatch(struct irq_desc *desc)
-+{
-+ struct irq_chip *chip = irq_desc_get_chip(desc);
-+ struct irq_domain *domain;
-+ unsigned int pending;
-+
-+ chained_irq_enter(chip, desc);
-+ pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));
-+ if (unlikely(!pending)) {
-+ spurious_interrupt();
-+ goto out;
-+ }
-+ domain = irq_desc_get_handler_data(desc);
-+ generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
-+
-+out:
-+ chained_irq_exit(chip, desc);
-+}
-+
-+/*
-+ * SoC interrupts are cascaded to MIPS CPU interrupts according to the
-+ * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for
-+ * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts
-+ * thus go into 4 IRRs.
-+ */
-+static int __init map_interrupts(struct device_node *node, struct irq_domain *domain)
-+{
-+ struct device_node *cpu_ictl;
-+ const __be32 *imap;
-+ u32 imaplen, soc_int, cpu_int, tmp, regs[4];
-+ int ret, i, irr_regs[] = {
-+ RTL_ICTL_IRR3,
-+ RTL_ICTL_IRR2,
-+ RTL_ICTL_IRR1,
-+ RTL_ICTL_IRR0,
-+ };
-+ u8 mips_irqs_set;
-+
-+ ret = of_property_read_u32(node, "#address-cells", &tmp);
-+ if (ret || tmp)
-+ return -EINVAL;
-+
-+ imap = of_get_property(node, "interrupt-map", &imaplen);
-+ if (!imap || imaplen % 3)
-+ return -EINVAL;
-+
-+ mips_irqs_set = 0;
-+ memset(regs, 0, sizeof(regs));
-+ for (i = 0; i < imaplen; i += 3 * sizeof(u32)) {
-+ soc_int = be32_to_cpup(imap);
-+ if (soc_int > 31)
-+ return -EINVAL;
-+
-+ cpu_ictl = of_find_node_by_phandle(be32_to_cpup(imap + 1));
-+ if (!cpu_ictl)
-+ return -EINVAL;
-+ ret = of_property_read_u32(cpu_ictl, "#interrupt-cells", &tmp);
-+ if (ret || tmp != 1)
-+ return -EINVAL;
-+ of_node_put(cpu_ictl);
-+
-+ cpu_int = be32_to_cpup(imap + 2);
-+ if (cpu_int > 7)
-+ return -EINVAL;
-+
-+ if (!(mips_irqs_set & BIT(cpu_int))) {
-+ irq_set_chained_handler_and_data(cpu_int, realtek_irq_dispatch,
-+ domain);
-+ mips_irqs_set |= BIT(cpu_int);
-+ }
-+
-+ regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32;
-+ imap += 3;
-+ }
-+
-+ for (i = 0; i < 4; i++)
-+ writel(regs[i], REG(irr_regs[i]));
-+
-+ return 0;
-+}
-+
-+static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
-+{
-+ struct irq_domain *domain;
-+ int ret;
-+
-+ realtek_ictl_base = of_iomap(node, 0);
-+ if (!realtek_ictl_base)
-+ return -ENXIO;
-+
-+ /* Disable all cascaded interrupts */
-+ writel(0, REG(RTL_ICTL_GIMR));
-+
-+ domain = irq_domain_add_simple(node, 32, 0,
-+ &irq_domain_ops, NULL);
-+
-+ ret = map_interrupts(node, domain);
-+ if (ret) {
-+ pr_err("invalid interrupt map\n");
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+IRQCHIP_DECLARE(realtek_rtl_intc, "realtek,rtl-intc", realtek_rtl_of_init);
diff --git a/target/linux/realtek/patches-5.10/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch b/target/linux/realtek/patches-5.10/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch
deleted file mode 100644
index 9935c57257..0000000000
--- a/target/linux/realtek/patches-5.10/007-5.16-gpio-realtek-realtek-otto-fix-gpio-line-irq-offset.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From: Sander Vanheule <sander@svanheule.net>
-Subject: gpio: realtek-otto: fix GPIO line IRQ offset
-
-The irqchip uses one domain for all GPIO lines, so th line offset should be
-determined w.r.t. the first line of the first port, not the first line of the
-triggered port.
-
-Fixes: 0d82fb1127fb ("gpio: Add Realtek Otto GPIO support")
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Link: https://lore.kernel.org/linux-gpio/20211028085243.34360-1-sander@svanheule.net/
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -206,7 +206,7 @@ static void realtek_gpio_irq_handler(str
- status = realtek_gpio_read_isr(ctrl, lines_done / 8);
- port_pin_count = min(gc->ngpio - lines_done, 8U);
- for_each_set_bit(offset, &status, port_pin_count) {
-- irq = irq_find_mapping(gc->irq.domain, offset);
-+ irq = irq_find_mapping(gc->irq.domain, offset + lines_done);
- generic_handle_irq(irq);
- }
- }
diff --git a/target/linux/realtek/patches-5.10/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch b/target/linux/realtek/patches-5.10/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch
deleted file mode 100644
index cf93d28f0a..0000000000
--- a/target/linux/realtek/patches-5.10/008-5.17-watchdog-add-realtek-otto-watchdog-timer.patch
+++ /dev/null
@@ -1,467 +0,0 @@
-From 293903b9dfe43520f01374dc1661be11d6838c49 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Thu, 18 Nov 2021 17:29:52 +0100
-Subject: watchdog: Add Realtek Otto watchdog timer
-
-Realtek MIPS SoCs (platform name Otto) have a watchdog timer with
-pretimeout notifitication support. The WDT can (partially) hard reset,
-or soft reset the SoC.
-
-This driver implements all features as described in the devicetree
-binding, except the phase2 interrupt, and also functions as a restart
-handler. The cpu reset mode is considered to be a "warm" restart, since
-this mode does not reset all peripherals. Being an embedded system
-though, the "cpu" and "software" modes will still cause the bootloader
-to run on restart.
-
-It is not known how a forced system reset can be disabled on the
-supported platforms. This means that the phase2 interrupt will only fire
-at the same time as reset, so implementing phase2 is of little use.
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Reviewed-by: Guenter Roeck <linux@roeck-us.net>
-Link: https://lore.kernel.org/r/6d060bccbdcc709cfa79203485db85aad3c3beb5.1637252610.git.sander@svanheule.net
-Signed-off-by: Guenter Roeck <linux@roeck-us.net>
----
- MAINTAINERS | 7 +
- drivers/watchdog/Kconfig | 13 ++
- drivers/watchdog/Makefile | 1 +
- drivers/watchdog/realtek_otto_wdt.c | 384 ++++++++++++++++++++++++++++++++++++
- 4 files changed, 405 insertions(+)
- create mode 100644 drivers/watchdog/realtek_otto_wdt.c
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -14824,6 +14824,13 @@ S: Maintained
- F: include/sound/rt*.h
- F: sound/soc/codecs/rt*
-
-+REALTEK OTTO WATCHDOG
-+M: Sander Vanheule <sander@svanheule.net>
-+L: linux-watchdog@vger.kernel.org
-+S: Maintained
-+F: Documentation/devicetree/bindings/watchdog/realtek,otto-wdt.yaml
-+F: driver/watchdog/realtek_otto_wdt.c
-+
- REALTEK RTL83xx SMI DSA ROUTER CHIPS
- M: Linus Walleij <linus.walleij@linaro.org>
- S: Maintained
---- a/drivers/watchdog/Kconfig
-+++ b/drivers/watchdog/Kconfig
-@@ -995,6 +995,19 @@ config RTD119X_WATCHDOG
- Say Y here to include support for the watchdog timer in
- Realtek RTD1295 SoCs.
-
-+config REALTEK_OTTO_WDT
-+ tristate "Realtek Otto MIPS watchdog support"
-+ depends on MACH_REALTEK_RTL || COMPILE_TEST
-+ depends on COMMON_CLK
-+ select WATCHDOG_CORE
-+ default MACH_REALTEK_RTL
-+ help
-+ Say Y here to include support for the watchdog timer on Realtek
-+ RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout
-+ notifications and system reset on timeout.
-+
-+ When built as a module this will be called realtek_otto_wdt.
-+
- config SPRD_WATCHDOG
- tristate "Spreadtrum watchdog support"
- depends on ARCH_SPRD || COMPILE_TEST
---- a/drivers/watchdog/Makefile
-+++ b/drivers/watchdog/Makefile
-@@ -174,6 +174,7 @@ obj-$(CONFIG_IMGPDC_WDT) += imgpdc_wdt.o
- obj-$(CONFIG_MT7621_WDT) += mt7621_wdt.o
- obj-$(CONFIG_PIC32_WDT) += pic32-wdt.o
- obj-$(CONFIG_PIC32_DMT) += pic32-dmt.o
-+obj-$(CONFIG_REALTEK_OTTO_WDT) += realtek_otto_wdt.o
-
- # PARISC Architecture
-
---- /dev/null
-+++ b/drivers/watchdog/realtek_otto_wdt.c
-@@ -0,0 +1,384 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+
-+/*
-+ * Realtek Otto MIPS platform watchdog
-+ *
-+ * Watchdog timer that will reset the system after timeout, using the selected
-+ * reset mode.
-+ *
-+ * Counter scaling and timeouts:
-+ * - Base prescale of (2 << 25), providing tick duration T_0: 168ms @ 200MHz
-+ * - PRESCALE: logarithmic prescaler adding a factor of {1, 2, 4, 8}
-+ * - Phase 1: Times out after (PHASE1 + 1) × PRESCALE × T_0
-+ * Generates an interrupt, WDT cannot be stopped after phase 1
-+ * - Phase 2: starts after phase 1, times out after (PHASE2 + 1) × PRESCALE × T_0
-+ * Resets the system according to RST_MODE
-+ */
-+
-+#include <linux/bits.h>
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/math.h>
-+#include <linux/minmax.h>
-+#include <linux/module.h>
-+#include <linux/mod_devicetable.h>
-+#include <linux/platform_device.h>
-+#include <linux/property.h>
-+#include <linux/reboot.h>
-+#include <linux/watchdog.h>
-+
-+#define OTTO_WDT_REG_CNTR 0x0
-+#define OTTO_WDT_CNTR_PING BIT(31)
-+
-+#define OTTO_WDT_REG_INTR 0x4
-+#define OTTO_WDT_INTR_PHASE_1 BIT(31)
-+#define OTTO_WDT_INTR_PHASE_2 BIT(30)
-+
-+#define OTTO_WDT_REG_CTRL 0x8
-+#define OTTO_WDT_CTRL_ENABLE BIT(31)
-+#define OTTO_WDT_CTRL_PRESCALE GENMASK(30, 29)
-+#define OTTO_WDT_CTRL_PHASE1 GENMASK(26, 22)
-+#define OTTO_WDT_CTRL_PHASE2 GENMASK(19, 15)
-+#define OTTO_WDT_CTRL_RST_MODE GENMASK(1, 0)
-+#define OTTO_WDT_MODE_SOC 0
-+#define OTTO_WDT_MODE_CPU 1
-+#define OTTO_WDT_MODE_SOFTWARE 2
-+#define OTTO_WDT_CTRL_DEFAULT OTTO_WDT_MODE_CPU
-+
-+#define OTTO_WDT_PRESCALE_MAX 3
-+
-+/*
-+ * One higher than the max values contained in PHASE{1,2}, since a value of 0
-+ * corresponds to one tick.
-+ */
-+#define OTTO_WDT_PHASE_TICKS_MAX 32
-+
-+/*
-+ * The maximum reset delay is actually 2×32 ticks, but that would require large
-+ * pretimeout values for timeouts longer than 32 ticks. Limit the maximum timeout
-+ * to 32 + 1 to ensure small pretimeout values can be configured as expected.
-+ */
-+#define OTTO_WDT_TIMEOUT_TICKS_MAX (OTTO_WDT_PHASE_TICKS_MAX + 1)
-+
-+struct otto_wdt_ctrl {
-+ struct watchdog_device wdev;
-+ struct device *dev;
-+ void __iomem *base;
-+ unsigned int clk_rate_khz;
-+ int irq_phase1;
-+};
-+
-+static int otto_wdt_start(struct watchdog_device *wdev)
-+{
-+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
-+ u32 v;
-+
-+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
-+ v |= OTTO_WDT_CTRL_ENABLE;
-+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ return 0;
-+}
-+
-+static int otto_wdt_stop(struct watchdog_device *wdev)
-+{
-+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
-+ u32 v;
-+
-+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
-+ v &= ~OTTO_WDT_CTRL_ENABLE;
-+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ return 0;
-+}
-+
-+static int otto_wdt_ping(struct watchdog_device *wdev)
-+{
-+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
-+
-+ iowrite32(OTTO_WDT_CNTR_PING, ctrl->base + OTTO_WDT_REG_CNTR);
-+
-+ return 0;
-+}
-+
-+static int otto_wdt_tick_ms(struct otto_wdt_ctrl *ctrl, int prescale)
-+{
-+ return DIV_ROUND_CLOSEST(1 << (25 + prescale), ctrl->clk_rate_khz);
-+}
-+
-+/*
-+ * The timer asserts the PHASE1/PHASE2 IRQs when the number of ticks exceeds
-+ * the value stored in those fields. This means each phase will run for at least
-+ * one tick, so small values need to be clamped to correctly reflect the timeout.
-+ */
-+static inline unsigned int div_round_ticks(unsigned int val, unsigned int tick_duration,
-+ unsigned int min_ticks)
-+{
-+ return max(min_ticks, DIV_ROUND_UP(val, tick_duration));
-+}
-+
-+static int otto_wdt_determine_timeouts(struct watchdog_device *wdev, unsigned int timeout,
-+ unsigned int pretimeout)
-+{
-+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
-+ unsigned int pretimeout_ms = pretimeout * 1000;
-+ unsigned int timeout_ms = timeout * 1000;
-+ unsigned int prescale_next = 0;
-+ unsigned int phase1_ticks;
-+ unsigned int phase2_ticks;
-+ unsigned int total_ticks;
-+ unsigned int prescale;
-+ unsigned int tick_ms;
-+ u32 v;
-+
-+ do {
-+ prescale = prescale_next;
-+ if (prescale > OTTO_WDT_PRESCALE_MAX)
-+ return -EINVAL;
-+
-+ tick_ms = otto_wdt_tick_ms(ctrl, prescale);
-+ total_ticks = div_round_ticks(timeout_ms, tick_ms, 2);
-+ phase1_ticks = div_round_ticks(timeout_ms - pretimeout_ms, tick_ms, 1);
-+ phase2_ticks = total_ticks - phase1_ticks;
-+
-+ prescale_next++;
-+ } while (phase1_ticks > OTTO_WDT_PHASE_TICKS_MAX
-+ || phase2_ticks > OTTO_WDT_PHASE_TICKS_MAX);
-+
-+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ v &= ~(OTTO_WDT_CTRL_PRESCALE | OTTO_WDT_CTRL_PHASE1 | OTTO_WDT_CTRL_PHASE2);
-+ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE1, phase1_ticks - 1);
-+ v |= FIELD_PREP(OTTO_WDT_CTRL_PHASE2, phase2_ticks - 1);
-+ v |= FIELD_PREP(OTTO_WDT_CTRL_PRESCALE, prescale);
-+
-+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ timeout_ms = total_ticks * tick_ms;
-+ ctrl->wdev.timeout = timeout_ms / 1000;
-+
-+ pretimeout_ms = phase2_ticks * tick_ms;
-+ ctrl->wdev.pretimeout = pretimeout_ms / 1000;
-+
-+ return 0;
-+}
-+
-+static int otto_wdt_set_timeout(struct watchdog_device *wdev, unsigned int val)
-+{
-+ return otto_wdt_determine_timeouts(wdev, val, min(wdev->pretimeout, val - 1));
-+}
-+
-+static int otto_wdt_set_pretimeout(struct watchdog_device *wdev, unsigned int val)
-+{
-+ return otto_wdt_determine_timeouts(wdev, wdev->timeout, val);
-+}
-+
-+static int otto_wdt_restart(struct watchdog_device *wdev, unsigned long reboot_mode,
-+ void *data)
-+{
-+ struct otto_wdt_ctrl *ctrl = watchdog_get_drvdata(wdev);
-+ u32 reset_mode;
-+ u32 v;
-+
-+ disable_irq(ctrl->irq_phase1);
-+
-+ switch (reboot_mode) {
-+ case REBOOT_SOFT:
-+ reset_mode = OTTO_WDT_MODE_SOFTWARE;
-+ break;
-+ case REBOOT_WARM:
-+ reset_mode = OTTO_WDT_MODE_CPU;
-+ break;
-+ default:
-+ reset_mode = OTTO_WDT_MODE_SOC;
-+ break;
-+ }
-+
-+ /* Configure for shortest timeout and wait for reset to occur */
-+ v = FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, reset_mode) | OTTO_WDT_CTRL_ENABLE;
-+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ mdelay(3 * otto_wdt_tick_ms(ctrl, 0));
-+
-+ return 0;
-+}
-+
-+static irqreturn_t otto_wdt_phase1_isr(int irq, void *dev_id)
-+{
-+ struct otto_wdt_ctrl *ctrl = dev_id;
-+
-+ iowrite32(OTTO_WDT_INTR_PHASE_1, ctrl->base + OTTO_WDT_REG_INTR);
-+ dev_crit(ctrl->dev, "phase 1 timeout\n");
-+ watchdog_notify_pretimeout(&ctrl->wdev);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static const struct watchdog_ops otto_wdt_ops = {
-+ .owner = THIS_MODULE,
-+ .start = otto_wdt_start,
-+ .stop = otto_wdt_stop,
-+ .ping = otto_wdt_ping,
-+ .set_timeout = otto_wdt_set_timeout,
-+ .set_pretimeout = otto_wdt_set_pretimeout,
-+ .restart = otto_wdt_restart,
-+};
-+
-+static const struct watchdog_info otto_wdt_info = {
-+ .identity = "Realtek Otto watchdog timer",
-+ .options = WDIOF_KEEPALIVEPING |
-+ WDIOF_MAGICCLOSE |
-+ WDIOF_SETTIMEOUT |
-+ WDIOF_PRETIMEOUT,
-+};
-+
-+static void otto_wdt_clock_action(void *data)
-+{
-+ clk_disable_unprepare(data);
-+}
-+
-+static int otto_wdt_probe_clk(struct otto_wdt_ctrl *ctrl)
-+{
-+ struct clk *clk = devm_clk_get(ctrl->dev, NULL);
-+ int ret;
-+
-+ if (IS_ERR(clk))
-+ return dev_err_probe(ctrl->dev, PTR_ERR(clk), "Failed to get clock\n");
-+
-+ ret = clk_prepare_enable(clk);
-+ if (ret)
-+ return dev_err_probe(ctrl->dev, ret, "Failed to enable clock\n");
-+
-+ ret = devm_add_action_or_reset(ctrl->dev, otto_wdt_clock_action, clk);
-+ if (ret)
-+ return ret;
-+
-+ ctrl->clk_rate_khz = clk_get_rate(clk) / 1000;
-+ if (ctrl->clk_rate_khz == 0)
-+ return dev_err_probe(ctrl->dev, -ENXIO, "Failed to get clock rate\n");
-+
-+ return 0;
-+}
-+
-+static int otto_wdt_probe_reset_mode(struct otto_wdt_ctrl *ctrl)
-+{
-+ static const char *mode_property = "realtek,reset-mode";
-+ const struct fwnode_handle *node = ctrl->dev->fwnode;
-+ int mode_count;
-+ u32 mode;
-+ u32 v;
-+
-+ if (!node)
-+ return -ENXIO;
-+
-+ mode_count = fwnode_property_string_array_count(node, mode_property);
-+ if (mode_count < 0)
-+ return mode_count;
-+ else if (mode_count == 0)
-+ return 0;
-+ else if (mode_count != 1)
-+ return -EINVAL;
-+
-+ if (fwnode_property_match_string(node, mode_property, "soc") == 0)
-+ mode = OTTO_WDT_MODE_SOC;
-+ else if (fwnode_property_match_string(node, mode_property, "cpu") == 0)
-+ mode = OTTO_WDT_MODE_CPU;
-+ else if (fwnode_property_match_string(node, mode_property, "software") == 0)
-+ mode = OTTO_WDT_MODE_SOFTWARE;
-+ else
-+ return -EINVAL;
-+
-+ v = ioread32(ctrl->base + OTTO_WDT_REG_CTRL);
-+ v &= ~OTTO_WDT_CTRL_RST_MODE;
-+ v |= FIELD_PREP(OTTO_WDT_CTRL_RST_MODE, mode);
-+ iowrite32(v, ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ return 0;
-+}
-+
-+static int otto_wdt_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct otto_wdt_ctrl *ctrl;
-+ unsigned int max_tick_ms;
-+ int ret;
-+
-+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
-+ if (!ctrl)
-+ return -ENOMEM;
-+
-+ ctrl->dev = dev;
-+ ctrl->base = devm_platform_ioremap_resource(pdev, 0);
-+ if (IS_ERR(ctrl->base))
-+ return PTR_ERR(ctrl->base);
-+
-+ /* Clear any old interrupts and reset initial state */
-+ iowrite32(OTTO_WDT_INTR_PHASE_1 | OTTO_WDT_INTR_PHASE_2,
-+ ctrl->base + OTTO_WDT_REG_INTR);
-+ iowrite32(OTTO_WDT_CTRL_DEFAULT, ctrl->base + OTTO_WDT_REG_CTRL);
-+
-+ ret = otto_wdt_probe_clk(ctrl);
-+ if (ret)
-+ return ret;
-+
-+ ctrl->irq_phase1 = platform_get_irq_byname(pdev, "phase1");
-+ if (ctrl->irq_phase1 < 0)
-+ return ctrl->irq_phase1;
-+
-+ ret = devm_request_irq(dev, ctrl->irq_phase1, otto_wdt_phase1_isr, 0,
-+ "realtek-otto-wdt", ctrl);
-+ if (ret)
-+ return dev_err_probe(dev, ret, "Failed to get IRQ for phase1\n");
-+
-+ ret = otto_wdt_probe_reset_mode(ctrl);
-+ if (ret)
-+ return dev_err_probe(dev, ret, "Invalid reset mode specified\n");
-+
-+ ctrl->wdev.parent = dev;
-+ ctrl->wdev.info = &otto_wdt_info;
-+ ctrl->wdev.ops = &otto_wdt_ops;
-+
-+ /*
-+ * Since pretimeout cannot be disabled, min. timeout is twice the
-+ * subsystem resolution. Max. timeout is ca. 43s at a bus clock of 200MHz.
-+ */
-+ ctrl->wdev.min_timeout = 2;
-+ max_tick_ms = otto_wdt_tick_ms(ctrl, OTTO_WDT_PRESCALE_MAX);
-+ ctrl->wdev.max_hw_heartbeat_ms = max_tick_ms * OTTO_WDT_TIMEOUT_TICKS_MAX;
-+ ctrl->wdev.timeout = min(30U, ctrl->wdev.max_hw_heartbeat_ms / 1000);
-+
-+ watchdog_set_drvdata(&ctrl->wdev, ctrl);
-+ watchdog_init_timeout(&ctrl->wdev, 0, dev);
-+ watchdog_stop_on_reboot(&ctrl->wdev);
-+ watchdog_set_restart_priority(&ctrl->wdev, 128);
-+
-+ ret = otto_wdt_determine_timeouts(&ctrl->wdev, ctrl->wdev.timeout, 1);
-+ if (ret)
-+ return dev_err_probe(dev, ret, "Failed to set timeout\n");
-+
-+ return devm_watchdog_register_device(dev, &ctrl->wdev);
-+}
-+
-+static const struct of_device_id otto_wdt_ids[] = {
-+ { .compatible = "realtek,rtl8380-wdt" },
-+ { .compatible = "realtek,rtl8390-wdt" },
-+ { .compatible = "realtek,rtl9300-wdt" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, otto_wdt_ids);
-+
-+static struct platform_driver otto_wdt_driver = {
-+ .probe = otto_wdt_probe,
-+ .driver = {
-+ .name = "realtek-otto-watchdog",
-+ .of_match_table = otto_wdt_ids,
-+ },
-+};
-+module_platform_driver(otto_wdt_driver);
-+
-+MODULE_LICENSE("GPL v2");
-+MODULE_AUTHOR("Sander Vanheule <sander@svanheule.net>");
-+MODULE_DESCRIPTION("Realtek Otto watchdog timer driver");
diff --git a/target/linux/realtek/patches-5.10/020-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch b/target/linux/realtek/patches-5.10/020-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch
deleted file mode 100644
index ef2e225717..0000000000
--- a/target/linux/realtek/patches-5.10/020-v5.17-net-mdio-add-helpers-to-extract-clause-45-regad-and-.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-From c6af53f038aa32cec12e8a305ba07c7ef168f1b0 Mon Sep 17 00:00:00 2001
-From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
-Date: Tue, 4 Jan 2022 12:07:00 +0000
-Subject: [PATCH 2/3] net: mdio: add helpers to extract clause 45 regad and
- devad fields
-
-Add a couple of helpers and definitions to extract the clause 45 regad
-and devad fields from the regnum passed into MDIO drivers.
-
-Tested-by: Daniel Golle <daniel@makrotopia.org>
-Reviewed-by: Andrew Lunn <andrew@lunn.ch>
-Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- include/linux/mdio.h | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/include/linux/mdio.h
-+++ b/include/linux/mdio.h
-@@ -7,6 +7,7 @@
- #define __LINUX_MDIO_H__
-
- #include <uapi/linux/mdio.h>
-+#include <linux/bitfield.h>
- #include <linux/mod_devicetable.h>
-
- /* Or MII_ADDR_C45 into regnum for read/write on mii_bus to enable the 21 bit
-@@ -14,6 +15,7 @@
- */
- #define MII_ADDR_C45 (1<<30)
- #define MII_DEVADDR_C45_SHIFT 16
-+#define MII_DEVADDR_C45_MASK GENMASK(20, 16)
- #define MII_REGADDR_C45_MASK GENMASK(15, 0)
-
- struct gpio_desc;
-@@ -342,6 +344,16 @@ static inline u32 mdiobus_c45_addr(int d
- return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
- }
-
-+static inline u16 mdiobus_c45_regad(u32 regnum)
-+{
-+ return FIELD_GET(MII_REGADDR_C45_MASK, regnum);
-+}
-+
-+static inline u16 mdiobus_c45_devad(u32 regnum)
-+{
-+ return FIELD_GET(MII_DEVADDR_C45_MASK, regnum);
-+}
-+
- static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
- u16 regnum)
- {
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch b/target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch
deleted file mode 100644
index 8f35351438..0000000000
--- a/target/linux/realtek/patches-5.10/021-v5.19-02-gpio-realtek-otto-Support-reversed-port-layouts.patch
+++ /dev/null
@@ -1,123 +0,0 @@
-From 512c5be35223d9baa2629efa1084cf5210eaee80 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sat, 9 Apr 2022 21:55:47 +0200
-Subject: [PATCH 2/6] gpio: realtek-otto: Support reversed port layouts
-
-The GPIO port layout on the RTL930x SoC series is reversed compared to
-the RTL838x and RTL839x SoC series. Add new port offset calculator
-functions to ensure the correct order is used when reading port IRQ
-data, and ensure bgpio uses the right byte ordering.
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
----
- drivers/gpio/gpio-realtek-otto.c | 55 +++++++++++++++++++++++++++++---
- 1 file changed, 51 insertions(+), 4 deletions(-)
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -58,6 +58,8 @@ struct realtek_gpio_ctrl {
- raw_spinlock_t lock;
- u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
- u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
-+ unsigned int (*port_offset_u8)(unsigned int port);
-+ unsigned int (*port_offset_u16)(unsigned int port);
- };
-
- /* Expand with more flags as devices with other quirks are added */
-@@ -69,6 +71,11 @@ enum realtek_gpio_flags {
- * line the IRQ handler was assigned to, causing uncaught interrupts.
- */
- GPIO_INTERRUPTS_DISABLED = BIT(0),
-+ /*
-+ * Port order is reversed, meaning DCBA register layout for 1-bit
-+ * fields, and [BA, DC] for 2-bit fields.
-+ */
-+ GPIO_PORTS_REVERSED = BIT(1),
- };
-
- static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
-@@ -86,21 +93,50 @@ static struct realtek_gpio_ctrl *irq_dat
- * port. The two interrupt mask registers store two bits per GPIO, so use u16
- * values.
- */
-+static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
-+{
-+ return port;
-+}
-+
-+static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
-+{
-+ return 2 * port;
-+}
-+
-+/*
-+ * Reversed port order register access
-+ *
-+ * For registers with one bit per GPIO, all ports are stored as u8-s in one
-+ * register in reversed order. The two interrupt mask registers store two bits
-+ * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
-+ * second ports 3 and 2.
-+ */
-+static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
-+{
-+ return 3 - port;
-+}
-+
-+static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
-+{
-+ return 2 * (port ^ 1);
-+}
-+
- static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
- unsigned int port, u16 irq_type, u16 irq_mask)
- {
-- iowrite16(irq_type & irq_mask, ctrl->base + REALTEK_GPIO_REG_IMR + 2 * port);
-+ iowrite16(irq_type & irq_mask,
-+ ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
- }
-
- static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
- unsigned int port, u8 mask)
- {
-- iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + port);
-+ iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
- }
-
- static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
- {
-- return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + port);
-+ return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
- }
-
- /* Set the rising and falling edge mask bits for a GPIO port pin */
-@@ -253,6 +289,7 @@ MODULE_DEVICE_TABLE(of, realtek_gpio_of_
- static int realtek_gpio_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-+ unsigned long bgpio_flags;
- unsigned int dev_flags;
- struct gpio_irq_chip *girq;
- struct realtek_gpio_ctrl *ctrl;
-@@ -280,10 +317,20 @@ static int realtek_gpio_probe(struct pla
-
- raw_spin_lock_init(&ctrl->lock);
-
-+ if (dev_flags & GPIO_PORTS_REVERSED) {
-+ bgpio_flags = 0;
-+ ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
-+ ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
-+ } else {
-+ bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
-+ ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
-+ ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
-+ }
-+
- err = bgpio_init(&ctrl->gc, dev, 4,
- ctrl->base + REALTEK_GPIO_REG_DATA, NULL, NULL,
- ctrl->base + REALTEK_GPIO_REG_DIR, NULL,
-- BGPIOF_BIG_ENDIAN_BYTE_ORDER);
-+ bgpio_flags);
- if (err) {
- dev_err(dev, "unable to init generic GPIO");
- return err;
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch b/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch
deleted file mode 100644
index 8f5d571ea2..0000000000
--- a/target/linux/realtek/patches-5.10/021-v5.19-03-gpio-realtek-otto-Support-per-cpu-interrupts.patch
+++ /dev/null
@@ -1,153 +0,0 @@
-From 95fa6dbe58f286a8f87cb37b7516232eb678de2d Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sat, 9 Apr 2022 21:55:48 +0200
-Subject: [PATCH 3/6] gpio: realtek-otto: Support per-cpu interrupts
-
-On SoCs with multiple cores, it is possible that the GPIO interrupt
-controller supports assigning specific pins to one or more cores.
-
-IRQ balancing can be performed on a line-by-line basis if the parent
-interrupt is routed to all available cores, which is the default upon
-initialisation.
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
----
- drivers/gpio/gpio-realtek-otto.c | 75 +++++++++++++++++++++++++++++++-
- 1 file changed, 74 insertions(+), 1 deletion(-)
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -1,6 +1,7 @@
- // SPDX-License-Identifier: GPL-2.0-only
-
- #include <linux/gpio/driver.h>
-+#include <linux/cpumask.h>
- #include <linux/irq.h>
- #include <linux/minmax.h>
- #include <linux/mod_devicetable.h>
-@@ -55,6 +56,8 @@
- struct realtek_gpio_ctrl {
- struct gpio_chip gc;
- void __iomem *base;
-+ void __iomem *cpumask_base;
-+ struct cpumask cpu_irq_maskable;
- raw_spinlock_t lock;
- u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
- u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
-@@ -76,6 +79,11 @@ enum realtek_gpio_flags {
- * fields, and [BA, DC] for 2-bit fields.
- */
- GPIO_PORTS_REVERSED = BIT(1),
-+ /*
-+ * Interrupts can be enabled per cpu. This requires a secondary IO
-+ * range, where the per-cpu enable masks are located.
-+ */
-+ GPIO_INTERRUPTS_PER_CPU = BIT(2),
- };
-
- static struct realtek_gpio_ctrl *irq_data_to_ctrl(struct irq_data *data)
-@@ -250,14 +258,61 @@ static void realtek_gpio_irq_handler(str
- chained_irq_exit(irq_chip, desc);
- }
-
-+static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
-+ unsigned int port, int cpu)
-+{
-+ return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
-+ REALTEK_GPIO_PORTS_PER_BANK * cpu;
-+}
-+
-+static int realtek_gpio_irq_set_affinity(struct irq_data *data,
-+ const struct cpumask *dest, bool force)
-+{
-+ struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
-+ unsigned int line = irqd_to_hwirq(data);
-+ unsigned int port = line / 8;
-+ unsigned int port_pin = line % 8;
-+ void __iomem *irq_cpu_mask;
-+ unsigned long flags;
-+ int cpu;
-+ u8 v;
-+
-+ if (!ctrl->cpumask_base)
-+ return -ENXIO;
-+
-+ raw_spin_lock_irqsave(&ctrl->lock, flags);
-+
-+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
-+ irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
-+ v = ioread8(irq_cpu_mask);
-+
-+ if (cpumask_test_cpu(cpu, dest))
-+ v |= BIT(port_pin);
-+ else
-+ v &= ~BIT(port_pin);
-+
-+ iowrite8(v, irq_cpu_mask);
-+ }
-+
-+ raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-+
-+ irq_data_update_effective_affinity(data, dest);
-+
-+ return 0;
-+}
-+
- static int realtek_gpio_irq_init(struct gpio_chip *gc)
- {
- struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
- unsigned int port;
-+ int cpu;
-
- for (port = 0; (port * 8) < gc->ngpio; port++) {
- realtek_gpio_write_imr(ctrl, port, 0, 0);
- realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
-+
-+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
-+ iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
- }
-
- return 0;
-@@ -269,6 +324,7 @@ static struct irq_chip realtek_gpio_irq_
- .irq_mask = realtek_gpio_irq_mask,
- .irq_unmask = realtek_gpio_irq_unmask,
- .irq_set_type = realtek_gpio_irq_set_type,
-+ .irq_set_affinity = realtek_gpio_irq_set_affinity,
- };
-
- static const struct of_device_id realtek_gpio_of_match[] = {
-@@ -293,8 +349,10 @@ static int realtek_gpio_probe(struct pla
- unsigned int dev_flags;
- struct gpio_irq_chip *girq;
- struct realtek_gpio_ctrl *ctrl;
-+ struct resource *res;
- u32 ngpios;
-- int err, irq;
-+ unsigned int nr_cpus;
-+ int cpu, err, irq;
-
- ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl)
-@@ -355,6 +413,21 @@ static int realtek_gpio_probe(struct pla
- girq->init_hw = realtek_gpio_irq_init;
- }
-
-+ cpumask_clear(&ctrl->cpu_irq_maskable);
-+
-+ if ((dev_flags & GPIO_INTERRUPTS_PER_CPU) && irq > 0) {
-+ ctrl->cpumask_base = devm_platform_get_and_ioremap_resource(pdev, 1, &res);
-+ if (IS_ERR(ctrl->cpumask_base))
-+ return dev_err_probe(dev, PTR_ERR(ctrl->cpumask_base),
-+ "missing CPU IRQ mask registers");
-+
-+ nr_cpus = resource_size(res) / REALTEK_GPIO_PORTS_PER_BANK;
-+ nr_cpus = min(nr_cpus, num_present_cpus());
-+
-+ for (cpu = 0; cpu < nr_cpus; cpu++)
-+ cpumask_set_cpu(cpu, &ctrl->cpu_irq_maskable);
-+ }
-+
- return devm_gpiochip_add_data(dev, &ctrl->gc, ctrl);
- }
-
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch b/target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch
deleted file mode 100644
index 536c85740a..0000000000
--- a/target/linux/realtek/patches-5.10/021-v5.19-04-gpio-realtek-otto-Add-RTL930x-support.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From deaf1cecdeb052cdb5e92fd642016198724b44a4 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sat, 9 Apr 2022 21:55:49 +0200
-Subject: [PATCH 4/6] gpio: realtek-otto: Add RTL930x support
-
-The RTL930x SoC series has support for 24 GPIOs, with the port order
-reversed compared to RTL838x and RTL839x. The RTL930x series also has
-two CPUs (VPEs) and can distribute individual GPIO interrupts between
-them.
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
----
- drivers/gpio/gpio-realtek-otto.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -338,6 +338,10 @@ static const struct of_device_id realtek
- {
- .compatible = "realtek,rtl8390-gpio",
- },
-+ {
-+ .compatible = "realtek,rtl9300-gpio",
-+ .data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)
-+ },
- {}
- };
- MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
diff --git a/target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch b/target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch
deleted file mode 100644
index 16990ce053..0000000000
--- a/target/linux/realtek/patches-5.10/021-v5.19-06-gpio-realtek-otto-Add-RTL931x-support.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From d3bf3dc4bbbf6109bd9b4bd60089d36205ec4a37 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sat, 9 Apr 2022 21:55:51 +0200
-Subject: [PATCH 6/6] gpio: realtek-otto: Add RTL931x support
-
-The RTL931x SoC series has support for 32 GPIOs, although not all lines
-may be broken out to a physical pad.
-
-The GPIO bank's parent interrupt can be routed to either or both of the
-SoC's CPU cores by the GIC. Line-by-line IRQ balancing is not possible
-on these SoCs.
-
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
----
- drivers/gpio/gpio-realtek-otto.c | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -342,6 +342,9 @@ static const struct of_device_id realtek
- .compatible = "realtek,rtl9300-gpio",
- .data = (void *)(GPIO_PORTS_REVERSED | GPIO_INTERRUPTS_PER_CPU)
- },
-+ {
-+ .compatible = "realtek,rtl9310-gpio",
-+ },
- {}
- };
- MODULE_DEVICE_TABLE(of, realtek_gpio_of_match);
diff --git a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch b/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch
deleted file mode 100644
index fce26133fc..0000000000
--- a/target/linux/realtek/patches-5.10/300-mips-add-rtl838x-platform.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From fce11f68491b46b93df69de0630cd9edb90bc772 Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Wed, 29 Dec 2021 21:54:21 +0100
-Subject: [PATCH] realtek: Create 4 different Realtek Platforms
-
-Creates RTL83XX as a basic kernel config parameter for the
-RTL838X, RTL839x, RTL930X and RTL931X platforms with respective
-configurations for the SoCs, which are introduced in addition.
-
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- arch/mips/Kbuild.platforms | 1 +
- arch/mips/Kconfig | 57 ++++++++++++++
- 2 files changed, 58 insertions(+)
-
---- a/arch/mips/Kbuild.platforms
-+++ b/arch/mips/Kbuild.platforms
-@@ -23,6 +23,7 @@ platform-$(CONFIG_PIC32MZDA) += pic32/
- platform-$(CONFIG_MACH_PISTACHIO) += pistachio/
- platform-$(CONFIG_RALINK) += ralink/
- platform-$(CONFIG_MIKROTIK_RB532) += rb532/
-+platform-$(CONFIG_RTL83XX) += rtl838x/
- platform-$(CONFIG_SGI_IP22) += sgi-ip22/
- platform-$(CONFIG_SGI_IP27) += sgi-ip27/
- platform-$(CONFIG_SGI_IP28) += sgi-ip22/
---- a/arch/mips/Kconfig
-+++ b/arch/mips/Kconfig
-@@ -1037,8 +1037,59 @@ config NLM_XLP_BOARD
- This board is based on Netlogic XLP Processor.
- Say Y here if you have a XLP based board.
-
-+config RTL83XX
-+ bool "Realtek based platforms"
-+ select DMA_NONCOHERENT
-+ select IRQ_MIPS_CPU
-+ select NO_EXCEPT_FILL
-+ select SYS_HAS_CPU_MIPS32_R1
-+ select SYS_HAS_CPU_MIPS32_R2
-+ select SYS_SUPPORTS_BIG_ENDIAN
-+ select SYS_SUPPORTS_HIGHMEM
-+ select SYS_SUPPORTS_32BIT_KERNEL
-+ select SYS_SUPPORTS_MIPS16
-+ select SYS_HAS_EARLY_PRINTK
-+ select SYS_HAS_EARLY_PRINTK_8250
-+ select USE_GENERIC_EARLY_PRINTK_8250
-+ select BOOT_RAW
-+ select PINCTRL
-+ select ARCH_HAS_RESET_CONTROLLER
-+ select RESET_CONTROLLER
-+ select USE_OF
-+
- endchoice
-
-+config RTL838X
-+ bool "Realtek RTL838X based platforms"
-+ depends on RTL83XX
-+ select CPU_SUPPORTS_CPUFREQ
-+ select MIPS_EXTERNAL_TIMER
-+
-+config RTL839X
-+ bool "Realtek RTL839X based platforms"
-+ depends on RTL83XX
-+ select CPU_SUPPORTS_CPUFREQ
-+ select MIPS_EXTERNAL_TIMER
-+ select SYS_SUPPORTS_MULTITHREADING
-+
-+config RTL930X
-+ bool "Realtek RTL930X based platforms"
-+ depends on RTL83XX
-+ select MIPS_CPU_SCACHE
-+ select CSRC_R4K
-+ select CEVT_RTL9300
-+ select SYS_SUPPORTS_MULTITHREADING
-+
-+config RTL931X
-+ bool "Realtek RTL931X based platforms"
-+ depends on RTL930X
-+ select MIPS_GIC
-+ select COMMON_CLK
-+ select CLKSRC_MIPS_GIC
-+ select SYS_SUPPORTS_VPE_LOADER
-+ select SYS_SUPPORTS_SMP
-+ select SYS_SUPPORTS_MIPS_CPS
-+
- source "arch/mips/alchemy/Kconfig"
- source "arch/mips/ath25/Kconfig"
- source "arch/mips/ath79/Kconfig"
-@@ -1097,6 +1148,9 @@ config CEVT_GT641XX
- config CEVT_R4K
- bool
-
-+config CEVT_RTL9300
-+ bool
-+
- config CEVT_SB1250
- bool
-
diff --git a/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch b/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch
deleted file mode 100644
index 2725651243..0000000000
--- a/target/linux/realtek/patches-5.10/301-gpio-add-rtl8231-driver.patch
+++ /dev/null
@@ -1,50 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- drivers/gpio/Kconfig | 6 ++++++
- drivers/gpio/Makefile | 1 +
- 2 files changed, 7 insertions(+)
-
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -508,6 +508,12 @@ config GPIO_REG
- A 32-bit single register GPIO fixed in/out implementation. This
- can be used to represent any register as a set of GPIO signals.
-
-+config GPIO_RTL8231
-+ tristate "RTL8231 GPIO"
-+ depends on RTL83XX
-+ 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
-@@ -127,6 +127,7 @@ obj-$(CONFIG_GPIO_RDA) += gpio-rda.o
- obj-$(CONFIG_GPIO_RDC321X) += gpio-rdc321x.o
- obj-$(CONFIG_GPIO_REALTEK_OTTO) += gpio-realtek-otto.o
- obj-$(CONFIG_GPIO_REG) += gpio-reg.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/patches-5.10/302-clocksource-add-otto-driver.patch b/target/linux/realtek/patches-5.10/302-clocksource-add-otto-driver.patch
deleted file mode 100644
index 81dff89f82..0000000000
--- a/target/linux/realtek/patches-5.10/302-clocksource-add-otto-driver.patch
+++ /dev/null
@@ -1,93 +0,0 @@
-From 3cc8011171186d906c547bc6f0c1f8e350edc7cf Mon Sep 17 00:00:00 2001
-From: Markus Stockhausen <markus.stockhausen@gmx.de>
-Date: Mon, 3 Oct 2022 14:45:21 +0200
-Subject: [PATCH] realtek: resurrect timer driver
-
-Now that we provide a clock driver for the Reltek SOCs the CPU frequency might
-change on demand. This has direct visible effects during operation
-
-- the CEVT 4K timer is no longer a stable clocksource
-- after CPU frequencies changes time calculation works wrong
-- sched_clock falls back to kernel default interval (100 Hz)
-- timestamps in dmesg have only 2 digits left
-
-[ 0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps ...
-[ 0.060000] pid_max: default: 32768 minimum: 301
-[ 0.070000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
-[ 0.070000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes, linear)
-[ 0.080000] dyndbg: Ignore empty _ddebug table in a CONFIG_DYNAMIC_DEBUG_CORE build
-[ 0.090000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, ...
-
-Looking around where we can start the CEVT timer for RTL930X is a good basis.
-Initially it was developed as a clocksource driver for the broken timer in that
-specific SOC series. Afterwards it was shifted around to the CEVT location,
-got SMP enablement and lost its clocksource feature. So we at least have
-something to copy from. As the timers on these devices are well understood
-the implementation follows this way:
-
-- leave the RTL930X implementation as is
-- provide a new driver for RTL83XX devices only
-- swap RTL930X driver at a later time
-
-Like the clock driver this patch contains a self contained module that is SOC
-independet and already provides full support for the RTL838X, RTL839X and
-RTL930X devices. Some of the new (or reestablished) features are:
-
-- simplified initialization routines
-- SMP setup with CPU hotplug framework
-- derived from LXB clock speed
-- supplied clocksource
-- dedicated register functions for better readability
-- documentation about some caveats
-
-Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
-[remove unused header includes, remove old CONFIG_MIPS dependency, add
-REALTEK_ prefix to driver symbol]
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-
----
- drivers/clocksource/Kconfig | 12 +++
- drivers/clocksource/Makefile | 1 +
- include/linux/cpuhotplug.h | 1 +
- 3 files changed, 14 insertions(+)
-
---- a/drivers/clocksource/Kconfig
-+++ b/drivers/clocksource/Kconfig
-@@ -127,6 +127,17 @@ config RDA_TIMER
- help
- Enables the support for the RDA Micro timer driver.
-
-+config REALTEK_OTTO_TIMER
-+ bool "Clocksource/timer for the Realtek Otto platform"
-+ select COMMON_CLK
-+ select TIMER_OF
-+ help
-+ This driver adds support for the timers found in the Realtek RTL83xx
-+ and RTL93xx SoCs series. This includes chips such as RTL8380, RTL8381
-+ and RTL832, as well as chips from the RTL839x series, such as RTL8390
-+ RT8391, RTL8392, RTL8393 and RTL8396 and chips of the RTL930x series
-+ such as RTL9301, RTL9302 or RTL9303.
-+
- config SUN4I_TIMER
- bool "Sun4i timer driver" if COMPILE_TEST
- depends on HAS_IOMEM
---- a/drivers/clocksource/Makefile
-+++ b/drivers/clocksource/Makefile
-@@ -63,6 +63,7 @@ obj-$(CONFIG_MILBEAUT_TIMER) += timer-mi
- obj-$(CONFIG_SPRD_TIMER) += timer-sprd.o
- obj-$(CONFIG_NPCM7XX_TIMER) += timer-npcm7xx.o
- obj-$(CONFIG_RDA_TIMER) += timer-rda.o
-+obj-$(CONFIG_REALTEK_OTTO_TIMER) += timer-rtl-otto.o
-
- obj-$(CONFIG_ARC_TIMERS) += arc_timer.o
- obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o
---- a/include/linux/cpuhotplug.h
-+++ b/include/linux/cpuhotplug.h
-@@ -133,6 +133,7 @@ enum cpuhp_state {
- CPUHP_AP_MARCO_TIMER_STARTING,
- CPUHP_AP_MIPS_GIC_TIMER_STARTING,
- CPUHP_AP_ARC_TIMER_STARTING,
-+ CPUHP_AP_REALTEK_TIMER_STARTING,
- CPUHP_AP_RISCV_TIMER_STARTING,
- CPUHP_AP_CLINT_TIMER_STARTING,
- CPUHP_AP_CSKY_TIMER_STARTING,
diff --git a/target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch b/target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch
deleted file mode 100644
index 1763d31fb0..0000000000
--- a/target/linux/realtek/patches-5.10/303-gpio-update-dependencies-for-gpio-realtek-otto.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 9bac1c20b8f39f2e0e342b087add5093b94feaed Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Wed, 5 May 2021 22:05:39 +0900
-Subject: realtek: fix gpio-realtek-otto driver dependency
-
-"MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X"
-is used in OpenWrt, so fix the dependency by renaming it.
-
-Submitted-by: INAGAKI Hiroshi <musashino.open@gmail.com>
----
- drivers/gpio/Kconfig | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
---- a/drivers/gpio/Kconfig
-+++ b/drivers/gpio/Kconfig
-@@ -491,8 +491,8 @@ config GPIO_RDA
-
- config GPIO_REALTEK_OTTO
- tristate "Realtek Otto GPIO support"
-- depends on MACH_REALTEK_RTL
-- default MACH_REALTEK_RTL
-+ depends on RTL83XX
-+ default RTL838X
- select GPIO_GENERIC
- select GPIOLIB_IRQCHIP
- help
diff --git a/target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch b/target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch
deleted file mode 100644
index 23c5448aa2..0000000000
--- a/target/linux/realtek/patches-5.10/304-spi-update-dependency-for-spi-realtek-rtl.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From 0b000cbfe0aa0323bffa855ef8449c0687a4c071 Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Thu, 6 May 2021 19:30:58 +0900
-Subject: realtek: backport spi-realtek-rtl driver from 5.12 to 5.10
-
-This patch backports "spi-realtek-rtl" driver to Kernel 5.10 from 5.12.
-"MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X"
-is used in OpenWrt, so update the dependency by the additional patch.
-
-Submitted-by: INAGAKI Hiroshi <musashino.open@gmail.com>
----
- drivers/spi/Makefile | 2 +-
- 1 files changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/spi/Makefile
-+++ b/drivers/spi/Makefile
-@@ -94,7 +94,7 @@ obj-$(CONFIG_SPI_QCOM_QSPI) += spi-qcom
- obj-$(CONFIG_SPI_QUP) += spi-qup.o
- obj-$(CONFIG_SPI_ROCKCHIP) += spi-rockchip.o
- obj-$(CONFIG_SPI_RB4XX) += spi-rb4xx.o
--obj-$(CONFIG_MACH_REALTEK_RTL) += spi-realtek-rtl.o
-+obj-$(CONFIG_RTL83XX) += spi-realtek-rtl.o
- obj-$(CONFIG_SPI_RPCIF) += spi-rpc-if.o
- obj-$(CONFIG_SPI_RSPI) += spi-rspi.o
- obj-$(CONFIG_SPI_S3C24XX) += spi-s3c24xx-hw.o
diff --git a/target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch b/target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch
deleted file mode 100644
index 0c1cc4235e..0000000000
--- a/target/linux/realtek/patches-5.10/305-irqchip-update-dependency-for-irq-realtek-rtl.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 2cd00b51470a30198b048a5fca48a04db77e29cc Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Fri, 21 May 2021 23:16:37 +0900
-Subject: [PATCH] realtek: backport irq-realtek-rtl driver from 5.12 to 5.10
-
-This patch backports "irq-realtek-rtl" driver to Kernel 5.10 from 5.12.
-"MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X"
-is used in OpenWrt, so update the dependency by the additional patch.
-
-Submitted-by: INAGAKI Hiroshi <musashino.open@gmail.com>
----
- drivers/irqchip/Makefile | 2 +-
- 1 files changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/irqchip/Makefile
-+++ b/drivers/irqchip/Makefile
-@@ -114,4 +114,4 @@ obj-$(CONFIG_LOONGSON_PCH_PIC) += irq-l
- obj-$(CONFIG_LOONGSON_PCH_MSI) += irq-loongson-pch-msi.o
- obj-$(CONFIG_MST_IRQ) += irq-mst-intc.o
- obj-$(CONFIG_SL28CPLD_INTC) += irq-sl28cpld.o
--obj-$(CONFIG_MACH_REALTEK_RTL) += irq-realtek-rtl.o
-+obj-$(CONFIG_RTL83XX) += irq-realtek-rtl.o
diff --git a/target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch b/target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch
deleted file mode 100644
index f92981340b..0000000000
--- a/target/linux/realtek/patches-5.10/307-wdt-update-dependency-for-realtek-otto-wdt.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From b8fc5eecdc5d33cf261986436597b5482ab856da Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sun, 14 Nov 2021 19:45:32 +0100
-Subject: [PATCH] realtek: Backport Realtek Otto WDT driver
-
-Add patch submitted upstream to linux-watchdog and replace the MIPS
-architecture symbols. Requires one extra patch for the DIV_ROUND_*
-macros, which have moved to a different header since 5.10.
-
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Tested-by: Stijn Segers <foss@volatilesystems.org>
-Tested-by: Paul Fertser <fercerpav@gmail.com>
-Tested-by: Stijn Tintel <stijn@linux-ipv6.be>
----
- drivers/watchdog/Kconfig | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/watchdog/Kconfig
-+++ b/drivers/watchdog/Kconfig
-@@ -997,10 +997,10 @@ config RTD119X_WATCHDOG
-
- config REALTEK_OTTO_WDT
- tristate "Realtek Otto MIPS watchdog support"
-- depends on MACH_REALTEK_RTL || COMPILE_TEST
-+ depends on RTL83XX
- depends on COMMON_CLK
- select WATCHDOG_CORE
-- default MACH_REALTEK_RTL
-+ default RTL83XX
- help
- Say Y here to include support for the watchdog timer on Realtek
- RTL838x, RTL839x, RTL930x SoCs. This watchdog has pretimeout
diff --git a/target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch b/target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch
deleted file mode 100644
index 78b145617f..0000000000
--- a/target/linux/realtek/patches-5.10/308-otto-wdt-fix-missing-math-header.patch
+++ /dev/null
@@ -1,28 +0,0 @@
-From b8fc5eecdc5d33cf261986436597b5482ab856da Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sun, 14 Nov 2021 19:45:32 +0100
-Subject: [PATCH] realtek: Backport Realtek Otto WDT driver
-
-Add patch submitted upstream to linux-watchdog and replace the MIPS
-architecture symbols. Requires one extra patch for the DIV_ROUND_*
-macros, which have moved to a different header since 5.10.
-
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Tested-by: Stijn Segers <foss@volatilesystems.org>
-Tested-by: Paul Fertser <fercerpav@gmail.com>
-Tested-by: Stijn Tintel <stijn@linux-ipv6.be>
----
- drivers/watchdog/realtek_otto_wdt.c | 2 +-
- 1 files changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/watchdog/realtek_otto_wdt.c
-+++ b/drivers/watchdog/realtek_otto_wdt.c
-@@ -21,7 +21,7 @@
- #include <linux/delay.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
--#include <linux/math.h>
-+#include <linux/kernel.h>
- #include <linux/minmax.h>
- #include <linux/module.h>
- #include <linux/mod_devicetable.h>
diff --git a/target/linux/realtek/patches-5.10/309-cevt-rtl9300-support.patch b/target/linux/realtek/patches-5.10/309-cevt-rtl9300-support.patch
deleted file mode 100644
index 93d69c07cf..0000000000
--- a/target/linux/realtek/patches-5.10/309-cevt-rtl9300-support.patch
+++ /dev/null
@@ -1,54 +0,0 @@
-From 775d903216a08c2a8009863d2f9c33f62657ba94 Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Thu, 6 Jan 2022 20:27:01 +0100
-Subject: [PATCH] realtek: Replace the RTL9300 generic timer with a CEVT timer
-
-The RTL9300 has a broken R4K MIPS timer interrupt, however, the
-R4K clocksource works. We replace the RTL9300 timer with a
-Clock Event Timer (CEVT), which is VSMP aware and can be instantiated
-as part of brining a VSMTP cpu up instead of the R4K CEVT source.
-For this we place the RTL9300 CEVT timer in arch/mips/kernel
-together with other MIPS CEVT timers, initialize the SoC IRQs
-from a modified smp-mt.c and instantiate each timer as part
-of the MIPS time setup in arch/mips/include/asm/time.h instead
-of the R4K CEVT, similarly as is done by other MIPS CEVT timers.
-
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- arch/mips/kernel/Makefile | 1 +
- arch/mips/include/asm/time.h | 7 +++++++
- 2 files changed, 8 insertions(+)
-
---- a/arch/mips/kernel/Makefile
-+++ b/arch/mips/kernel/Makefile
-@@ -27,6 +27,7 @@ obj-$(CONFIG_CEVT_BCM1480) += cevt-bcm14
- obj-$(CONFIG_CEVT_R4K) += cevt-r4k.o
- obj-$(CONFIG_CEVT_DS1287) += cevt-ds1287.o
- obj-$(CONFIG_CEVT_GT641XX) += cevt-gt641xx.o
-+obj-$(CONFIG_CEVT_RTL9300) += cevt-rtl9300.o
- obj-$(CONFIG_CEVT_SB1250) += cevt-sb1250.o
- obj-$(CONFIG_CEVT_TXX9) += cevt-txx9.o
- obj-$(CONFIG_CSRC_BCM1480) += csrc-bcm1480.o
---- a/arch/mips/include/asm/time.h
-+++ b/arch/mips/include/asm/time.h
-@@ -15,6 +15,8 @@
- #include <linux/clockchips.h>
- #include <linux/clocksource.h>
-
-+extern void rtl9300_clockevent_init(void);
-+
- extern spinlock_t rtc_lock;
-
- /*
-@@ -43,6 +45,11 @@ extern int r4k_clockevent_init(void);
-
- static inline int mips_clockevent_init(void)
- {
-+#ifdef CONFIG_CEVT_RTL9300
-+ rtl9300_clockevent_init();
-+ return 0;
-+#endif
-+
- #ifdef CONFIG_CEVT_R4K
- return r4k_clockevent_init();
- #else
diff --git a/target/linux/realtek/patches-5.10/310-add-i2c-rtl9300-support.patch b/target/linux/realtek/patches-5.10/310-add-i2c-rtl9300-support.patch
deleted file mode 100644
index 4df9bf043b..0000000000
--- a/target/linux/realtek/patches-5.10/310-add-i2c-rtl9300-support.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From 63a0a4d85bc900464c5b046b13808a582345f8c8 Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Sat, 11 Dec 2021 20:14:47 +0100
-Subject: [PATCH] realtek: Add support for RTL9300/RTL9310 I2C controller
-
-This adds support for the RTL9300 and RTL9310 I2C controller.
-The controller implements the SMBus protocol for SMBus transfers
-over an I2C bus. The driver supports selecting one of the 2 possible
-SCL pins and any of the 8 possible SDA pins. Bus speeds of
-100kHz (standard speed) and 400kHz (high speed I2C) are supported.
-
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- drivers/i2c/busses/Kconfig | 10 +++++++++
- drivers/i2c/busses/Makefile | 1 +
- 2 files changed, 11 insertions(+)
-
---- a/drivers/i2c/busses/Kconfig
-+++ b/drivers/i2c/busses/Kconfig
-@@ -954,6 +954,16 @@ config I2C_RK3X
- This driver can also be built as a module. If so, the module will
- be called i2c-rk3x.
-
-+config I2C_RTL9300
-+ tristate "Realtek RTL9300 I2C adapter"
-+ depends on OF
-+ help
-+ Say Y here to include support for the I2C adapter in Realtek RTL9300
-+ and RTL9310 SoCs.
-+
-+ This driver can also be built as a module. If so, the module will
-+ be called i2c-rtl9300.
-+
- config HAVE_S3C2410_I2C
- bool
- help
---- a/drivers/i2c/busses/Makefile
-+++ b/drivers/i2c/busses/Makefile
-@@ -95,6 +95,7 @@ obj-$(CONFIG_I2C_QCOM_GENI) += i2c-qcom-
- obj-$(CONFIG_I2C_QUP) += i2c-qup.o
- obj-$(CONFIG_I2C_RIIC) += i2c-riic.o
- obj-$(CONFIG_I2C_RK3X) += i2c-rk3x.o
-+obj-$(CONFIG_I2C_RTL9300) += i2c-rtl9300.o
- obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o
- obj-$(CONFIG_I2C_SH7760) += i2c-sh7760.o
- obj-$(CONFIG_I2C_SH_MOBILE) += i2c-sh_mobile.o
diff --git a/target/linux/realtek/patches-5.10/311-add-i2c-mux-rtl9300-support.patch b/target/linux/realtek/patches-5.10/311-add-i2c-mux-rtl9300-support.patch
deleted file mode 100644
index d0bfba4538..0000000000
--- a/target/linux/realtek/patches-5.10/311-add-i2c-mux-rtl9300-support.patch
+++ /dev/null
@@ -1,46 +0,0 @@
-From f4bdb7fdccdfe3fa382abe77f72a16c2f2e6add0 Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Sat, 11 Dec 2021 20:25:37 +0100
-Subject: [PATCH] realtek: Add support for RTL9300/RTL9310 I2C multiplexing
-
-The RTL9300/RTL9310 I2C controllers have support for 2 independent I2C
-masters, each with a fixed SCL pin, that cannot be changed. Each of these
-masters can use 8 (RTL9300) or 16 (RTL9310) different pins for SDA.
-This multiplexer directly controls the two masters and their shared
-IO configuration registers to allow multiplexing between any of these
-busses. The two masters cannot be used in parallel as the multiplex
-is protected by a standard multiplex lock.
-
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- drivers/i2c/muxes/Kconfig | 9 +++++++
- drivers/i2c/muxes/Makefile | 1 +
- 2 files changed, 10 insertions(+)
-
---- a/drivers/i2c/muxes/Kconfig
-+++ b/drivers/i2c/muxes/Kconfig
-@@ -99,6 +99,15 @@ config I2C_MUX_REG
- This driver can also be built as a module. If so, the module
- will be called i2c-mux-reg.
-
-+config I2C_MUX_RTL9300
-+ tristate "RTL9300 based I2C multiplexer"
-+ help
-+ If you say yes to this option, support will be included for a
-+ RTL9300 based I2C multiplexer.
-+
-+ This driver can also be built as a module. If so, the module
-+ will be called i2c-mux-reg.
-+
- config I2C_DEMUX_PINCTRL
- tristate "pinctrl-based I2C demultiplexer"
- depends on PINCTRL && OF
---- a/drivers/i2c/muxes/Makefile
-+++ b/drivers/i2c/muxes/Makefile
-@@ -14,5 +14,6 @@ obj-$(CONFIG_I2C_MUX_PCA9541) += i2c-mux
- obj-$(CONFIG_I2C_MUX_PCA954x) += i2c-mux-pca954x.o
- obj-$(CONFIG_I2C_MUX_PINCTRL) += i2c-mux-pinctrl.o
- obj-$(CONFIG_I2C_MUX_REG) += i2c-mux-reg.o
-+obj-$(CONFIG_I2C_MUX_RTL9300) += i2c-mux-rtl9300.o
-
- ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/target/linux/realtek/patches-5.10/315-irqchip-irq-realtek-rtl-add-VPE-support.patch b/target/linux/realtek/patches-5.10/315-irqchip-irq-realtek-rtl-add-VPE-support.patch
deleted file mode 100644
index 26c36302c2..0000000000
--- a/target/linux/realtek/patches-5.10/315-irqchip-irq-realtek-rtl-add-VPE-support.patch
+++ /dev/null
@@ -1,407 +0,0 @@
-From 6c18e9c491959ac0674ebe36b09f9ddc3f2c9bce Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Fri, 31 Dec 2021 11:56:49 +0100
-Subject: [PATCH] realtek: Add VPE support for the IRQ driver
-
-In order to support VSMP, enable support for both VPEs
-of the RTL839X and RTL930X SoCs in the irq-realtek-rtl
-driver. Add support for IRQ affinity setting.
-
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- drivers/irqchip/irq-realtek-rtl.c | 152 +++++++++++++++---
- 1 file changed, 73 insertions(+), 76 deletions(-)
-
---- a/drivers/irqchip/irq-realtek-rtl.c
-+++ b/drivers/irqchip/irq-realtek-rtl.c
-@@ -21,21 +21,63 @@
- #define RTL_ICTL_IRR2 0x10
- #define RTL_ICTL_IRR3 0x14
-
--#define REG(x) (realtek_ictl_base + x)
-+#define RTL_ICTL_NUM_INPUTS 32
-+#define RTL_ICTL_NUM_OUTPUTS 15
-
- static DEFINE_RAW_SPINLOCK(irq_lock);
--static void __iomem *realtek_ictl_base;
-+
-+#define REG(offset, cpu) (realtek_ictl_base[cpu] + offset)
-+
-+static void __iomem *realtek_ictl_base[NR_CPUS];
-+static cpumask_t realtek_ictl_cpu_configurable;
-+
-+struct realtek_ictl_output {
-+ /* IRQ controller data */
-+ struct fwnode_handle *fwnode;
-+ /* Output specific data */
-+ unsigned int output_index;
-+ struct irq_domain *domain;
-+ u32 child_mask;
-+};
-+
-+/*
-+ * IRR0-IRR3 store 4 bits per interrupt, but Realtek uses inverted numbering,
-+ * placing IRQ 31 in the first four bits. A routing value of '0' means the
-+ * interrupt is left disconnected. Routing values {1..15} connect to output
-+ * lines {0..14}.
-+ */
-+#define IRR_OFFSET(idx) (4 * (3 - (idx * 4) / 32))
-+#define IRR_SHIFT(idx) ((idx * 4) % 32)
-+
-+static inline u32 read_irr(void __iomem *irr0, int idx)
-+{
-+ return (readl(irr0 + IRR_OFFSET(idx)) >> IRR_SHIFT(idx)) & 0xf;
-+}
-+
-+static inline void write_irr(void __iomem *irr0, int idx, u32 value)
-+{
-+ unsigned int offset = IRR_OFFSET(idx);
-+ unsigned int shift = IRR_SHIFT(idx);
-+ u32 irr;
-+
-+ irr = readl(irr0 + offset) & ~(0xf << shift);
-+ irr |= (value & 0xf) << shift;
-+ writel(irr, irr0 + offset);
-+}
-
- static void realtek_ictl_unmask_irq(struct irq_data *i)
- {
- unsigned long flags;
- u32 value;
-+ int cpu;
-
- raw_spin_lock_irqsave(&irq_lock, flags);
-
-- value = readl(REG(RTL_ICTL_GIMR));
-- value |= BIT(i->hwirq);
-- writel(value, REG(RTL_ICTL_GIMR));
-+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable) {
-+ value = readl(REG(RTL_ICTL_GIMR, cpu));
-+ value |= BIT(i->hwirq);
-+ writel(value, REG(RTL_ICTL_GIMR, cpu));
-+ }
-
- raw_spin_unlock_irqrestore(&irq_lock, flags);
- }
-@@ -44,137 +86,247 @@ static void realtek_ictl_mask_irq(struct
- {
- unsigned long flags;
- u32 value;
-+ int cpu;
-
- raw_spin_lock_irqsave(&irq_lock, flags);
-
-- value = readl(REG(RTL_ICTL_GIMR));
-- value &= ~BIT(i->hwirq);
-- writel(value, REG(RTL_ICTL_GIMR));
-+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable) {
-+ value = readl(REG(RTL_ICTL_GIMR, cpu));
-+ value &= ~BIT(i->hwirq);
-+ writel(value, REG(RTL_ICTL_GIMR, cpu));
-+ }
-
- raw_spin_unlock_irqrestore(&irq_lock, flags);
- }
-
-+static int __maybe_unused realtek_ictl_irq_affinity(struct irq_data *i,
-+ const struct cpumask *dest, bool force)
-+{
-+ struct realtek_ictl_output *output = i->domain->host_data;
-+ cpumask_t cpu_configure;
-+ cpumask_t cpu_disable;
-+ cpumask_t cpu_enable;
-+ unsigned long flags;
-+ int cpu;
-+
-+ raw_spin_lock_irqsave(&irq_lock, flags);
-+
-+ cpumask_and(&cpu_configure, cpu_present_mask, &realtek_ictl_cpu_configurable);
-+
-+ cpumask_and(&cpu_enable, &cpu_configure, dest);
-+ cpumask_andnot(&cpu_disable, &cpu_configure, dest);
-+
-+ for_each_cpu(cpu, &cpu_disable)
-+ write_irr(REG(RTL_ICTL_IRR0, cpu), i->hwirq, 0);
-+
-+ for_each_cpu(cpu, &cpu_enable)
-+ write_irr(REG(RTL_ICTL_IRR0, cpu), i->hwirq, output->output_index + 1);
-+
-+ irq_data_update_effective_affinity(i, &cpu_enable);
-+
-+ raw_spin_unlock_irqrestore(&irq_lock, flags);
-+
-+ return IRQ_SET_MASK_OK;
-+}
-+
- static struct irq_chip realtek_ictl_irq = {
- .name = "realtek-rtl-intc",
- .irq_mask = realtek_ictl_mask_irq,
- .irq_unmask = realtek_ictl_unmask_irq,
-+#ifdef CONFIG_SMP
-+ .irq_set_affinity = realtek_ictl_irq_affinity,
-+#endif
- };
-
- static int intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
- {
-- irq_set_chip_and_handler(hw, &realtek_ictl_irq, handle_level_irq);
-+ struct realtek_ictl_output *output = d->host_data;
-+ unsigned long flags;
-+
-+ irq_set_chip_and_handler(irq, &realtek_ictl_irq, handle_level_irq);
-+
-+ raw_spin_lock_irqsave(&irq_lock, flags);
-+
-+ output->child_mask |= BIT(hw);
-+ write_irr(REG(RTL_ICTL_IRR0, 0), hw, output->output_index + 1);
-+
-+ raw_spin_unlock_irqrestore(&irq_lock, flags);
-
- return 0;
- }
-
-+static int intc_select(struct irq_domain *d, struct irq_fwspec *fwspec,
-+ enum irq_domain_bus_token bus_token)
-+{
-+ struct realtek_ictl_output *output = d->host_data;
-+ bool routed_elsewhere;
-+ unsigned long flags;
-+ u32 routing_old;
-+ int cpu;
-+
-+ if (fwspec->fwnode != output->fwnode)
-+ return false;
-+
-+ /* Original specifiers had only one parameter */
-+ if (fwspec->param_count < 2)
-+ return true;
-+
-+ raw_spin_lock_irqsave(&irq_lock, flags);
-+
-+ /*
-+ * Inputs can only be routed to one output, so they shouldn't be
-+ * allowed to end up in multiple domains.
-+ */
-+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable) {
-+ routing_old = read_irr(REG(RTL_ICTL_IRR0, cpu), fwspec->param[0]);
-+ routed_elsewhere = routing_old && fwspec->param[1] != routing_old - 1;
-+ if (routed_elsewhere) {
-+ pr_warn("soc int %d already routed to output %d\n",
-+ fwspec->param[0], routing_old - 1);
-+ break;
-+ }
-+ }
-+
-+ raw_spin_unlock_irqrestore(&irq_lock, flags);
-+
-+ return !routed_elsewhere && fwspec->param[1] == output->output_index;
-+}
-+
- static const struct irq_domain_ops irq_domain_ops = {
- .map = intc_map,
-+ .select = intc_select,
- .xlate = irq_domain_xlate_onecell,
- };
-
- static void realtek_irq_dispatch(struct irq_desc *desc)
- {
-+ struct realtek_ictl_output *output = irq_desc_get_handler_data(desc);
- struct irq_chip *chip = irq_desc_get_chip(desc);
-- struct irq_domain *domain;
-- unsigned int pending;
-+ int cpu = smp_processor_id();
-+ unsigned long pending;
-+ unsigned int soc_int;
-
- chained_irq_enter(chip, desc);
-- pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));
-+ pending = readl(REG(RTL_ICTL_GIMR, cpu)) & readl(REG(RTL_ICTL_GISR, cpu))
-+ & output->child_mask;
-+
- if (unlikely(!pending)) {
- spurious_interrupt();
- goto out;
- }
-- domain = irq_desc_get_handler_data(desc);
-- generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
-+
-+ for_each_set_bit(soc_int, &pending, RTL_ICTL_NUM_INPUTS)
-+ generic_handle_irq(irq_find_mapping(output->domain, soc_int));
-+// generic_handle_domain_irq(output->domain, soc_int);
-
- out:
- chained_irq_exit(chip, desc);
- }
-
--/*
-- * SoC interrupts are cascaded to MIPS CPU interrupts according to the
-- * interrupt-map in the device tree. Each SoC interrupt gets 4 bits for
-- * the CPU interrupt in an Interrupt Routing Register. Max 32 SoC interrupts
-- * thus go into 4 IRRs.
-- */
--static int __init map_interrupts(struct device_node *node, struct irq_domain *domain)
-+static int __init setup_parent_interrupts(struct device_node *node, int *parents,
-+ unsigned int num_parents)
- {
-- struct device_node *cpu_ictl;
-- const __be32 *imap;
-- u32 imaplen, soc_int, cpu_int, tmp, regs[4];
-- int ret, i, irr_regs[] = {
-- RTL_ICTL_IRR3,
-- RTL_ICTL_IRR2,
-- RTL_ICTL_IRR1,
-- RTL_ICTL_IRR0,
-- };
-- u8 mips_irqs_set;
-+ struct realtek_ictl_output *outputs;
-+ struct realtek_ictl_output *output;
-+ struct irq_domain *domain;
-+ unsigned int p;
-
-- ret = of_property_read_u32(node, "#address-cells", &tmp);
-- if (ret || tmp)
-- return -EINVAL;
-+ outputs = kcalloc(num_parents, sizeof(*outputs), GFP_KERNEL);
-+ if (!outputs)
-+ return -ENOMEM;
-
-- imap = of_get_property(node, "interrupt-map", &imaplen);
-- if (!imap || imaplen % 3)
-- return -EINVAL;
-+ for (p = 0; p < num_parents; p++) {
-+ output = outputs + p;
-
-- mips_irqs_set = 0;
-- memset(regs, 0, sizeof(regs));
-- for (i = 0; i < imaplen; i += 3 * sizeof(u32)) {
-- soc_int = be32_to_cpup(imap);
-- if (soc_int > 31)
-- return -EINVAL;
--
-- cpu_ictl = of_find_node_by_phandle(be32_to_cpup(imap + 1));
-- if (!cpu_ictl)
-- return -EINVAL;
-- ret = of_property_read_u32(cpu_ictl, "#interrupt-cells", &tmp);
-- if (ret || tmp != 1)
-- return -EINVAL;
-- of_node_put(cpu_ictl);
--
-- cpu_int = be32_to_cpup(imap + 2);
-- if (cpu_int > 7)
-- return -EINVAL;
--
-- if (!(mips_irqs_set & BIT(cpu_int))) {
-- irq_set_chained_handler_and_data(cpu_int, realtek_irq_dispatch,
-- domain);
-- mips_irqs_set |= BIT(cpu_int);
-- }
-+ domain = irq_domain_add_linear(node, RTL_ICTL_NUM_INPUTS, &irq_domain_ops, output);
-+ if (!domain)
-+ goto domain_err;
-
-- regs[(soc_int * 4) / 32] |= cpu_int << (soc_int * 4) % 32;
-- imap += 3;
-- }
-+ output->fwnode = of_node_to_fwnode(node);
-+ output->output_index = p;
-+ output->domain = domain;
-
-- for (i = 0; i < 4; i++)
-- writel(regs[i], REG(irr_regs[i]));
-+ irq_set_chained_handler_and_data(parents[p], realtek_irq_dispatch, output);
-+ }
-
- return 0;
-+
-+domain_err:
-+ while (p--) {
-+ irq_set_chained_handler_and_data(parents[p], NULL, NULL);
-+ irq_domain_remove(outputs[p].domain);
-+ }
-+
-+ kfree(outputs);
-+
-+ return -ENOMEM;
- }
-
- static int __init realtek_rtl_of_init(struct device_node *node, struct device_node *parent)
- {
-- struct irq_domain *domain;
-- int ret;
-+ int parent_irqs[RTL_ICTL_NUM_OUTPUTS];
-+ struct of_phandle_args oirq;
-+ unsigned int num_parents;
-+ unsigned int soc_irq;
-+ unsigned int p;
-+ int cpu;
-+
-+ cpumask_clear(&realtek_ictl_cpu_configurable);
-+
-+ for (cpu = 0; cpu < NR_CPUS; cpu++) {
-+ realtek_ictl_base[cpu] = of_iomap(node, cpu);
-+ if (realtek_ictl_base[cpu]) {
-+ cpumask_set_cpu(cpu, &realtek_ictl_cpu_configurable);
-+
-+ /* Disable all cascaded interrupts and clear routing */
-+ writel(0, REG(RTL_ICTL_GIMR, cpu));
-+ for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++)
-+ write_irr(REG(RTL_ICTL_IRR0, cpu), soc_irq, 0);
-+ }
-+ }
-
-- realtek_ictl_base = of_iomap(node, 0);
-- if (!realtek_ictl_base)
-+ if (cpumask_empty(&realtek_ictl_cpu_configurable))
- return -ENXIO;
-
-- /* Disable all cascaded interrupts */
-- writel(0, REG(RTL_ICTL_GIMR));
-+ num_parents = of_irq_count(node);
-+ if (num_parents > RTL_ICTL_NUM_OUTPUTS) {
-+ pr_err("too many parent interrupts\n");
-+ return -EINVAL;
-+ }
-
-- domain = irq_domain_add_simple(node, 32, 0,
-- &irq_domain_ops, NULL);
-+ for (p = 0; p < num_parents; p++)
-+ parent_irqs[p] = of_irq_get(node, p);
-
-- ret = map_interrupts(node, domain);
-- if (ret) {
-- pr_err("invalid interrupt map\n");
-- return ret;
-+ if (WARN_ON(!num_parents)) {
-+ /*
-+ * If DT contains no parent interrupts, assume MIPS CPU IRQ 2
-+ * (HW0) is connected to the first output. This is the case for
-+ * all known hardware anyway. "interrupt-map" is deprecated, so
-+ * don't bother trying to parse that.
-+ * Since this is to account for old devicetrees with one-cell
-+ * interrupt specifiers, only one output domain is needed.
-+ */
-+ oirq.np = of_find_compatible_node(NULL, NULL, "mti,cpu-interrupt-controller");
-+ if (oirq.np) {
-+ oirq.args_count = 1;
-+ oirq.args[0] = 2;
-+
-+ parent_irqs[0] = irq_create_of_mapping(&oirq);
-+ num_parents = 1;
-+ }
-+
-+ of_node_put(oirq.np);
- }
-
-- return 0;
-+ /* Ensure we haven't collected any errors before proceeding */
-+ for (p = 0; p < num_parents; p++) {
-+ if (parent_irqs[p] < 0)
-+ return parent_irqs[p];
-+ if (!parent_irqs[p])
-+ return -ENODEV;
-+ }
-+
-+ return setup_parent_interrupts(node, &parent_irqs[0], num_parents);
- }
-
- IRQCHIP_DECLARE(realtek_rtl_intc, "realtek,rtl-intc", realtek_rtl_of_init);
diff --git a/target/linux/realtek/patches-5.10/316-otto-gpio-uniprocessor-irq-mask.patch b/target/linux/realtek/patches-5.10/316-otto-gpio-uniprocessor-irq-mask.patch
deleted file mode 100644
index 3980875dd4..0000000000
--- a/target/linux/realtek/patches-5.10/316-otto-gpio-uniprocessor-irq-mask.patch
+++ /dev/null
@@ -1,51 +0,0 @@
-From bde6311569ef25a00c3beaeabfd6b78b19651872 Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sun, 29 May 2022 19:38:09 +0200
-Subject: [PATCH] realtek: don't unmask non-maskable GPIO IRQs
-
-On uniprocessor builds, for_each_cpu(cpu, mask) will assume 'mask'
-always contains exactly one CPU, and ignore the actual mask contents.
-This causes the loop to run, even when it shouldn't on an empty mask,
-and tries to access an uninitialised pointer.
-
-Fix this by wrapping the loop in a cpumask_empty() check, to ensure it
-will not run on uniprocessor builds if the CPU mask is empty.
-
-Fixes: af6cd37f42f3 ("realtek: replace RTL93xx GPIO patches")
-Reported-by: INAGAKI Hiroshi <musashino.open@gmail.com>
-Reported-by: Robert Marko <robimarko@gmail.com>
-Tested-by: Robert Marko <robimarko@gmail.com>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
----
- drivers/gpio/gpio-realtek-otto.c | 9 +++++++++++--
- 1 file changed, 11 insertions(+), 2 deletions(-)
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -304,6 +304,7 @@ static int realtek_gpio_irq_set_affinity
- static int realtek_gpio_irq_init(struct gpio_chip *gc)
- {
- struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
-+ void __iomem *irq_cpu_mask;
- unsigned int port;
- int cpu;
-
-@@ -311,8 +312,16 @@ static int realtek_gpio_irq_init(struct
- realtek_gpio_write_imr(ctrl, port, 0, 0);
- realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
-
-- for_each_cpu(cpu, &ctrl->cpu_irq_maskable)
-- iowrite8(GENMASK(7, 0), realtek_gpio_irq_cpu_mask(ctrl, port, cpu));
-+ /*
-+ * Uniprocessor builds assume a mask always contains one CPU,
-+ * so only start the loop if we have at least one maskable CPU.
-+ */
-+ if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
-+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
-+ irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
-+ iowrite8(GENMASK(7, 0), irq_cpu_mask);
-+ }
-+ }
- }
-
- return 0;
diff --git a/target/linux/realtek/patches-5.10/317-gpio-realtek-otto-switch-to-32-bit-I-O.patch b/target/linux/realtek/patches-5.10/317-gpio-realtek-otto-switch-to-32-bit-I-O.patch
deleted file mode 100644
index 9c043b7126..0000000000
--- a/target/linux/realtek/patches-5.10/317-gpio-realtek-otto-switch-to-32-bit-I-O.patch
+++ /dev/null
@@ -1,373 +0,0 @@
-From ee0175b3b44288c74d5292c2a9c2c154f6c0317e Mon Sep 17 00:00:00 2001
-From: Sander Vanheule <sander@svanheule.net>
-Date: Sun, 7 Aug 2022 21:21:15 +0200
-Subject: [PATCH] gpio: realtek-otto: switch to 32-bit I/O
-
-By using 16-bit I/O on the GPIO peripheral, which is apparently not safe
-on MIPS, the IMR can end up containing garbage. This then results in
-interrupt triggers for lines that don't have an interrupt handler
-associated. The irq_desc lookup fails, and the ISR will not be cleared,
-keeping the CPU busy until reboot, or until another IMR operation
-restores the correct value. This situation appears to happen very
-rarely, for < 0.5% of IMR writes.
-
-Instead of using 8-bit or 16-bit I/O operations on the 32-bit memory
-mapped peripheral registers, switch to using 32-bit I/O only, operating
-on the entire bank for all single bit line settings. For 2-bit line
-settings, with 16-bit port values, stick to manual (un)packing.
-
-This issue has been seen on RTL8382M (HPE 1920-16G), RTL8391M (Netgear
-GS728TP v2), and RTL8393M (D-Link DGS-1210-52 F3, Zyxel GS1900-48).
-
-Reported-by: Luiz Angelo Daros de Luca <luizluca@gmail.com> # DGS-1210-52
-Reported-by: Birger Koblitz <mail@birger-koblitz.de> # GS728TP
-Reported-by: Jan Hoffmann <jan@3e8.eu> # 1920-16G
-Fixes: 0d82fb1127fb ("gpio: Add Realtek Otto GPIO support")
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-Cc: Paul Cercueil <paul@crapouillou.net>
-Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
-Signed-off-by: Bartosz Golaszewski <brgl@bgdev.pl>
-
-Update patch for missing upstream changes:
- - commit a01a40e33499 ("gpio: realtek-otto: Make the irqchip immutable")
- - commit dbd1c54fc820 ("gpio: Bulk conversion to generic_handle_domain_irq()")
-Signed-off-by: Sander Vanheule <sander@svanheule.net>
-
----
- drivers/gpio/gpio-realtek-otto.c | 166 ++++++++++++++++---------------
- 1 file changed, 85 insertions(+), 81 deletions(-)
-
---- a/drivers/gpio/gpio-realtek-otto.c
-+++ b/drivers/gpio/gpio-realtek-otto.c
-@@ -46,10 +46,20 @@
- * @lock: Lock for accessing the IRQ registers and values
- * @intr_mask: Mask for interrupts lines
- * @intr_type: Interrupt type selection
-+ * @bank_read: Read a bank setting as a single 32-bit value
-+ * @bank_write: Write a bank setting as a single 32-bit value
-+ * @imr_line_pos: Bit shift of an IRQ line's IMR value.
-+ *
-+ * The DIR, DATA, and ISR registers consist of four 8-bit port values, packed
-+ * into a single 32-bit register. Use @bank_read (@bank_write) to get (assign)
-+ * a value from (to) these registers. The IMR register consists of four 16-bit
-+ * port values, packed into two 32-bit registers. Use @imr_line_pos to get the
-+ * bit shift of the 2-bit field for a line's IMR settings. Shifts larger than
-+ * 32 overflow into the second register.
- *
- * Because the interrupt mask register (IMR) combines the function of IRQ type
- * selection and masking, two extra values are stored. @intr_mask is used to
-- * mask/unmask the interrupts for a GPIO port, and @intr_type is used to store
-+ * mask/unmask the interrupts for a GPIO line, and @intr_type is used to store
- * the selected interrupt types. The logical AND of these values is written to
- * IMR on changes.
- */
-@@ -59,10 +69,11 @@ struct realtek_gpio_ctrl {
- void __iomem *cpumask_base;
- struct cpumask cpu_irq_maskable;
- raw_spinlock_t lock;
-- u16 intr_mask[REALTEK_GPIO_PORTS_PER_BANK];
-- u16 intr_type[REALTEK_GPIO_PORTS_PER_BANK];
-- unsigned int (*port_offset_u8)(unsigned int port);
-- unsigned int (*port_offset_u16)(unsigned int port);
-+ u8 intr_mask[REALTEK_GPIO_MAX];
-+ u8 intr_type[REALTEK_GPIO_MAX];
-+ u32 (*bank_read)(void __iomem *reg);
-+ void (*bank_write)(void __iomem *reg, u32 value);
-+ unsigned int (*line_imr_pos)(unsigned int line);
- };
-
- /* Expand with more flags as devices with other quirks are added */
-@@ -101,14 +112,22 @@ static struct realtek_gpio_ctrl *irq_dat
- * port. The two interrupt mask registers store two bits per GPIO, so use u16
- * values.
- */
--static unsigned int realtek_gpio_port_offset_u8(unsigned int port)
-+static u32 realtek_gpio_bank_read_swapped(void __iomem *reg)
-+{
-+ return ioread32be(reg);
-+}
-+
-+static void realtek_gpio_bank_write_swapped(void __iomem *reg, u32 value)
- {
-- return port;
-+ iowrite32be(value, reg);
- }
-
--static unsigned int realtek_gpio_port_offset_u16(unsigned int port)
-+static unsigned int realtek_gpio_line_imr_pos_swapped(unsigned int line)
- {
-- return 2 * port;
-+ unsigned int port_pin = line % 8;
-+ unsigned int port = line / 8;
-+
-+ return 2 * (8 * (port ^ 1) + port_pin);
- }
-
- /*
-@@ -119,64 +138,65 @@ static unsigned int realtek_gpio_port_of
- * per GPIO, so use u16 values. The first register contains ports 1 and 0, the
- * second ports 3 and 2.
- */
--static unsigned int realtek_gpio_port_offset_u8_rev(unsigned int port)
-+static u32 realtek_gpio_bank_read(void __iomem *reg)
- {
-- return 3 - port;
-+ return ioread32(reg);
- }
-
--static unsigned int realtek_gpio_port_offset_u16_rev(unsigned int port)
-+static void realtek_gpio_bank_write(void __iomem *reg, u32 value)
- {
-- return 2 * (port ^ 1);
-+ iowrite32(value, reg);
- }
-
--static void realtek_gpio_write_imr(struct realtek_gpio_ctrl *ctrl,
-- unsigned int port, u16 irq_type, u16 irq_mask)
-+static unsigned int realtek_gpio_line_imr_pos(unsigned int line)
- {
-- iowrite16(irq_type & irq_mask,
-- ctrl->base + REALTEK_GPIO_REG_IMR + ctrl->port_offset_u16(port));
-+ return 2 * line;
- }
-
--static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl,
-- unsigned int port, u8 mask)
-+static void realtek_gpio_clear_isr(struct realtek_gpio_ctrl *ctrl, u32 mask)
- {
-- iowrite8(mask, ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
-+ ctrl->bank_write(ctrl->base + REALTEK_GPIO_REG_ISR, mask);
- }
-
--static u8 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl, unsigned int port)
-+static u32 realtek_gpio_read_isr(struct realtek_gpio_ctrl *ctrl)
- {
-- return ioread8(ctrl->base + REALTEK_GPIO_REG_ISR + ctrl->port_offset_u8(port));
-+ return ctrl->bank_read(ctrl->base + REALTEK_GPIO_REG_ISR);
- }
-
--/* Set the rising and falling edge mask bits for a GPIO port pin */
--static u16 realtek_gpio_imr_bits(unsigned int pin, u16 value)
-+/* Set the rising and falling edge mask bits for a GPIO pin */
-+static void realtek_gpio_update_line_imr(struct realtek_gpio_ctrl *ctrl, unsigned int line)
- {
-- return (value & REALTEK_GPIO_IMR_LINE_MASK) << 2 * pin;
-+ void __iomem *reg = ctrl->base + REALTEK_GPIO_REG_IMR;
-+ unsigned int line_shift = ctrl->line_imr_pos(line);
-+ unsigned int shift = line_shift % 32;
-+ u32 irq_type = ctrl->intr_type[line];
-+ u32 irq_mask = ctrl->intr_mask[line];
-+ u32 reg_val;
-+
-+ reg += 4 * (line_shift / 32);
-+ reg_val = ioread32(reg);
-+ reg_val &= ~(REALTEK_GPIO_IMR_LINE_MASK << shift);
-+ reg_val |= (irq_type & irq_mask & REALTEK_GPIO_IMR_LINE_MASK) << shift;
-+ iowrite32(reg_val, reg);
- }
-
- static void realtek_gpio_irq_ack(struct irq_data *data)
- {
- struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
- irq_hw_number_t line = irqd_to_hwirq(data);
-- unsigned int port = line / 8;
-- unsigned int port_pin = line % 8;
-
-- realtek_gpio_clear_isr(ctrl, port, BIT(port_pin));
-+ realtek_gpio_clear_isr(ctrl, BIT(line));
- }
-
- static void realtek_gpio_irq_unmask(struct irq_data *data)
- {
- struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
- unsigned int line = irqd_to_hwirq(data);
-- unsigned int port = line / 8;
-- unsigned int port_pin = line % 8;
- unsigned long flags;
-- u16 m;
-
- raw_spin_lock_irqsave(&ctrl->lock, flags);
-- m = ctrl->intr_mask[port];
-- m |= realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-- ctrl->intr_mask[port] = m;
-- realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
-+ ctrl->intr_mask[line] = REALTEK_GPIO_IMR_LINE_MASK;
-+ realtek_gpio_update_line_imr(ctrl, line);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
- }
-
-@@ -184,16 +204,11 @@ static void realtek_gpio_irq_mask(struct
- {
- struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
- unsigned int line = irqd_to_hwirq(data);
-- unsigned int port = line / 8;
-- unsigned int port_pin = line % 8;
- unsigned long flags;
-- u16 m;
-
- raw_spin_lock_irqsave(&ctrl->lock, flags);
-- m = ctrl->intr_mask[port];
-- m &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-- ctrl->intr_mask[port] = m;
-- realtek_gpio_write_imr(ctrl, port, ctrl->intr_type[port], m);
-+ ctrl->intr_mask[line] = 0;
-+ realtek_gpio_update_line_imr(ctrl, line);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
- }
-
-@@ -201,10 +216,8 @@ static int realtek_gpio_irq_set_type(str
- {
- struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
- unsigned int line = irqd_to_hwirq(data);
-- unsigned int port = line / 8;
-- unsigned int port_pin = line % 8;
- unsigned long flags;
-- u16 type, t;
-+ u8 type;
-
- switch (flow_type & IRQ_TYPE_SENSE_MASK) {
- case IRQ_TYPE_EDGE_FALLING:
-@@ -223,11 +236,8 @@ static int realtek_gpio_irq_set_type(str
- irq_set_handler_locked(data, handle_edge_irq);
-
- raw_spin_lock_irqsave(&ctrl->lock, flags);
-- t = ctrl->intr_type[port];
-- t &= ~realtek_gpio_imr_bits(port_pin, REALTEK_GPIO_IMR_LINE_MASK);
-- t |= realtek_gpio_imr_bits(port_pin, type);
-- ctrl->intr_type[port] = t;
-- realtek_gpio_write_imr(ctrl, port, t, ctrl->intr_mask[port]);
-+ ctrl->intr_type[line] = type;
-+ realtek_gpio_update_line_imr(ctrl, line);
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-
- return 0;
-@@ -238,31 +248,24 @@ static void realtek_gpio_irq_handler(str
- struct gpio_chip *gc = irq_desc_get_handler_data(desc);
- struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
- struct irq_chip *irq_chip = irq_desc_get_chip(desc);
-- unsigned int lines_done;
-- unsigned int port_pin_count;
- unsigned int irq;
- unsigned long status;
- int offset;
-
- chained_irq_enter(irq_chip, desc);
-
-- for (lines_done = 0; lines_done < gc->ngpio; lines_done += 8) {
-- status = realtek_gpio_read_isr(ctrl, lines_done / 8);
-- port_pin_count = min(gc->ngpio - lines_done, 8U);
-- for_each_set_bit(offset, &status, port_pin_count) {
-- irq = irq_find_mapping(gc->irq.domain, offset + lines_done);
-- generic_handle_irq(irq);
-- }
-+ status = realtek_gpio_read_isr(ctrl);
-+ for_each_set_bit(offset, &status, gc->ngpio) {
-+ irq = irq_find_mapping(gc->irq.domain, offset);
-+ generic_handle_irq(irq);
- }
-
- chained_irq_exit(irq_chip, desc);
- }
-
--static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl,
-- unsigned int port, int cpu)
-+static inline void __iomem *realtek_gpio_irq_cpu_mask(struct realtek_gpio_ctrl *ctrl, int cpu)
- {
-- return ctrl->cpumask_base + ctrl->port_offset_u8(port) +
-- REALTEK_GPIO_PORTS_PER_BANK * cpu;
-+ return ctrl->cpumask_base + REALTEK_GPIO_PORTS_PER_BANK * cpu;
- }
-
- static int realtek_gpio_irq_set_affinity(struct irq_data *data,
-@@ -270,12 +273,10 @@ static int realtek_gpio_irq_set_affinity
- {
- struct realtek_gpio_ctrl *ctrl = irq_data_to_ctrl(data);
- unsigned int line = irqd_to_hwirq(data);
-- unsigned int port = line / 8;
-- unsigned int port_pin = line % 8;
- void __iomem *irq_cpu_mask;
- unsigned long flags;
- int cpu;
-- u8 v;
-+ u32 v;
-
- if (!ctrl->cpumask_base)
- return -ENXIO;
-@@ -283,15 +284,15 @@ static int realtek_gpio_irq_set_affinity
- raw_spin_lock_irqsave(&ctrl->lock, flags);
-
- for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
-- irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
-- v = ioread8(irq_cpu_mask);
-+ irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
-+ v = ctrl->bank_read(irq_cpu_mask);
-
- if (cpumask_test_cpu(cpu, dest))
-- v |= BIT(port_pin);
-+ v |= BIT(line);
- else
-- v &= ~BIT(port_pin);
-+ v &= ~BIT(line);
-
-- iowrite8(v, irq_cpu_mask);
-+ ctrl->bank_write(irq_cpu_mask, v);
- }
-
- raw_spin_unlock_irqrestore(&ctrl->lock, flags);
-@@ -305,22 +306,23 @@ static int realtek_gpio_irq_init(struct
- {
- struct realtek_gpio_ctrl *ctrl = gpiochip_get_data(gc);
- void __iomem *irq_cpu_mask;
-- unsigned int port;
-+ u32 mask_all = GENMASK(gc->ngpio - 1, 0);
-+ unsigned int line;
- int cpu;
-
-- for (port = 0; (port * 8) < gc->ngpio; port++) {
-- realtek_gpio_write_imr(ctrl, port, 0, 0);
-- realtek_gpio_clear_isr(ctrl, port, GENMASK(7, 0));
--
-- /*
-- * Uniprocessor builds assume a mask always contains one CPU,
-- * so only start the loop if we have at least one maskable CPU.
-- */
-- if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
-- for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
-- irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, port, cpu);
-- iowrite8(GENMASK(7, 0), irq_cpu_mask);
-- }
-+ for (line = 0; line < gc->ngpio; line++)
-+ realtek_gpio_update_line_imr(ctrl, line);
-+
-+ realtek_gpio_clear_isr(ctrl, mask_all);
-+
-+ /*
-+ * Uniprocessor builds assume a mask always contains one CPU,
-+ * so only start the loop if we have at least one maskable CPU.
-+ */
-+ if(!cpumask_empty(&ctrl->cpu_irq_maskable)) {
-+ for_each_cpu(cpu, &ctrl->cpu_irq_maskable) {
-+ irq_cpu_mask = realtek_gpio_irq_cpu_mask(ctrl, cpu);
-+ ctrl->bank_write(irq_cpu_mask, mask_all);
- }
- }
-
-@@ -393,12 +395,14 @@ static int realtek_gpio_probe(struct pla
-
- if (dev_flags & GPIO_PORTS_REVERSED) {
- bgpio_flags = 0;
-- ctrl->port_offset_u8 = realtek_gpio_port_offset_u8_rev;
-- ctrl->port_offset_u16 = realtek_gpio_port_offset_u16_rev;
-+ ctrl->bank_read = realtek_gpio_bank_read;
-+ ctrl->bank_write = realtek_gpio_bank_write;
-+ ctrl->line_imr_pos = realtek_gpio_line_imr_pos;
- } else {
- bgpio_flags = BGPIOF_BIG_ENDIAN_BYTE_ORDER;
-- ctrl->port_offset_u8 = realtek_gpio_port_offset_u8;
-- ctrl->port_offset_u16 = realtek_gpio_port_offset_u16;
-+ ctrl->bank_read = realtek_gpio_bank_read_swapped;
-+ ctrl->bank_write = realtek_gpio_bank_write_swapped;
-+ ctrl->line_imr_pos = realtek_gpio_line_imr_pos_swapped;
- }
-
- err = bgpio_init(&ctrl->gc, dev, 4,
diff --git a/target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch b/target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch
deleted file mode 100644
index 94c4230835..0000000000
--- a/target/linux/realtek/patches-5.10/318-add-rtl83xx-clk-support.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 800d5fb3c6a16661932c932bacd660e38d06b727 Mon Sep 17 00:00:00 2001
-From: Markus Stockhausen <markus.stockhausen@gmx.de>
-Date: Thu, 25 Aug 2022 08:22:36 +0200
-Subject: [PATCH] realtek: add patch to enable new clock driver in kernel
-
-Allow building the clock driver with kernel config options.
-
-Submitted-by: Markus Stockhausen <markus.stockhausen@gmx.de>
----
- drivers/clk/Kconfig | 1 +
- drivers/clk/Makefile | 1 +
- 2 files changed, 2 insertions(+)
-
---- a/drivers/clk/Kconfig
-+++ b/drivers/clk/Kconfig
-@@ -372,6 +372,7 @@ source "drivers/clk/mediatek/Kconfig"
- source "drivers/clk/meson/Kconfig"
- source "drivers/clk/mvebu/Kconfig"
- source "drivers/clk/qcom/Kconfig"
-+source "drivers/clk/realtek/Kconfig"
- source "drivers/clk/renesas/Kconfig"
- source "drivers/clk/rockchip/Kconfig"
- source "drivers/clk/samsung/Kconfig"
---- a/drivers/clk/Makefile
-+++ b/drivers/clk/Makefile
-@@ -100,6 +100,7 @@ obj-$(CONFIG_COMMON_CLK_NXP) += nxp/
- obj-$(CONFIG_MACH_PISTACHIO) += pistachio/
- obj-$(CONFIG_COMMON_CLK_PXA) += pxa/
- obj-$(CONFIG_COMMON_CLK_QCOM) += qcom/
-+obj-$(CONFIG_COMMON_CLK_REALTEK) += realtek/
- obj-y += renesas/
- obj-$(CONFIG_ARCH_ROCKCHIP) += rockchip/
- obj-$(CONFIG_COMMON_CLK_SAMSUNG) += samsung/
diff --git a/target/linux/realtek/patches-5.10/319-irqchip-irq-realtek-rtl-fix-VPE-affinity.patch b/target/linux/realtek/patches-5.10/319-irqchip-irq-realtek-rtl-fix-VPE-affinity.patch
deleted file mode 100644
index bb95e7103a..0000000000
--- a/target/linux/realtek/patches-5.10/319-irqchip-irq-realtek-rtl-fix-VPE-affinity.patch
+++ /dev/null
@@ -1,159 +0,0 @@
-From 2cd00b51470a30198b048a5fca48a04db77e29cc Mon Sep 17 00:00:00 2001
-From: INAGAKI Hiroshi <musashino.open@gmail.com>
-Date: Fri, 21 May 2021 23:16:37 +0900
-Subject: [PATCH] realtek: backport irq-realtek-rtl driver from 5.12 to 5.10
-
-This patch backports "irq-realtek-rtl" driver to Kernel 5.10 from 5.12.
-"MACH_REALTEK_RTL" is used as a platform name in upstream, but "RTL838X"
-is used in OpenWrt, so update the dependency by the additional patch.
-
-Submitted-by: INAGAKI Hiroshi <musashino.open@gmail.com>
----
- drivers/irqchip/irq-realtek-rtl.c | 38 +++++++++++------
- 1 files changed, 58 insertions(+), 20 deletions(-)
-
---- a/drivers/irqchip/irq-realtek-rtl.c
-+++ b/drivers/irqchip/irq-realtek-rtl.c
-@@ -28,6 +28,7 @@ static DEFINE_RAW_SPINLOCK(irq_lock);
-
- #define REG(offset, cpu) (realtek_ictl_base[cpu] + offset)
-
-+static u32 realtek_ictl_unmask[NR_CPUS];
- static void __iomem *realtek_ictl_base[NR_CPUS];
- static cpumask_t realtek_ictl_cpu_configurable;
-
-@@ -41,11 +42,29 @@ struct realtek_ictl_output {
- };
-
- /*
-- * IRR0-IRR3 store 4 bits per interrupt, but Realtek uses inverted numbering,
-- * placing IRQ 31 in the first four bits. A routing value of '0' means the
-- * interrupt is left disconnected. Routing values {1..15} connect to output
-- * lines {0..14}.
-+ * Per CPU we have a set of 5 registers that determine interrupt handling for
-+ * 32 external interrupts. GIMR (enable/disable interrupt) plus IRR0-IRR3 that
-+ * contain "routing" or "priority" values. GIMR uses one bit for each interrupt
-+ * and IRRx store 4 bits per interrupt. Realtek uses inverted numbering,
-+ * placing IRQ 31 in the first four bits. The register combinations give the
-+ * following results for a single interrupt in the wild:
-+ *
-+ * a) GIMR = 0 / IRRx > 0 -> no interrupts
-+ * b) GIMR = 0 / IRRx = 0 -> no interrupts
-+ * c) GIMR = 1 / IRRx > 0 -> interrupts
-+ * d) GIMR = 1 / IRRx = 0 -> rare interrupts in SMP environment
-+ *
-+ * Combination d) seems to trigger interrupts only on a VPE if the other VPE
-+ * has GIMR = 0 and IRRx > 0. E.g. busy without interrupts allowed. To provide
-+ * IRQ balancing features in SMP this driver will handle the registers as
-+ * follows:
-+ *
-+ * 1) set IRRx > 0 for VPE where the interrupt is desired
-+ * 2) set IRRx = 0 for VPE where the interrupt is not desired
-+ * 3) set both GIMR = 0 to mask (disabled) interrupt
-+ * 4) set GIMR = 1 to unmask (enable) interrupt but only for VPE where IRRx > 0
- */
-+
- #define IRR_OFFSET(idx) (4 * (3 - (idx * 4) / 32))
- #define IRR_SHIFT(idx) ((idx * 4) % 32)
-
-@@ -65,19 +84,33 @@ static inline void write_irr(void __iome
- writel(irr, irr0 + offset);
- }
-
-+static inline void enable_gimr(int hwirq, int cpu)
-+{
-+ u32 value;
-+
-+ value = readl(REG(RTL_ICTL_GIMR, cpu));
-+ value |= (BIT(hwirq) & realtek_ictl_unmask[cpu]);
-+ writel(value, REG(RTL_ICTL_GIMR, cpu));
-+}
-+
-+static inline void disable_gimr(int hwirq, int cpu)
-+{
-+ u32 value;
-+
-+ value = readl(REG(RTL_ICTL_GIMR, cpu));
-+ value &= ~BIT(hwirq);
-+ writel(value, REG(RTL_ICTL_GIMR, cpu));
-+}
-+
- static void realtek_ictl_unmask_irq(struct irq_data *i)
- {
- unsigned long flags;
-- u32 value;
- int cpu;
-
- raw_spin_lock_irqsave(&irq_lock, flags);
-
-- for_each_cpu(cpu, &realtek_ictl_cpu_configurable) {
-- value = readl(REG(RTL_ICTL_GIMR, cpu));
-- value |= BIT(i->hwirq);
-- writel(value, REG(RTL_ICTL_GIMR, cpu));
-- }
-+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable)
-+ enable_gimr(i->hwirq, cpu);
-
- raw_spin_unlock_irqrestore(&irq_lock, flags);
- }
-@@ -85,16 +118,12 @@ static void realtek_ictl_unmask_irq(stru
- static void realtek_ictl_mask_irq(struct irq_data *i)
- {
- unsigned long flags;
-- u32 value;
- int cpu;
-
- raw_spin_lock_irqsave(&irq_lock, flags);
-
-- for_each_cpu(cpu, &realtek_ictl_cpu_configurable) {
-- value = readl(REG(RTL_ICTL_GIMR, cpu));
-- value &= ~BIT(i->hwirq);
-- writel(value, REG(RTL_ICTL_GIMR, cpu));
-- }
-+ for_each_cpu(cpu, &realtek_ictl_cpu_configurable)
-+ disable_gimr(i->hwirq, cpu);
-
- raw_spin_unlock_irqrestore(&irq_lock, flags);
- }
-@@ -116,11 +145,17 @@ static int __maybe_unused realtek_ictl_i
- cpumask_and(&cpu_enable, &cpu_configure, dest);
- cpumask_andnot(&cpu_disable, &cpu_configure, dest);
-
-- for_each_cpu(cpu, &cpu_disable)
-+ for_each_cpu(cpu, &cpu_disable) {
- write_irr(REG(RTL_ICTL_IRR0, cpu), i->hwirq, 0);
-+ realtek_ictl_unmask[cpu] &= ~BIT(i->hwirq);
-+ disable_gimr(i->hwirq, cpu);
-+ }
-
-- for_each_cpu(cpu, &cpu_enable)
-+ for_each_cpu(cpu, &cpu_enable) {
- write_irr(REG(RTL_ICTL_IRR0, cpu), i->hwirq, output->output_index + 1);
-+ realtek_ictl_unmask[cpu] |= BIT(i->hwirq);
-+ enable_gimr(i->hwirq, cpu);
-+ }
-
- irq_data_update_effective_affinity(i, &cpu_enable);
-
-@@ -149,6 +184,7 @@ static int intc_map(struct irq_domain *d
-
- output->child_mask |= BIT(hw);
- write_irr(REG(RTL_ICTL_IRR0, 0), hw, output->output_index + 1);
-+ realtek_ictl_unmask[0] |= BIT(hw);
-
- raw_spin_unlock_irqrestore(&irq_lock, flags);
-
-@@ -279,9 +315,11 @@ static int __init realtek_rtl_of_init(st
- cpumask_set_cpu(cpu, &realtek_ictl_cpu_configurable);
-
- /* Disable all cascaded interrupts and clear routing */
-- writel(0, REG(RTL_ICTL_GIMR, cpu));
-- for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++)
-+ for (soc_irq = 0; soc_irq < RTL_ICTL_NUM_INPUTS; soc_irq++) {
- write_irr(REG(RTL_ICTL_IRR0, cpu), soc_irq, 0);
-+ realtek_ictl_unmask[cpu] &= ~BIT(soc_irq);
-+ disable_gimr(soc_irq, cpu);
-+ }
- }
- }
-
diff --git a/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch b/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch
deleted file mode 100644
index f97ea94d9b..0000000000
--- a/target/linux/realtek/patches-5.10/700-net-dsa-add-support-for-rtl838x-switch.patch
+++ /dev/null
@@ -1,40 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: net: dsa: Add support for rtl838x switch
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- drivers/net/dsa/rtl83xx/Kconfig | 2 ++
- drivers/net/dsa/rtl83xx/Makefile | 1 +
- 2 files changed, 3 insertions(+)
-
---- a/drivers/net/dsa/Kconfig
-+++ b/drivers/net/dsa/Kconfig
-@@ -68,6 +68,8 @@ config NET_DSA_QCA8K
- This enables support for the Qualcomm Atheros QCA8K Ethernet
- switch chips.
-
-+source "drivers/net/dsa/rtl83xx/Kconfig"
-+
- config NET_DSA_REALTEK_SMI
- tristate "Realtek SMI Ethernet switch family support"
- depends on NET_DSA
---- a/drivers/net/dsa/Makefile
-+++ b/drivers/net/dsa/Makefile
-@@ -23,3 +23,4 @@ obj-y += mv88e6xxx/
- obj-y += ocelot/
- obj-y += qca/
- obj-y += sja1105/
-+obj-y += rtl83xx/
diff --git a/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch b/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch
deleted file mode 100644
index 27299f17de..0000000000
--- a/target/linux/realtek/patches-5.10/701-net-dsa-add-rtl838x-support-for-tag-trailer.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: net: dsa: Add rtl838x support for tag trailer
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- net/dsa/tag_trailer.c | 16 +++++++++++++-
- 1 file changed, 17 insertions(+), 1 deletion(-)
-
---- a/net/dsa/tag_trailer.c
-+++ b/net/dsa/tag_trailer.c
-@@ -17,7 +17,12 @@ static struct sk_buff *trailer_xmit(stru
-
- trailer = skb_put(skb, 4);
- trailer[0] = 0x80;
-+
-+#ifdef CONFIG_NET_DSA_RTL83XX
-+ trailer[1] = dp->index;
-+#else
- trailer[1] = 1 << dp->index;
-+#endif /* CONFIG_NET_DSA_RTL838X */
- trailer[2] = 0x10;
- trailer[3] = 0x00;
-
-@@ -34,12 +39,23 @@ static struct sk_buff *trailer_rcv(struc
- return NULL;
-
- trailer = skb_tail_pointer(skb) - 4;
-+
-+#ifdef CONFIG_NET_DSA_RTL83XX
-+ if (trailer[0] != 0x80 || (trailer[1] & 0x80) != 0x00 ||
-+ (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00)
-+ return NULL;
-+
-+ if (trailer[1] & 0x40)
-+ skb->offload_fwd_mark = 1;
-+
-+ source_port = trailer[1] & 0x3f;
-+#else
- if (trailer[0] != 0x80 || (trailer[1] & 0xf8) != 0x00 ||
- (trailer[2] & 0xef) != 0x00 || trailer[3] != 0x00)
- return NULL;
-
- source_port = trailer[1] & 7;
--
-+#endif
- skb->dev = dsa_master_find_slave(dev, 0, source_port);
- if (!skb->dev)
- return NULL;
diff --git a/target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch b/target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch
deleted file mode 100644
index 63991d373c..0000000000
--- a/target/linux/realtek/patches-5.10/702-net-dsa-increase-dsa-max-ports-for-rtl838x.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: net: dsa: Increase max ports for rtl838x
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- include/linux/platform_data/dsa.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/include/linux/platform_data/dsa.h
-+++ b/include/linux/platform_data/dsa.h
-@@ -6,7 +6,7 @@ struct device;
- struct net_device;
-
- #define DSA_MAX_SWITCHES 4
--#define DSA_MAX_PORTS 12
-+#define DSA_MAX_PORTS 54
- #define DSA_RTABLE_NONE -1
-
- struct dsa_chip_data {
diff --git a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch b/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch
deleted file mode 100644
index 9f50e8b564..0000000000
--- a/target/linux/realtek/patches-5.10/702-net-ethernet-add-support-for-rtl838x-ethernet.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: net: ethernet: Add support for RTL838x ethernet
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- drivers/net/ethernet/Kconfig | 7 +-
- drivers/net/ethernet/Makefile | 1 +
- 2 files changed, 8 insertions(+)
-
---- a/drivers/net/ethernet/Kconfig
-+++ b/drivers/net/ethernet/Kconfig
-@@ -163,6 +163,13 @@ source "drivers/net/ethernet/rdc/Kconfig
- source "drivers/net/ethernet/realtek/Kconfig"
- source "drivers/net/ethernet/renesas/Kconfig"
- source "drivers/net/ethernet/rocker/Kconfig"
-+
-+config NET_RTL838X
-+ tristate "Realtek rtl838x Ethernet MAC support"
-+ depends on RTL83XX
-+ help
-+ Say Y here if you want to use the Realtek rtl838x Gbps Ethernet MAC.
-+
- source "drivers/net/ethernet/samsung/Kconfig"
- source "drivers/net/ethernet/seeq/Kconfig"
- source "drivers/net/ethernet/sfc/Kconfig"
---- a/drivers/net/ethernet/Makefile
-+++ b/drivers/net/ethernet/Makefile
-@@ -75,6 +75,7 @@ obj-$(CONFIG_NET_VENDOR_REALTEK) += real
- obj-$(CONFIG_NET_VENDOR_RENESAS) += renesas/
- obj-$(CONFIG_NET_VENDOR_RDC) += rdc/
- obj-$(CONFIG_NET_VENDOR_ROCKER) += rocker/
-+obj-$(CONFIG_NET_RTL838X) += rtl838x_eth.o
- obj-$(CONFIG_NET_VENDOR_SAMSUNG) += samsung/
- obj-$(CONFIG_NET_VENDOR_SEEQ) += seeq/
- obj-$(CONFIG_NET_VENDOR_SILAN) += silan/
diff --git a/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch b/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch
deleted file mode 100644
index 8f68dd4e88..0000000000
--- a/target/linux/realtek/patches-5.10/703-include-linux-add-phy-ops-for-rtl838x.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: phy: Add PHY ops for rtl838x EEE
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- include/linux/phy.h | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -885,6 +885,10 @@ struct phy_driver {
- int (*get_sqi)(struct phy_device *dev);
- /** @get_sqi_max: Get the maximum signal quality indication */
- int (*get_sqi_max)(struct phy_device *dev);
-+ int (*get_port)(struct phy_device *dev);
-+ int (*set_port)(struct phy_device *dev, int port);
-+ int (*get_eee)(struct phy_device *dev, struct ethtool_eee *e);
-+ int (*set_eee)(struct phy_device *dev, struct ethtool_eee *e);
- };
- #define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
- struct phy_driver, mdiodrv)
diff --git a/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch b/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch
deleted file mode 100644
index c46be91fe0..0000000000
--- a/target/linux/realtek/patches-5.10/704-drivers-net-phy-eee-support-for-rtl838x.patch
+++ /dev/null
@@ -1,61 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: net: phy: EEE support for rtl838x
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- drivers/net/phy/phylink. | 14 +++++++++++--
- 1 file changed, 12 insertions(+), 2 deletions(-)
-
---- a/drivers/net/phy/phylink.c
-+++ b/drivers/net/phy/phylink.c
-@@ -1449,6 +1449,11 @@ int phylink_ethtool_ksettings_set(struct
- * the presence of a PHY, this should not be changed as that
- * should be determined from the media side advertisement.
- */
-+ if (pl->phydev->drv->get_port && pl->phydev->drv->set_port) {
-+ if(pl->phydev->drv->get_port(pl->phydev) != kset->base.port) {
-+ pl->phydev->drv->set_port(pl->phydev, kset->base.port);
-+ }
-+ }
- return phy_ethtool_ksettings_set(pl->phydev, kset);
- }
-
-@@ -1750,8 +1755,11 @@ int phylink_ethtool_get_eee(struct phyli
-
- ASSERT_RTNL();
-
-- if (pl->phydev)
-+ if (pl->phydev) {
-+ if (pl->phydev->drv->get_eee)
-+ return pl->phydev->drv->get_eee(pl->phydev, eee);
- ret = phy_ethtool_get_eee(pl->phydev, eee);
-+ }
-
- return ret;
- }
-@@ -1768,8 +1776,11 @@ int phylink_ethtool_set_eee(struct phyli
-
- ASSERT_RTNL();
-
-- if (pl->phydev)
-+ if (pl->phydev) {
-+ if (pl->phydev->drv->set_eee)
-+ return pl->phydev->drv->set_eee(pl->phydev, eee);
- ret = phy_ethtool_set_eee(pl->phydev, eee);
-+ }
-
- return ret;
- }
diff --git a/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch b/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch
deleted file mode 100644
index 442bff82fa..0000000000
--- a/target/linux/realtek/patches-5.10/704-include-linux-add-phy-hsgmii-mode.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 9d9bf16aa8d966834ac1280f96c37d22552c33d1 Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Wed, 8 Sep 2021 16:13:18 +0200
-Subject: phy: Add PHY hsgmii mode
-
-This adds RTL93xx-specific MAC configuration routines that allow also configuration
-of 10GBit links for phylink. There is support for the Realtek-specific HISGMI
-protocol.
-
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- include/linux/phy.h | 3 +++
- 1 file changed, 3 insertions(+)
-
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -134,6 +134,7 @@ typedef enum {
- PHY_INTERFACE_MODE_XGMII,
- PHY_INTERFACE_MODE_XLGMII,
- PHY_INTERFACE_MODE_MOCA,
-+ PHY_INTERFACE_MODE_HSGMII,
- PHY_INTERFACE_MODE_QSGMII,
- PHY_INTERFACE_MODE_TRGMII,
- PHY_INTERFACE_MODE_100BASEX,
-@@ -201,6 +202,8 @@ static inline const char *phy_modes(phy_
- return "xlgmii";
- case PHY_INTERFACE_MODE_MOCA:
- return "moca";
-+ case PHY_INTERFACE_MODE_HSGMII:
-+ return "hsgmii";
- case PHY_INTERFACE_MODE_QSGMII:
- return "qsgmii";
- case PHY_INTERFACE_MODE_TRGMII:
diff --git a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch b/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch
deleted file mode 100644
index 47041262fc..0000000000
--- a/target/linux/realtek/patches-5.10/705-add-rtl-phy.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 89f71ebb355c624320c2b0ace8ae9488ff53cbeb Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <mail@birger-koblitz.de>
-Date: Tue, 5 Jan 2021 20:40:52 +0100
-Subject: PHY: Add realtek PHY
-
-This fixes the build problems for the REALTEK target by adding a proper
-configuration option for the phy module.
-
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
----
- drivers/net/phy/Kconfig | 6 ++++++
- drivers/net/phy/Makefile | 1 +
- 2 files changed, 7 insertions(+)
-
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -330,6 +330,12 @@ config REALTEK_PHY
- help
- Supports the Realtek 821x PHY.
-
-+config REALTEK_SOC_PHY
-+ tristate "Realtek SoC PHYs"
-+ depends on RTL83XX
-+ help
-+ Supports the PHYs found in combination with Realtek Switch SoCs
-+
- config RENESAS_PHY
- tristate "Renesas PHYs"
- help
---- a/drivers/net/phy/Makefile
-+++ b/drivers/net/phy/Makefile
-@@ -89,6 +89,7 @@ obj-$(CONFIG_NATIONAL_PHY) += national.o
- obj-$(CONFIG_NXP_TJA11XX_PHY) += nxp-tja11xx.o
- obj-$(CONFIG_QSEMI_PHY) += qsemi.o
- obj-$(CONFIG_REALTEK_PHY) += realtek.o
-+obj-$(CONFIG_REALTEK_SOC_PHY) += rtl83xx-phy.o
- obj-$(CONFIG_RENESAS_PHY) += uPD60620.o
- obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o
- obj-$(CONFIG_SMSC_PHY) += smsc.o
diff --git a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch b/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch
deleted file mode 100644
index bba6fd7182..0000000000
--- a/target/linux/realtek/patches-5.10/705-include-linux-phy-increase-phy-address-number-for-rtl839x.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-From 2b88563ee5aafd9571d965b7f2093a0f58d98a31 Mon Sep 17 00:00:00 2001
-From: John Crispin <john@phrozen.org>
-Date: Thu, 26 Nov 2020 12:02:21 +0100
-Subject: PHY: Increase max PHY adddress number
-
-* 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 <bert@biot.com>
-Submitted-by: Birger Koblitz <mail@birger-koblitz.de>
-Submitted-by: Sander Vanheule <sander@svanheule.net>
-Submitted-by: Bjørn Mork <bjorn@mork.no>
-Submitted-by: John Crispin <john@phrozen.org>
----
- include/linux/phy.h | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -233,7 +233,7 @@ static inline const char *phy_modes(phy_
- #define PHY_INIT_TIMEOUT 100000
- #define PHY_FORCE_TIMEOUT 10
-
--#define PHY_MAX_ADDR 32
-+#define PHY_MAX_ADDR 64
-
- /* Used when trying to connect to a specific phy (mii bus id:phy device id) */
- #define PHY_ID_FMT "%s:%02x"
diff --git a/target/linux/realtek/patches-5.10/708-brflood-api.patch b/target/linux/realtek/patches-5.10/708-brflood-api.patch
deleted file mode 100644
index 2716933ae7..0000000000
--- a/target/linux/realtek/patches-5.10/708-brflood-api.patch
+++ /dev/null
@@ -1,162 +0,0 @@
-From afa3ab54c03d5126b14651f367b38165fab5b3cc Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Tue, 18 Jan 2022 17:18:43 +0100
-Subject: net: brflood API
-
-Adds the DSA API for bridge configuration (flooding, L2 learning,
-and aging) offload as found in Linux 5.12 so that we can implement
-it in our drivver.
-
-Submitted-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- include/net/dsa.h | 6 +++++++--
- net/dsa/dsa_priv.h | 6 +++---
- net/dsa/port.c | 28 ++++++++----
- net/dsa/slave.c | 6 +++---
- 4 file changed, 29 insertions(+), 13 deletions(-)
-
---- a/include/net/dsa.h
-+++ b/include/net/dsa.h
-@@ -552,8 +552,14 @@ struct dsa_switch_ops {
- void (*port_stp_state_set)(struct dsa_switch *ds, int port,
- u8 state);
- void (*port_fast_age)(struct dsa_switch *ds, int port);
-- int (*port_egress_floods)(struct dsa_switch *ds, int port,
-- bool unicast, bool multicast);
-+ int (*port_pre_bridge_flags)(struct dsa_switch *ds, int port,
-+ unsigned long flags,
-+ struct netlink_ext_ack *extack);
-+ int (*port_bridge_flags)(struct dsa_switch *ds, int port,
-+ unsigned long flags,
-+ struct netlink_ext_ack *extack);
-+ int (*port_set_mrouter)(struct dsa_switch *ds, int port, bool mrouter,
-+ struct netlink_ext_ack *extack);
-
- /*
- * VLAN support
---- a/net/dsa/dsa_priv.h
-+++ b/net/dsa/dsa_priv.h
-@@ -167,11 +167,11 @@ int dsa_port_mdb_add(const struct dsa_po
- int dsa_port_mdb_del(const struct dsa_port *dp,
- const struct switchdev_obj_port_mdb *mdb);
- int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
-- struct switchdev_trans *trans);
-+ struct switchdev_trans *trans, struct netlink_ext_ack *extack);
- int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
-- struct switchdev_trans *trans);
-+ struct switchdev_trans *trans, struct netlink_ext_ack *extack);
- int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
-- struct switchdev_trans *trans);
-+ struct switchdev_trans *trans, struct netlink_ext_ack *extack);
- int dsa_port_vlan_add(struct dsa_port *dp,
- const struct switchdev_obj_port_vlan *vlan,
- struct switchdev_trans *trans);
---- a/net/dsa/port.c
-+++ b/net/dsa/port.c
-@@ -145,7 +145,7 @@ int dsa_port_bridge_join(struct dsa_port
- int err;
-
- /* Set the flooding mode before joining the port in the switch */
-- err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL);
-+ err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL, NULL);
- if (err)
- return err;
-
-@@ -158,7 +158,7 @@ int dsa_port_bridge_join(struct dsa_port
-
- /* The bridging is rolled back on error */
- if (err) {
-- dsa_port_bridge_flags(dp, 0, NULL);
-+ dsa_port_bridge_flags(dp, 0, NULL, NULL);
- dp->bridge_dev = NULL;
- }
-
-@@ -185,7 +185,7 @@ void dsa_port_bridge_leave(struct dsa_po
- pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
-
- /* Port is leaving the bridge, disable flooding */
-- dsa_port_bridge_flags(dp, 0, NULL);
-+ dsa_port_bridge_flags(dp, 0, NULL, NULL);
-
- /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
- * so allow it to be in BR_STATE_FORWARDING to be kept functional
-@@ -333,44 +333,44 @@ int dsa_port_ageing_time(struct dsa_port
- }
-
- int dsa_port_pre_bridge_flags(const struct dsa_port *dp, unsigned long flags,
-- struct switchdev_trans *trans)
-+ struct switchdev_trans *trans, struct netlink_ext_ack *extack)
- {
- struct dsa_switch *ds = dp->ds;
-
-- if (!ds->ops->port_egress_floods ||
-- (flags & ~(BR_FLOOD | BR_MCAST_FLOOD)))
-+ if (!ds->ops->port_pre_bridge_flags)
- return -EINVAL;
-
-- return 0;
-+ return ds->ops->port_pre_bridge_flags(ds, dp->index, flags, extack);
- }
-
- int dsa_port_bridge_flags(const struct dsa_port *dp, unsigned long flags,
-- struct switchdev_trans *trans)
-+ struct switchdev_trans *trans, struct netlink_ext_ack *extack)
- {
- struct dsa_switch *ds = dp->ds;
-- int port = dp->index;
-- int err = 0;
-
- if (switchdev_trans_ph_prepare(trans))
- return 0;
-
-- if (ds->ops->port_egress_floods)
-- err = ds->ops->port_egress_floods(ds, port, flags & BR_FLOOD,
-- flags & BR_MCAST_FLOOD);
-+ if (!ds->ops->port_bridge_flags)
-+ return -EINVAL;
-+
-+ return ds->ops->port_bridge_flags(ds, dp->index, flags, extack);
-
-- return err;
- }
-
- int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
-- struct switchdev_trans *trans)
-+ struct switchdev_trans *trans,
-+ struct netlink_ext_ack *extack)
- {
- struct dsa_switch *ds = dp->ds;
-- int port = dp->index;
-
- if (switchdev_trans_ph_prepare(trans))
-- return ds->ops->port_egress_floods ? 0 : -EOPNOTSUPP;
-+ return ds->ops->port_set_mrouter ? 0 : -EOPNOTSUPP;
-+
-+ if (!ds->ops->port_set_mrouter)
-+ return -EOPNOTSUPP;
-
-- return ds->ops->port_egress_floods(ds, port, true, mrouter);
-+ return ds->ops->port_set_mrouter(ds, dp->index, mrouter, extack);
- }
-
- int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
---- a/net/dsa/slave.c
-+++ b/net/dsa/slave.c
-@@ -290,13 +290,13 @@ static int dsa_slave_port_attr_set(struc
- break;
- case SWITCHDEV_ATTR_ID_PORT_PRE_BRIDGE_FLAGS:
- ret = dsa_port_pre_bridge_flags(dp, attr->u.brport_flags,
-- trans);
-+ trans, NULL);
- break;
- case SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS:
-- ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans);
-+ ret = dsa_port_bridge_flags(dp, attr->u.brport_flags, trans, NULL);
- break;
- case SWITCHDEV_ATTR_ID_BRIDGE_MROUTER:
-- ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, trans);
-+ ret = dsa_port_mrouter(dp->cpu_dp, attr->u.mrouter, trans, NULL);
- break;
- default:
- ret = -EOPNOTSUPP;
diff --git a/target/linux/realtek/patches-5.10/709-lag-offloading.patch b/target/linux/realtek/patches-5.10/709-lag-offloading.patch
deleted file mode 100644
index f84687ff4a..0000000000
--- a/target/linux/realtek/patches-5.10/709-lag-offloading.patch
+++ /dev/null
@@ -1,781 +0,0 @@
-From afa3ab54c03d5126b14651f367b38165fab5b3cc Mon Sep 17 00:00:00 2001
-From: Birger Koblitz <git@birger-koblitz.de>
-Date: Tue, 18 Jan 2022 17:18:43 +0100
-Subject: [PATCH] realtek: Backport bridge configuration for DSA
-
-Adds the DSA API for bridge configuration (flooding, L2 learning,
-and aging) offload as found in Linux 5.12 so that we can implement
-it in our drivver.
-
-Submitted-by: Sebastian Gottschall <s.gottschall@dd-wrt.com>
-Submitted-by: Birger Koblitz <git@birger-koblitz.de>
----
- drivers/net/bonding/bond_main.c | 2 ++
- include/net/dsa.h | 79 ++++++++++++++++-
- net/dsa/dsa2.c | 88 +++++++++++++++++++
- net/dsa/dsa_priv.h | 74 ++++++++++++++
- net/dsa/port.c | 92 ++++++++++++++++++++
- net/dsa/slave.c | 88 ++++++++++++++++---
- net/dsa/switch.c | 49 ++++++++++
- net/sda/tag_dsa.c | 13 +++++-
- 8 file changed, 460 insertions(+), 25 deletions(-)
-
---- a/drivers/net/bonding/bond_main.c
-+++ b/drivers/net/bonding/bond_main.c
-@@ -2045,6 +2045,8 @@ int bond_enslave(struct net_device *bond
- goto err_unregister;
- }
-
-+ bond_lower_state_changed(new_slave);
-+
- res = bond_sysfs_slave_add(new_slave);
- if (res) {
- slave_dbg(bond_dev, slave_dev, "Error %d calling bond_sysfs_slave_add\n", res);
---- a/include/net/dsa.h
-+++ b/include/net/dsa.h
-@@ -149,8 +149,41 @@ struct dsa_switch_tree {
-
- /* List of DSA links composing the routing table */
- struct list_head rtable;
-+
-+ /* Maps offloaded LAG netdevs to a zero-based linear ID for
-+ * drivers that need it.
-+ */
-+ struct net_device **lags;
-+ unsigned int lags_len;
- };
-
-+#define dsa_lags_foreach_id(_id, _dst) \
-+ for ((_id) = 0; (_id) < (_dst)->lags_len; (_id)++) \
-+ if ((_dst)->lags[(_id)])
-+
-+#define dsa_lag_foreach_port(_dp, _dst, _lag) \
-+ list_for_each_entry((_dp), &(_dst)->ports, list) \
-+ if ((_dp)->lag_dev == (_lag))
-+
-+static inline struct net_device *dsa_lag_dev(struct dsa_switch_tree *dst,
-+ unsigned int id)
-+{
-+ return dst->lags[id];
-+}
-+
-+static inline int dsa_lag_id(struct dsa_switch_tree *dst,
-+ struct net_device *lag)
-+{
-+ unsigned int id;
-+
-+ dsa_lags_foreach_id(id, dst) {
-+ if (dsa_lag_dev(dst, id) == lag)
-+ return id;
-+ }
-+
-+ return -ENODEV;
-+}
-+
- /* TC matchall action types */
- enum dsa_port_mall_action_type {
- DSA_PORT_MALL_MIRROR,
-@@ -220,6 +253,8 @@ struct dsa_port {
- bool devlink_port_setup;
- struct phylink *pl;
- struct phylink_config pl_config;
-+ struct net_device *lag_dev;
-+ bool lag_tx_enabled;
-
- struct list_head list;
-
-@@ -340,6 +375,14 @@ struct dsa_switch {
- */
- bool mtu_enforcement_ingress;
-
-+ /* Drivers that benefit from having an ID associated with each
-+ * offloaded LAG should set this to the maximum number of
-+ * supported IDs. DSA will then maintain a mapping of _at
-+ * least_ these many IDs, accessible to drivers via
-+ * dsa_lag_id().
-+ */
-+ unsigned int num_lag_ids;
-+
- size_t num_ports;
- };
-
-@@ -432,6 +475,18 @@ static inline bool dsa_port_is_vlan_filt
- return dp->vlan_filtering;
- }
-
-+static inline
-+struct net_device *dsa_port_to_bridge_port(const struct dsa_port *dp)
-+{
-+ if (!dp->bridge_dev)
-+ return NULL;
-+
-+ if (dp->lag_dev)
-+ return dp->lag_dev;
-+
-+ return dp->slave;
-+}
-+
- typedef int dsa_fdb_dump_cb_t(const unsigned char *addr, u16 vid,
- bool is_static, void *data);
- struct dsa_switch_ops {
-@@ -629,6 +684,13 @@ struct dsa_switch_ops {
- void (*crosschip_bridge_leave)(struct dsa_switch *ds, int tree_index,
- int sw_index, int port,
- struct net_device *br);
-+ int (*crosschip_lag_change)(struct dsa_switch *ds, int sw_index,
-+ int port);
-+ int (*crosschip_lag_join)(struct dsa_switch *ds, int sw_index,
-+ int port, struct net_device *lag,
-+ struct netdev_lag_upper_info *info);
-+ int (*crosschip_lag_leave)(struct dsa_switch *ds, int sw_index,
-+ int port, struct net_device *lag);
-
- /*
- * PTP functionality
-@@ -660,6 +722,16 @@ struct dsa_switch_ops {
- int (*port_change_mtu)(struct dsa_switch *ds, int port,
- int new_mtu);
- int (*port_max_mtu)(struct dsa_switch *ds, int port);
-+
-+ /*
-+ * LAG integration
-+ */
-+ int (*port_lag_change)(struct dsa_switch *ds, int port);
-+ int (*port_lag_join)(struct dsa_switch *ds, int port,
-+ struct net_device *lag,
-+ struct netdev_lag_upper_info *info);
-+ int (*port_lag_leave)(struct dsa_switch *ds, int port,
-+ struct net_device *lag);
- };
-
- #define DSA_DEVLINK_PARAM_DRIVER(_id, _name, _type, _cmodes) \
---- a/net/dsa/dsa.c
-+++ b/net/dsa/dsa.c
-@@ -220,11 +220,21 @@ static int dsa_switch_rcv(struct sk_buff
- }
-
- skb = nskb;
-- p = netdev_priv(skb->dev);
- skb_push(skb, ETH_HLEN);
- skb->pkt_type = PACKET_HOST;
- skb->protocol = eth_type_trans(skb, skb->dev);
-
-+ if (unlikely(!dsa_slave_dev_check(skb->dev))) {
-+ /* Packet is to be injected directly on an upper
-+ * device, e.g. a team/bond, so skip all DSA-port
-+ * specific actions.
-+ */
-+ netif_rx(skb);
-+ return 0;
-+ }
-+
-+ p = netdev_priv(skb->dev);
-+
- if (unlikely(cpu_dp->ds->untag_bridge_pvid)) {
- nskb = dsa_untag_bridge_pvid(skb);
- if (!nskb) {
---- a/net/dsa/dsa2.c
-+++ b/net/dsa/dsa2.c
-@@ -21,6 +21,65 @@
- static DEFINE_MUTEX(dsa2_mutex);
- LIST_HEAD(dsa_tree_list);
-
-+/**
-+ * dsa_lag_map() - Map LAG netdev to a linear LAG ID
-+ * @dst: Tree in which to record the mapping.
-+ * @lag: Netdev that is to be mapped to an ID.
-+ *
-+ * dsa_lag_id/dsa_lag_dev can then be used to translate between the
-+ * two spaces. The size of the mapping space is determined by the
-+ * driver by setting ds->num_lag_ids. It is perfectly legal to leave
-+ * it unset if it is not needed, in which case these functions become
-+ * no-ops.
-+ */
-+void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag)
-+{
-+ unsigned int id;
-+
-+ if (dsa_lag_id(dst, lag) >= 0)
-+ /* Already mapped */
-+ return;
-+
-+ for (id = 0; id < dst->lags_len; id++) {
-+ if (!dsa_lag_dev(dst, id)) {
-+ dst->lags[id] = lag;
-+ return;
-+ }
-+ }
-+
-+ /* No IDs left, which is OK. Some drivers do not need it. The
-+ * ones that do, e.g. mv88e6xxx, will discover that dsa_lag_id
-+ * returns an error for this device when joining the LAG. The
-+ * driver can then return -EOPNOTSUPP back to DSA, which will
-+ * fall back to a software LAG.
-+ */
-+}
-+
-+/**
-+ * dsa_lag_unmap() - Remove a LAG ID mapping
-+ * @dst: Tree in which the mapping is recorded.
-+ * @lag: Netdev that was mapped.
-+ *
-+ * As there may be multiple users of the mapping, it is only removed
-+ * if there are no other references to it.
-+ */
-+void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag)
-+{
-+ struct dsa_port *dp;
-+ unsigned int id;
-+
-+ dsa_lag_foreach_port(dp, dst, lag)
-+ /* There are remaining users of this mapping */
-+ return;
-+
-+ dsa_lags_foreach_id(id, dst) {
-+ if (dsa_lag_dev(dst, id) == lag) {
-+ dst->lags[id] = NULL;
-+ break;
-+ }
-+ }
-+}
-+
- struct dsa_switch *dsa_switch_find(int tree_index, int sw_index)
- {
- struct dsa_switch_tree *dst;
-@@ -597,6 +656,32 @@ static void dsa_tree_teardown_master(str
- dsa_master_teardown(dp->master);
- }
-
-+static int dsa_tree_setup_lags(struct dsa_switch_tree *dst)
-+{
-+ unsigned int len = 0;
-+ struct dsa_port *dp;
-+
-+ list_for_each_entry(dp, &dst->ports, list) {
-+ if (dp->ds->num_lag_ids > len)
-+ len = dp->ds->num_lag_ids;
-+ }
-+
-+ if (!len)
-+ return 0;
-+
-+ dst->lags = kcalloc(len, sizeof(*dst->lags), GFP_KERNEL);
-+ if (!dst->lags)
-+ return -ENOMEM;
-+
-+ dst->lags_len = len;
-+ return 0;
-+}
-+
-+static void dsa_tree_teardown_lags(struct dsa_switch_tree *dst)
-+{
-+ kfree(dst->lags);
-+}
-+
- static int dsa_tree_setup(struct dsa_switch_tree *dst)
- {
- bool complete;
-@@ -624,12 +709,18 @@ static int dsa_tree_setup(struct dsa_swi
- if (err)
- goto teardown_switches;
-
-+ err = dsa_tree_setup_lags(dst);
-+ if (err)
-+ goto teardown_master;
-+
- dst->setup = true;
-
- pr_info("DSA: tree %d setup\n", dst->index);
-
- return 0;
-
-+teardown_master:
-+ dsa_tree_teardown_master(dst);
- teardown_switches:
- dsa_tree_teardown_switches(dst);
- teardown_default_cpu:
-@@ -645,6 +736,8 @@ static void dsa_tree_teardown(struct dsa
- if (!dst->setup)
- return;
-
-+ dsa_tree_teardown_lags(dst);
-+
- dsa_tree_teardown_master(dst);
-
- dsa_tree_teardown_switches(dst);
---- a/net/dsa/dsa_priv.h
-+++ b/net/dsa/dsa_priv.h
-@@ -20,6 +20,9 @@ enum {
- DSA_NOTIFIER_BRIDGE_LEAVE,
- DSA_NOTIFIER_FDB_ADD,
- DSA_NOTIFIER_FDB_DEL,
-+ DSA_NOTIFIER_LAG_CHANGE,
-+ DSA_NOTIFIER_LAG_JOIN,
-+ DSA_NOTIFIER_LAG_LEAVE,
- DSA_NOTIFIER_MDB_ADD,
- DSA_NOTIFIER_MDB_DEL,
- DSA_NOTIFIER_VLAN_ADD,
-@@ -57,6 +60,15 @@ struct dsa_notifier_mdb_info {
- int port;
- };
-
-+/* DSA_NOTIFIER_LAG_* */
-+struct dsa_notifier_lag_info {
-+ struct net_device *lag;
-+ int sw_index;
-+ int port;
-+
-+ struct netdev_lag_upper_info *info;
-+};
-+
- /* DSA_NOTIFIER_VLAN_* */
- struct dsa_notifier_vlan_info {
- const struct switchdev_obj_port_vlan *vlan;
-@@ -149,6 +161,11 @@ void dsa_port_disable_rt(struct dsa_port
- void dsa_port_disable(struct dsa_port *dp);
- int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br);
- void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br);
-+int dsa_port_lag_change(struct dsa_port *dp,
-+ struct netdev_lag_lower_state_info *linfo);
-+int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag_dev,
-+ struct netdev_lag_upper_info *uinfo);
-+void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag_dev);
- int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
- struct switchdev_trans *trans);
- bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
-@@ -181,6 +198,71 @@ int dsa_port_link_register_of(struct dsa
- void dsa_port_link_unregister_of(struct dsa_port *dp);
- extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
-
-+static inline bool dsa_port_offloads_netdev(struct dsa_port *dp,
-+ struct net_device *dev)
-+{
-+ /* Switchdev offloading can be configured on: */
-+
-+ if (dev == dp->slave)
-+ /* DSA ports directly connected to a bridge, and event
-+ * was emitted for the ports themselves.
-+ */
-+ return true;
-+
-+ if (dp->bridge_dev == dev)
-+ /* DSA ports connected to a bridge, and event was emitted
-+ * for the bridge.
-+ */
-+ return true;
-+
-+ if (dp->lag_dev == dev)
-+ /* DSA ports connected to a bridge via a LAG */
-+ return true;
-+
-+ return false;
-+}
-+
-+static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
-+ struct net_device *dev)
-+{
-+ return dsa_port_to_bridge_port(dp) == dev;
-+}
-+
-+static inline bool dsa_port_offloads_bridge(struct dsa_port *dp,
-+ struct net_device *bridge_dev)
-+{
-+ /* DSA ports connected to a bridge, and event was emitted
-+ * for the bridge.
-+ */
-+ return dp->bridge_dev == bridge_dev;
-+}
-+
-+/* Returns true if any port of this tree offloads the given net_device */
-+static inline bool dsa_tree_offloads_bridge_port(struct dsa_switch_tree *dst,
-+ struct net_device *dev)
-+{
-+ struct dsa_port *dp;
-+
-+ list_for_each_entry(dp, &dst->ports, list)
-+ if (dsa_port_offloads_bridge_port(dp, dev))
-+ return true;
-+
-+ return false;
-+}
-+
-+/* Returns true if any port of this tree offloads the given net_device */
-+static inline bool dsa_tree_offloads_netdev(struct dsa_switch_tree *dst,
-+ struct net_device *dev)
-+{
-+ struct dsa_port *dp;
-+
-+ list_for_each_entry(dp, &dst->ports, list)
-+ if (dsa_port_offloads_netdev(dp, dev))
-+ return true;
-+
-+ return false;
-+}
-+
- /* slave.c */
- extern const struct dsa_device_ops notag_netdev_ops;
- void dsa_slave_mii_bus_init(struct dsa_switch *ds);
-@@ -285,6 +367,9 @@ int dsa_switch_register_notifier(struct
- void dsa_switch_unregister_notifier(struct dsa_switch *ds);
-
- /* dsa2.c */
-+void dsa_lag_map(struct dsa_switch_tree *dst, struct net_device *lag);
-+void dsa_lag_unmap(struct dsa_switch_tree *dst, struct net_device *lag);
-+
- extern struct list_head dsa_tree_list;
-
- #endif
---- a/net/dsa/port.c
-+++ b/net/dsa/port.c
-@@ -193,6 +193,99 @@ void dsa_port_bridge_leave(struct dsa_po
- dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
- }
-
-+int dsa_port_lag_change(struct dsa_port *dp,
-+ struct netdev_lag_lower_state_info *linfo)
-+{
-+ struct dsa_notifier_lag_info info = {
-+ .sw_index = dp->ds->index,
-+ .port = dp->index,
-+ };
-+ bool tx_enabled;
-+
-+ if (!dp->lag_dev)
-+ return 0;
-+
-+ /* On statically configured aggregates (e.g. loadbalance
-+ * without LACP) ports will always be tx_enabled, even if the
-+ * link is down. Thus we require both link_up and tx_enabled
-+ * in order to include it in the tx set.
-+ */
-+ tx_enabled = linfo->link_up && linfo->tx_enabled;
-+
-+ if (tx_enabled == dp->lag_tx_enabled)
-+ return 0;
-+
-+ dp->lag_tx_enabled = tx_enabled;
-+
-+ return dsa_port_notify(dp, DSA_NOTIFIER_LAG_CHANGE, &info);
-+}
-+
-+int dsa_port_lag_join(struct dsa_port *dp, struct net_device *lag,
-+ struct netdev_lag_upper_info *uinfo)
-+{
-+ struct dsa_notifier_lag_info info = {
-+ .sw_index = dp->ds->index,
-+ .port = dp->index,
-+ .lag = lag,
-+ .info = uinfo,
-+ };
-+ struct net_device *bridge_dev;
-+ int err;
-+
-+ dsa_lag_map(dp->ds->dst, lag);
-+ dp->lag_dev = lag;
-+
-+ err = dsa_port_notify(dp, DSA_NOTIFIER_LAG_JOIN, &info);
-+ if (err)
-+ goto err_lag_join;
-+
-+ bridge_dev = netdev_master_upper_dev_get(lag);
-+ if (!bridge_dev || !netif_is_bridge_master(bridge_dev))
-+ return 0;
-+
-+ err = dsa_port_bridge_join(dp, bridge_dev);
-+ if (err)
-+ goto err_bridge_join;
-+
-+ return 0;
-+
-+err_bridge_join:
-+ dsa_port_notify(dp, DSA_NOTIFIER_LAG_LEAVE, &info);
-+err_lag_join:
-+ dp->lag_dev = NULL;
-+ dsa_lag_unmap(dp->ds->dst, lag);
-+ return err;
-+}
-+
-+void dsa_port_lag_leave(struct dsa_port *dp, struct net_device *lag)
-+{
-+ struct dsa_notifier_lag_info info = {
-+ .sw_index = dp->ds->index,
-+ .port = dp->index,
-+ .lag = lag,
-+ };
-+ int err;
-+
-+ if (!dp->lag_dev)
-+ return;
-+
-+ /* Port might have been part of a LAG that in turn was
-+ * attached to a bridge.
-+ */
-+ if (dp->bridge_dev)
-+ dsa_port_bridge_leave(dp, dp->bridge_dev);
-+
-+ dp->lag_tx_enabled = false;
-+ dp->lag_dev = NULL;
-+
-+ err = dsa_port_notify(dp, DSA_NOTIFIER_LAG_LEAVE, &info);
-+ if (err)
-+ pr_err("DSA: failed to notify DSA_NOTIFIER_LAG_LEAVE: %d\n",
-+ err);
-+
-+ dsa_lag_unmap(dp->ds->dst, lag);
-+}
-+
- /* Must be called under rcu_read_lock() */
- static bool dsa_port_can_apply_vlan_filtering(struct dsa_port *dp,
- bool vlan_filtering)
---- a/net/dsa/slave.c
-+++ b/net/dsa/slave.c
-@@ -337,9 +337,6 @@ static int dsa_slave_vlan_add(struct net
- struct switchdev_obj_port_vlan vlan;
- int vid, err;
-
-- if (obj->orig_dev != dev)
-- return -EOPNOTSUPP;
--
- if (dsa_port_skip_vlan_configuration(dp))
- return 0;
-
-@@ -394,11 +391,13 @@ static int dsa_slave_port_obj_add(struct
-
- switch (obj->id) {
- case SWITCHDEV_OBJ_ID_PORT_MDB:
-- if (obj->orig_dev != dev)
-+ if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
- return -EOPNOTSUPP;
- err = dsa_port_mdb_add(dp, SWITCHDEV_OBJ_PORT_MDB(obj), trans);
- break;
- case SWITCHDEV_OBJ_ID_HOST_MDB:
-+ if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
-+ return -EOPNOTSUPP;
- /* DSA can directly translate this to a normal MDB add,
- * but on the CPU port.
- */
-@@ -406,6 +405,9 @@ static int dsa_slave_port_obj_add(struct
- trans);
- break;
- case SWITCHDEV_OBJ_ID_PORT_VLAN:
-+ if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
-+ return -EOPNOTSUPP;
-+
- err = dsa_slave_vlan_add(dev, obj, trans);
- break;
- default:
-@@ -424,9 +426,6 @@ static int dsa_slave_vlan_del(struct net
- struct switchdev_obj_port_vlan *vlan;
- int vid, err;
-
-- if (obj->orig_dev != dev)
-- return -EOPNOTSUPP;
--
- if (dsa_port_skip_vlan_configuration(dp))
- return 0;
-
-@@ -453,17 +452,22 @@ static int dsa_slave_port_obj_del(struct
-
- switch (obj->id) {
- case SWITCHDEV_OBJ_ID_PORT_MDB:
-- if (obj->orig_dev != dev)
-+ if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
- return -EOPNOTSUPP;
- err = dsa_port_mdb_del(dp, SWITCHDEV_OBJ_PORT_MDB(obj));
- break;
- case SWITCHDEV_OBJ_ID_HOST_MDB:
-+ if (!dsa_port_offloads_bridge(dp, obj->orig_dev))
-+ return -EOPNOTSUPP;
- /* DSA can directly translate this to a normal MDB add,
- * but on the CPU port.
- */
- err = dsa_port_mdb_del(dp->cpu_dp, SWITCHDEV_OBJ_PORT_MDB(obj));
- break;
- case SWITCHDEV_OBJ_ID_PORT_VLAN:
-+ if (!dsa_port_offloads_bridge_port(dp, obj->orig_dev))
-+ return -EOPNOTSUPP;
-+
- err = dsa_slave_vlan_del(dev, obj);
- break;
- default:
-@@ -1993,6 +1997,46 @@ static int dsa_slave_changeupper(struct
- dsa_port_bridge_leave(dp, info->upper_dev);
- err = NOTIFY_OK;
- }
-+ } else if (netif_is_lag_master(info->upper_dev)) {
-+ if (info->linking) {
-+ err = dsa_port_lag_join(dp, info->upper_dev,
-+ info->upper_info);
-+ if (err == -EOPNOTSUPP) {
-+ NL_SET_ERR_MSG_MOD(info->info.extack,
-+ "Offloading not supported");
-+ err = 0;
-+ }
-+ err = notifier_from_errno(err);
-+ } else {
-+ dsa_port_lag_leave(dp, info->upper_dev);
-+ err = NOTIFY_OK;
-+ }
-+ }
-+
-+ return err;
-+}
-+
-+static int
-+dsa_slave_lag_changeupper(struct net_device *dev,
-+ struct netdev_notifier_changeupper_info *info)
-+{
-+ struct net_device *lower;
-+ struct list_head *iter;
-+ int err = NOTIFY_DONE;
-+ struct dsa_port *dp;
-+
-+ netdev_for_each_lower_dev(dev, lower, iter) {
-+ if (!dsa_slave_dev_check(lower))
-+ continue;
-+
-+ dp = dsa_slave_to_port(lower);
-+ if (!dp->lag_dev)
-+ /* Software LAG */
-+ continue;
-+
-+ err = dsa_slave_changeupper(lower, info);
-+ if (notifier_to_errno(err))
-+ break;
- }
-
- return err;
-@@ -2078,10 +2122,26 @@ static int dsa_slave_netdevice_event(str
- break;
- }
- case NETDEV_CHANGEUPPER:
-+ if (dsa_slave_dev_check(dev))
-+ return dsa_slave_changeupper(dev, ptr);
-+
-+ if (netif_is_lag_master(dev))
-+ return dsa_slave_lag_changeupper(dev, ptr);
-+
-+ break;
-+ case NETDEV_CHANGELOWERSTATE: {
-+ struct netdev_notifier_changelowerstate_info *info = ptr;
-+ struct dsa_port *dp;
-+ int err;
-+
- if (!dsa_slave_dev_check(dev))
-- return NOTIFY_DONE;
-+ break;
-
-- return dsa_slave_changeupper(dev, ptr);
-+ dp = dsa_slave_to_port(dev);
-+
-+ err = dsa_port_lag_change(dp, info->lower_state_info);
-+ return notifier_from_errno(err);
-+ }
- }
-
- return NOTIFY_DONE;
-@@ -2229,6 +2289,15 @@ static int dsa_slave_switchdev_event(str
- if (!fdb_info->added_by_user &&
- !dp->ds->assisted_learning_on_cpu_port)
- return NOTIFY_DONE;
-+
-+ /* When the bridge learns an address on an offloaded
-+ * LAG we don't want to send traffic to the CPU, the
-+ * other ports bridged with the LAG should be able to
-+ * autonomously forward towards it.
-+ */
-+ if (dsa_tree_offloads_netdev(dp->ds->dst, dev))
-+ return NOTIFY_DONE;
-+
- }
-
- if (!dp->ds->ops->port_fdb_add || !dp->ds->ops->port_fdb_del)
---- a/net/dsa/switch.c
-+++ b/net/dsa/switch.c
-@@ -193,6 +193,47 @@ static int dsa_switch_fdb_del(struct dsa
- return ds->ops->port_fdb_del(ds, port, info->addr, info->vid);
- }
-
-+static int dsa_switch_lag_change(struct dsa_switch *ds,
-+ struct dsa_notifier_lag_info *info)
-+{
-+ if (ds->index == info->sw_index && ds->ops->port_lag_change)
-+ return ds->ops->port_lag_change(ds, info->port);
-+
-+ if (ds->index != info->sw_index && ds->ops->crosschip_lag_change)
-+ return ds->ops->crosschip_lag_change(ds, info->sw_index,
-+ info->port);
-+
-+ return 0;
-+}
-+
-+static int dsa_switch_lag_join(struct dsa_switch *ds,
-+ struct dsa_notifier_lag_info *info)
-+{
-+ if (ds->index == info->sw_index && ds->ops->port_lag_join)
-+ return ds->ops->port_lag_join(ds, info->port, info->lag,
-+ info->info);
-+
-+ if (ds->index != info->sw_index && ds->ops->crosschip_lag_join)
-+ return ds->ops->crosschip_lag_join(ds, info->sw_index,
-+ info->port, info->lag,
-+ info->info);
-+
-+ return -EOPNOTSUPP;
-+}
-+
-+static int dsa_switch_lag_leave(struct dsa_switch *ds,
-+ struct dsa_notifier_lag_info *info)
-+{
-+ if (ds->index == info->sw_index && ds->ops->port_lag_leave)
-+ return ds->ops->port_lag_leave(ds, info->port, info->lag);
-+
-+ if (ds->index != info->sw_index && ds->ops->crosschip_lag_leave)
-+ return ds->ops->crosschip_lag_leave(ds, info->sw_index,
-+ info->port, info->lag);
-+
-+ return -EOPNOTSUPP;
-+}
-+
- static bool dsa_switch_mdb_match(struct dsa_switch *ds, int port,
- struct dsa_notifier_mdb_info *info)
- {
-@@ -340,6 +381,15 @@ static int dsa_switch_event(struct notif
- case DSA_NOTIFIER_FDB_DEL:
- err = dsa_switch_fdb_del(ds, info);
- break;
-+ case DSA_NOTIFIER_LAG_CHANGE:
-+ err = dsa_switch_lag_change(ds, info);
-+ break;
-+ case DSA_NOTIFIER_LAG_JOIN:
-+ err = dsa_switch_lag_join(ds, info);
-+ break;
-+ case DSA_NOTIFIER_LAG_LEAVE:
-+ err = dsa_switch_lag_leave(ds, info);
-+ break;
- case DSA_NOTIFIER_MDB_ADD:
- err = dsa_switch_mdb_add(ds, info);
- break;
---- a/net/dsa/tag_dsa.c
-+++ b/net/dsa/tag_dsa.c
-@@ -82,7 +82,19 @@ static struct sk_buff *dsa_rcv(struct sk
- source_device = dsa_header[0] & 0x1f;
- source_port = (dsa_header[1] >> 3) & 0x1f;
-
-- skb->dev = dsa_master_find_slave(dev, source_device, source_port);
-+ if (trunk) {
-+ struct dsa_port *cpu_dp = dev->dsa_ptr;
-+
-+ /* The exact source port is not available in the tag,
-+ * so we inject the frame directly on the upper
-+ * team/bond.
-+ */
-+ skb->dev = dsa_lag_dev(cpu_dp->dst, source_port);
-+ } else {
-+ skb->dev = dsa_master_find_slave(dev, source_device,
-+ source_port);
-+ }
-+
- if (!skb->dev)
- return NULL;
-
diff --git a/target/linux/realtek/patches-5.10/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch b/target/linux/realtek/patches-5.10/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch
deleted file mode 100644
index 53fbbccd55..0000000000
--- a/target/linux/realtek/patches-5.10/710-net-phy-sfp-re-probe-modules-on-DEV_UP-event.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From a381ac0aa281fdb0b41a39d8a2bc08fd88f6db92 Mon Sep 17 00:00:00 2001
-From: Antoine Tenart <antoine.tenart@bootlin.com>
-Date: Tue, 25 Feb 2020 16:32:37 +0100
-Subject: [PATCH 1/3] net: phy: sfp: re-probe modules on DEV_UP event
-
-Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
----
- drivers/net/phy/sfp.c | 7 +++++++
- 1 file changed, 7 insertions(+)
-
---- a/drivers/net/phy/sfp.c
-+++ b/drivers/net/phy/sfp.c
-@@ -1968,6 +1968,13 @@ static void sfp_sm_module(struct sfp *sf
- return;
- }
-
-+ /* Re-probe the SFP modules when an interface is brought up, as the MAC
-+ * do not report its link status (This means Phylink wouldn't be
-+ * triggered if the PHY had a link before a MAC is brought up).
-+ */
-+ if (event == SFP_E_DEV_UP && sfp->sm_mod_state == SFP_MOD_PRESENT)
-+ sfp_sm_mod_next(sfp, SFP_MOD_PROBE, T_SERIAL);
-+
- switch (sfp->sm_mod_state) {
- default:
- if (event == SFP_E_INSERT) {
diff --git a/target/linux/realtek/patches-5.10/711-net-phy-add-an-MDIO-SMBus-library.patch b/target/linux/realtek/patches-5.10/711-net-phy-add-an-MDIO-SMBus-library.patch
deleted file mode 100644
index 5e1053ca6c..0000000000
--- a/target/linux/realtek/patches-5.10/711-net-phy-add-an-MDIO-SMBus-library.patch
+++ /dev/null
@@ -1,168 +0,0 @@
-From d585c55b9f70cf9e8c66820d7efe7130c683f19e Mon Sep 17 00:00:00 2001
-From: Antoine Tenart <antoine.tenart@bootlin.com>
-Date: Fri, 21 Feb 2020 11:51:27 +0100
-Subject: [PATCH 2/3] net: phy: add an MDIO SMBus library
-
-Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
----
- drivers/net/mdio/Kconfig | 11 +++++++
- drivers/net/mdio/Makefile | 1 +
- drivers/net/mdio/mdio-smbus.c | 62 +++++++++++++++++++++++++++++++++++
- drivers/net/phy/Kconfig | 1 +
- include/linux/mdio/mdio-i2c.h | 16 +++++++++
- 5 files changed, 91 insertions(+)
- create mode 100644 drivers/net/mdio/mdio-smbus.c
-
---- a/drivers/net/mdio/Kconfig
-+++ b/drivers/net/mdio/Kconfig
-@@ -40,6 +40,17 @@ config MDIO_SUN4I
- interface units of the Allwinner SoC that have an EMAC (A10,
- A12, A10s, etc.)
-
-+config MDIO_SMBUS
-+ tristate
-+ depends on I2C_SMBUS
-+ help
-+ Support SMBus based PHYs. This provides a MDIO bus bridged
-+ to SMBus to allow PHYs connected in SMBus mode to be accessed
-+ using the existing infrastructure.
-+
-+ This is library mode.
-+
-+
- config MDIO_XGENE
- tristate "APM X-Gene SoC MDIO bus controller"
- depends on ARCH_XGENE || COMPILE_TEST
---- a/drivers/net/mdio/Makefile
-+++ b/drivers/net/mdio/Makefile
-@@ -17,6 +17,7 @@ obj-$(CONFIG_MDIO_MOXART) += mdio-moxar
- obj-$(CONFIG_MDIO_MSCC_MIIM) += mdio-mscc-miim.o
- obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
- obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
-+obj-$(CONFIG_MDIO_SMBUS) += mdio-smbus.o
- obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
- obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
- obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
---- /dev/null
-+++ b/drivers/net/mdio/mdio-smbus.c
-@@ -0,0 +1,62 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * MDIO SMBus bridge
-+ *
-+ * Copyright (C) 2020 Antoine Tenart
-+ *
-+ * Network PHYs can appear on SMBus when they are part of SFP modules.
-+ */
-+#include <linux/i2c.h>
-+#include <linux/phy.h>
-+#include <linux/mdio/mdio-i2c.h>
-+
-+static int smbus_mii_read(struct mii_bus *mii, int phy_id, int reg)
-+{
-+ struct i2c_adapter *i2c = mii->priv;
-+ union i2c_smbus_data data;
-+ int ret;
-+
-+ ret = i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, I2C_SMBUS_READ,
-+ reg, I2C_SMBUS_BYTE_DATA, &data);
-+ if (ret < 0)
-+ return 0xff;
-+
-+ return data.byte;
-+}
-+
-+static int smbus_mii_write(struct mii_bus *mii, int phy_id, int reg, u16 val)
-+{
-+ struct i2c_adapter *i2c = mii->priv;
-+ union i2c_smbus_data data;
-+ int ret;
-+
-+ data.byte = val;
-+
-+ ret = i2c_smbus_xfer(i2c, i2c_mii_phy_addr(phy_id), 0, I2C_SMBUS_WRITE,
-+ reg, I2C_SMBUS_BYTE_DATA, &data);
-+ return ret < 0 ? ret : 0;
-+}
-+
-+struct mii_bus *mdio_smbus_alloc(struct device *parent, struct i2c_adapter *i2c)
-+{
-+ struct mii_bus *mii;
-+
-+ if (!i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA))
-+ return ERR_PTR(-EINVAL);
-+
-+ mii = mdiobus_alloc();
-+ if (!mii)
-+ return ERR_PTR(-ENOMEM);
-+
-+ snprintf(mii->id, MII_BUS_ID_SIZE, "smbus:%s", dev_name(parent));
-+ mii->parent = parent;
-+ mii->read = smbus_mii_read;
-+ mii->write = smbus_mii_write;
-+ mii->priv = i2c;
-+
-+ return mii;
-+}
-+
-+MODULE_AUTHOR("Antoine Tenart");
-+MODULE_DESCRIPTION("MDIO SMBus bridge library");
-+MODULE_LICENSE("GPL");
---- a/drivers/net/phy/Kconfig
-+++ b/drivers/net/phy/Kconfig
-@@ -60,6 +60,7 @@ config SFP
- depends on I2C && PHYLINK
- depends on HWMON || HWMON=n
- select MDIO_I2C
-+ select MDIO_SMBUS
-
- comment "Switch configuration API + drivers"
-
---- a/include/linux/mdio/mdio-i2c.h
-+++ b/include/linux/mdio/mdio-i2c.h
-@@ -12,5 +12,21 @@ struct i2c_adapter;
- struct mii_bus;
-
- struct mii_bus *mdio_i2c_alloc(struct device *parent, struct i2c_adapter *i2c);
-+struct mii_bus *mdio_smbus_alloc(struct device *parent, struct i2c_adapter *i2c);
-+
-+/*
-+ * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
-+ * specified to be present in SFP modules. These correspond with PHY
-+ * addresses 16 and 17. Disallow access to these "phy" addresses.
-+ */
-+static bool i2c_mii_valid_phy_id(int phy_id)
-+{
-+ return phy_id != 0x10 && phy_id != 0x11;
-+}
-+
-+static unsigned int i2c_mii_phy_addr(int phy_id)
-+{
-+ return phy_id + 0x40;
-+}
-
- #endif
---- a/drivers/net/mdio/mdio-i2c.c
-+++ b/drivers/net/mdio/mdio-i2c.c
-@@ -13,21 +13,6 @@
- #include <linux/mdio/mdio-i2c.h>
- #include <linux/phy.h>
-
--/*
-- * I2C bus addresses 0x50 and 0x51 are normally an EEPROM, which is
-- * specified to be present in SFP modules. These correspond with PHY
-- * addresses 16 and 17. Disallow access to these "phy" addresses.
-- */
--static bool i2c_mii_valid_phy_id(int phy_id)
--{
-- return phy_id != 0x10 && phy_id != 0x11;
--}
--
--static unsigned int i2c_mii_phy_addr(int phy_id)
--{
-- return phy_id + 0x40;
--}
--
- static int i2c_mii_read(struct mii_bus *bus, int phy_id, int reg)
- {
- struct i2c_adapter *i2c = bus->priv;
diff --git a/target/linux/realtek/patches-5.10/712-net-phy-sfp-add-support-for-SMBus.patch b/target/linux/realtek/patches-5.10/712-net-phy-sfp-add-support-for-SMBus.patch
deleted file mode 100644
index e2540d4512..0000000000
--- a/target/linux/realtek/patches-5.10/712-net-phy-sfp-add-support-for-SMBus.patch
+++ /dev/null
@@ -1,99 +0,0 @@
-From 3cb0bde365d913c484d20224367a54a0eac780a7 Mon Sep 17 00:00:00 2001
-From: Antoine Tenart <antoine.tenart@bootlin.com>
-Date: Fri, 21 Feb 2020 11:55:29 +0100
-Subject: [PATCH 3/3] net: phy: sfp: add support for SMBus
-
-Signed-off-by: Antoine Tenart <antoine.tenart@bootlin.com>
----
- drivers/net/phy/sfp.c | 68 ++++++++++++++++++++++++++++++++++---------
- 1 file changed, 54 insertions(+), 14 deletions(-)
-
---- a/drivers/net/phy/sfp.c
-+++ b/drivers/net/phy/sfp.c
-@@ -419,32 +419,72 @@ static int sfp_i2c_write(struct sfp *sfp
- return ret == ARRAY_SIZE(msgs) ? len : 0;
- }
-
-+static int sfp_smbus_read(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
-+ size_t len)
-+{
-+ u8 bus_addr = a2 ? 0x51 : 0x50, *val = buf;
-+
-+ bus_addr -= 0x40;
-+
-+ while (len > 0) {
-+ *val = sfp->i2c_mii->read(sfp->i2c_mii, bus_addr, dev_addr);
-+
-+ val++;
-+ dev_addr++;
-+ len--;
-+ }
-+
-+ return val - (u8 *)buf;
-+}
-+
-+static int sfp_smbus_write(struct sfp *sfp, bool a2, u8 dev_addr, void *buf,
-+ size_t len)
-+{
-+ u8 bus_addr = a2 ? 0x51 : 0x50;
-+ u16 val;
-+
-+ memcpy(&val, buf, len);
-+
-+ return sfp->i2c_mii->write(sfp->i2c_mii, bus_addr, dev_addr, val);
-+}
-+
- static int sfp_i2c_configure(struct sfp *sfp, struct i2c_adapter *i2c)
- {
-- struct mii_bus *i2c_mii;
-+ struct mii_bus *mii;
- int ret;
-
-- if (!i2c_check_functionality(i2c, I2C_FUNC_I2C))
-- return -EINVAL;
--
- sfp->i2c = i2c;
-- sfp->read = sfp_i2c_read;
-- sfp->write = sfp_i2c_write;
-
-- i2c_mii = mdio_i2c_alloc(sfp->dev, i2c);
-- if (IS_ERR(i2c_mii))
-- return PTR_ERR(i2c_mii);
-+ if (i2c_check_functionality(i2c, I2C_FUNC_I2C)) {
-+ sfp->read = sfp_i2c_read;
-+ sfp->write = sfp_i2c_write;
-+
-+ mii = mdio_i2c_alloc(sfp->dev, i2c);
-+ if (IS_ERR(mii))
-+ return PTR_ERR(mii);
-+
-+ mii->name = "SFP I2C Bus";
-+ } else if (i2c_check_functionality(i2c, I2C_FUNC_SMBUS_BYTE_DATA)) {
-+ sfp->read = sfp_smbus_read;
-+ sfp->write = sfp_smbus_write;
-+
-+ mii = mdio_smbus_alloc(sfp->dev, i2c);
-+ if (IS_ERR(mii))
-+ return PTR_ERR(mii);
-
-- i2c_mii->name = "SFP I2C Bus";
-- i2c_mii->phy_mask = ~0;
-+ mii->name = "SFP SMBus";
-+ } else {
-+ return -EINVAL;
-+ }
-
-- ret = mdiobus_register(i2c_mii);
-+ mii->phy_mask = ~0;
-+ ret = mdiobus_register(mii);
- if (ret < 0) {
-- mdiobus_free(i2c_mii);
-+ mdiobus_free(mii);
- return ret;
- }
-
-- sfp->i2c_mii = i2c_mii;
-+ sfp->i2c_mii = mii;
-
- return 0;
- }
diff --git a/target/linux/realtek/patches-5.10/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch b/target/linux/realtek/patches-5.10/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch
deleted file mode 100644
index a3bfec59ab..0000000000
--- a/target/linux/realtek/patches-5.10/713-v5.12-net-dsa-configure-better-brport-flags-when-ports-lea.patch
+++ /dev/null
@@ -1,148 +0,0 @@
-From: Vladimir Oltean <vladimir.oltean@nxp.com>
-Date: Fri, 12 Feb 2021 17:15:54 +0200
-Subject: [PATCH] net: dsa: configure better brport flags when ports leave the
- bridge
-
-Bugfixed version of upstream commit 5e38c15856e9 ("net: dsa: configure
-better brport flags when ports leave the bridge")
-
-For a DSA switch port operating in standalone mode, address learning
-doesn't make much sense since that is a bridge function. In fact,
-address learning even breaks setups such as this one:
-
- +---------------------------------------------+
- | |
- | +-------------------+ |
- | | br0 | send receive |
- | +--------+-+--------+ +--------+ +--------+ |
- | | | | | | | | | |
- | | swp0 | | swp1 | | swp2 | | swp3 | |
- | | | | | | | | | |
- +-+--------+-+--------+-+--------+-+--------+-+
- | ^ | ^
- | | | |
- | +-----------+ |
- | |
- +--------------------------------+
-
-because if the switch has a single FDB (can offload a single bridge)
-then source address learning on swp3 can "steal" the source MAC address
-of swp2 from br0's FDB, because learning frames coming from swp2 will be
-done twice: first on the swp1 ingress port, second on the swp3 ingress
-port. So the hardware FDB will become out of sync with the software
-bridge, and when swp2 tries to send one more packet towards swp1, the
-ASIC will attempt to short-circuit the forwarding path and send it
-directly to swp3 (since that's the last port it learned that address on),
-which it obviously can't, because swp3 operates in standalone mode.
-
-So DSA drivers operating in standalone mode should still configure a
-list of bridge port flags even when they are standalone. Currently DSA
-attempts to call dsa_port_bridge_flags with 0, which disables egress
-flooding of unknown unicast and multicast, something which doesn't make
-much sense. For the switches that implement .port_egress_floods - b53
-and mv88e6xxx, it probably doesn't matter too much either, since they
-can possibly inject traffic from the CPU into a standalone port,
-regardless of MAC DA, even if egress flooding is turned off for that
-port, but certainly not all DSA switches can do that - sja1105, for
-example, can't. So it makes sense to use a better common default there,
-such as "flood everything".
-
-It should also be noted that what DSA calls "dsa_port_bridge_flags()"
-is a degenerate name for just calling .port_egress_floods(), since
-nothing else is implemented - not learning, in particular. But disabling
-address learning, something that this driver is also coding up for, will
-be supported by individual drivers once .port_egress_floods is replaced
-with a more generic .port_bridge_flags.
-
-Previous attempts to code up this logic have been in the common bridge
-layer, but as pointed out by Ido Schimmel, there are corner cases that
-are missed when doing that:
-https://patchwork.kernel.org/project/netdevbpf/patch/20210209151936.97382-5-olteanv@gmail.com/
-
-So, at least for now, let's leave DSA in charge of setting port flags
-before and after the bridge join and leave.
-
-Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
-Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
-Signed-off-by: David S. Miller <davem@davemloft.net>
-[ backport and bugfix: break dsa_port_bridge_flags() out of loop ]
-Signed-off-by: Bjørn Mork <bjorn@mork.no>
----
- net/dsa/port.c | 45 ++++++++++++++++++++++++++++++++++++++-------
- 1 file changed, 38 insertions(+), 7 deletions(-)
-
---- a/net/dsa/port.c
-+++ b/net/dsa/port.c
-@@ -134,6 +134,27 @@ void dsa_port_disable(struct dsa_port *d
- rtnl_unlock();
- }
-
-+static void dsa_port_change_brport_flags(struct dsa_port *dp,
-+ bool bridge_offload)
-+{
-+ unsigned long mask, flags;
-+ int flag, err;
-+
-+ mask = BR_LEARNING | BR_FLOOD | BR_MCAST_FLOOD | BR_BCAST_FLOOD;
-+ if (bridge_offload)
-+ flags = mask;
-+ else
-+ flags = mask & ~BR_LEARNING;
-+
-+ for_each_set_bit(flag, &mask, 32) {
-+ err = dsa_port_pre_bridge_flags(dp, BIT(flag), NULL, NULL);
-+ if (err)
-+ flags &= ~BIT(flag);
-+ }
-+
-+ dsa_port_bridge_flags(dp, flags, NULL, NULL);
-+}
-+
- int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br)
- {
- struct dsa_notifier_bridge_info info = {
-@@ -144,10 +165,10 @@ int dsa_port_bridge_join(struct dsa_port
- };
- int err;
-
-- /* Set the flooding mode before joining the port in the switch */
-- err = dsa_port_bridge_flags(dp, BR_FLOOD | BR_MCAST_FLOOD, NULL, NULL);
-- if (err)
-- return err;
-+ /* Notify the port driver to set its configurable flags in a way that
-+ * matches the initial settings of a bridge port.
-+ */
-+ dsa_port_change_brport_flags(dp, true);
-
- /* Here the interface is already bridged. Reflect the current
- * configuration so that drivers can program their chips accordingly.
-@@ -158,7 +179,7 @@ int dsa_port_bridge_join(struct dsa_port
-
- /* The bridging is rolled back on error */
- if (err) {
-- dsa_port_bridge_flags(dp, 0, NULL, NULL);
-+ dsa_port_change_brport_flags(dp, false);
- dp->bridge_dev = NULL;
- }
-
-@@ -184,8 +205,18 @@ void dsa_port_bridge_leave(struct dsa_po
- if (err)
- pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n");
-
-- /* Port is leaving the bridge, disable flooding */
-- dsa_port_bridge_flags(dp, 0, NULL, NULL);
-+ /* Configure the port for standalone mode (no address learning,
-+ * flood everything).
-+ * The bridge only emits SWITCHDEV_ATTR_ID_PORT_BRIDGE_FLAGS events
-+ * when the user requests it through netlink or sysfs, but not
-+ * automatically at port join or leave, so we need to handle resetting
-+ * the brport flags ourselves. But we even prefer it that way, because
-+ * otherwise, some setups might never get the notification they need,
-+ * for example, when a port leaves a LAG that offloads the bridge,
-+ * it becomes standalone, but as far as the bridge is concerned, no
-+ * port ever left.
-+ */
-+ dsa_port_change_brport_flags(dp, false);
-
- /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer,
- * so allow it to be in BR_STATE_FORWARDING to be kept functional
diff --git a/target/linux/realtek/patches-5.10/800-net-mdio-support-hardware-assisted-indirect-access.patch b/target/linux/realtek/patches-5.10/800-net-mdio-support-hardware-assisted-indirect-access.patch
deleted file mode 100644
index aca017c03a..0000000000
--- a/target/linux/realtek/patches-5.10/800-net-mdio-support-hardware-assisted-indirect-access.patch
+++ /dev/null
@@ -1,840 +0,0 @@
-From 5d84f16b0036b33487b94abef15ad3c224c81ee9 Mon Sep 17 00:00:00 2001
-From: Daniel Golle <daniel@makrotopia.org>
-Date: Thu, 3 Feb 2022 16:38:50 +0000
-Subject: [PATCH] net: mdio: support hardware-assisted indirect access
-
-MDIO controllers found in Switch-SoCs can offload some MDIO operations
-to the hardware:
- * MMD register access via Clause-22
- Instead of using multiple operations to access MMD registers via
- MII register MII_MMD_CTRL and MII_MMD_DATA some controllers
- allow transparent access to MMD PHY registers.
-
- * paged MII register access
- Some PHYs (namely RealTek and Vitesse) use vendor-defined MII
- register 0x1f for paged access. Some MDIO host controllers support
- transparent paged access when used with such PHYs.
-
- * add convenience accessors to fully support paged access also on
- multi-PHY packages (like the embedded PHYs in RTL83xx):
- phy_package_read_paged and phy_package_write_paged
- phy_package_port_read and phy_package_port_write
- phy_package_port_read_paged and phy_package_port_write_paged
-
-Signed-off-by: Daniel Golle <daniel@makrotopia.org>
----
- drivers/net/phy/mdio_bus.c | 335 ++++++++++++++++++++++++++++++++++++-
- drivers/net/phy/phy-core.c | 66 +++++++-
- include/linux/mdio.h | 59 +++++++
- include/linux/phy.h | 129 ++++++++++++++
- include/uapi/linux/mii.h | 1 +
- 5 files changed, 580 insertions(+), 10 deletions(-)
-
---- a/drivers/net/phy/mdio_bus.c
-+++ b/drivers/net/phy/mdio_bus.c
-@@ -739,6 +739,32 @@ out:
- }
-
- /**
-+ * __mdiobus_select_page - Unlocked version of the mdiobus_select_page function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: register page to select
-+ *
-+ * Selects a MDIO bus register page. Caller must hold the mdio bus lock.
-+ *
-+ * NOTE: MUST NOT be called from interrupt context.
-+ */
-+int __mdiobus_select_page(struct mii_bus *bus, int addr, u16 page)
-+{
-+ lockdep_assert_held_once(&bus->mdio_lock);
-+
-+ if (bus->selected_page[addr] == page)
-+ return 0;
-+
-+ bus->selected_page[addr] = page;
-+ if (bus->read_paged)
-+ return 0;
-+
-+ return bus->write(bus, addr, MII_MAINPAGE, page);
-+
-+}
-+EXPORT_SYMBOL(__mdiobus_select_page);
-+
-+/**
- * __mdiobus_read - Unlocked version of the mdiobus_read function
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -754,7 +780,10 @@ int __mdiobus_read(struct mii_bus *bus,
-
- WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock));
-
-- retval = bus->read(bus, addr, regnum);
-+ if (bus->read_paged)
-+ retval = bus->read_paged(bus, addr, bus->selected_page[addr], regnum);
-+ else
-+ retval = bus->read(bus, addr, regnum);
-
- trace_mdio_access(bus, 1, addr, regnum, retval, retval);
- mdiobus_stats_acct(&bus->stats[addr], true, retval);
-@@ -764,6 +793,40 @@ int __mdiobus_read(struct mii_bus *bus,
- EXPORT_SYMBOL(__mdiobus_read);
-
- /**
-+ * __mdiobus_read_paged - Unlocked version of the mdiobus_read_paged function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to access
-+ * @regnum: register number to read
-+ *
-+ * Read a MDIO bus register. Caller must hold the mdio bus lock.
-+ *
-+ * NOTE: MUST NOT be called from interrupt context.
-+ */
-+int __mdiobus_read_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum)
-+{
-+ int retval;
-+ int oldpage;
-+
-+ lockdep_assert_held_once(&bus->mdio_lock);
-+
-+ if (bus->read_paged) {
-+ retval = bus->read_paged(bus, addr, page, regnum);
-+ } else {
-+ oldpage = bus->selected_page[addr];
-+ __mdiobus_select_page(bus, addr, page);
-+ retval = bus->read(bus, addr, regnum);
-+ __mdiobus_select_page(bus, addr, oldpage);
-+ }
-+
-+ trace_mdio_access(bus, 1, addr, regnum, retval, retval);
-+ mdiobus_stats_acct(&bus->stats[addr], true, retval);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(__mdiobus_read_paged);
-+
-+/**
- * __mdiobus_write - Unlocked version of the mdiobus_write function
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -780,7 +843,10 @@ int __mdiobus_write(struct mii_bus *bus,
-
- WARN_ON_ONCE(!mutex_is_locked(&bus->mdio_lock));
-
-- err = bus->write(bus, addr, regnum, val);
-+ if (bus->write_paged)
-+ err = bus->write_paged(bus, addr, bus->selected_page[addr], regnum, val);
-+ else
-+ err = bus->write(bus, addr, regnum, val);
-
- trace_mdio_access(bus, 0, addr, regnum, val, err);
- mdiobus_stats_acct(&bus->stats[addr], false, err);
-@@ -790,6 +856,39 @@ int __mdiobus_write(struct mii_bus *bus,
- EXPORT_SYMBOL(__mdiobus_write);
-
- /**
-+ * __mdiobus_write_paged - Unlocked version of the mdiobus_write_paged function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to access
-+ * @regnum: register number to write
-+ * @val: value to write to @regnum
-+ *
-+ * Write a MDIO bus register. Caller must hold the mdio bus lock.
-+ *
-+ * NOTE: MUST NOT be called from interrupt context.
-+ */
-+int __mdiobus_write_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 val)
-+{
-+ int err, oldpage;
-+
-+ lockdep_assert_held_once(&bus->mdio_lock);
-+
-+ if (bus->write_paged) {
-+ err = bus->write_paged(bus, addr, page, regnum, val);
-+ } else {
-+ oldpage = bus->selected_page[addr];
-+ __mdiobus_select_page(bus, addr, page);
-+ err = bus->write(bus, addr, regnum, val);
-+ __mdiobus_select_page(bus, addr, oldpage);
-+ }
-+ trace_mdio_access(bus, 0, addr, regnum, val, err);
-+ mdiobus_stats_acct(&bus->stats[addr], false, err);
-+ return err;
-+}
-+EXPORT_SYMBOL(__mdiobus_write_paged);
-+
-+
-+/**
- * __mdiobus_modify_changed - Unlocked version of the mdiobus_modify function
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -822,6 +921,43 @@ int __mdiobus_modify_changed(struct mii_
- EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);
-
- /**
-+ * __mdiobus_modify_changed_paged - Unlocked version of the mdiobus_modify_paged function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @regnum: register number to modify
-+ * @mask: bit mask of bits to clear
-+ * @set: bit mask of bits to set
-+ *
-+ * Read, modify, and if any change, write the register value back to the
-+ * device. Any error returns a negative number.
-+ *
-+ * NOTE: MUST NOT be called from interrupt context.
-+ */
-+int __mdiobus_modify_changed_paged(struct mii_bus *bus, int addr, u32 regnum, u16 page,
-+ u16 mask, u16 set)
-+{
-+ int new, ret, oldpage;
-+
-+ oldpage = bus->selected_page[addr];
-+ __mdiobus_select_page(bus, addr, page);
-+
-+ ret = __mdiobus_read_paged(bus, addr, page, regnum);
-+ if (ret < 0)
-+ return ret;
-+
-+ new = (ret & ~mask) | set;
-+ if (new == ret)
-+ return 0;
-+
-+ ret = __mdiobus_write_paged(bus, addr, page, regnum, new);
-+
-+ __mdiobus_select_page(bus, addr, oldpage);
-+
-+ return ret < 0 ? ret : 1;
-+}
-+EXPORT_SYMBOL_GPL(__mdiobus_modify_changed_paged);
-+
-+/**
- * mdiobus_read_nested - Nested version of the mdiobus_read function
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -847,6 +983,79 @@ int mdiobus_read_nested(struct mii_bus *
- EXPORT_SYMBOL(mdiobus_read_nested);
-
- /**
-+ * mdiobus_select_page_nested - Nested version of the mdiobus_select_page function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: register page to access
-+ *
-+ * In case of nested MDIO bus access avoid lockdep false positives by
-+ * using mutex_lock_nested().
-+ *
-+ * NOTE: MUST NOT be called from interrupt context,
-+ * because the bus read/write functions may wait for an interrupt
-+ * to conclude the operation.
-+ */
-+int mdiobus_select_page_nested(struct mii_bus *bus, int addr, u16 page)
-+{
-+ int retval;
-+
-+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
-+ retval = __mdiobus_select_page(bus, addr, page);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(mdiobus_select_page_nested);
-+
-+/**
-+ * mdiobus_read_paged_nested - Nested version of the mdiobus_read_paged function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: register page to access
-+ * @regnum: register number to read
-+ *
-+ * In case of nested MDIO bus access avoid lockdep false positives by
-+ * using mutex_lock_nested().
-+ *
-+ * NOTE: MUST NOT be called from interrupt context,
-+ * because the bus read/write functions may wait for an interrupt
-+ * to conclude the operation.
-+ */
-+int mdiobus_read_paged_nested(struct mii_bus *bus, int addr, u16 page, u32 regnum)
-+{
-+ int retval;
-+
-+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
-+ retval = __mdiobus_read_paged(bus, addr, page, regnum);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(mdiobus_read_paged_nested);
-+
-+/**
-+ * mdiobus_select_page - Convenience function for setting the MII register page
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to set
-+ *
-+ * NOTE: MUST NOT be called from interrupt context,
-+ * because the bus read/write functions may wait for an interrupt
-+ * to conclude the operation.
-+ */
-+int mdiobus_select_page(struct mii_bus *bus, int addr, u16 page)
-+{
-+ int retval;
-+
-+ mutex_lock(&bus->mdio_lock);
-+ retval = __mdiobus_select_page(bus, addr, page);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(mdiobus_select_page);
-+
-+/**
- * mdiobus_read - Convenience function for reading a given MII mgmt register
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -869,6 +1078,29 @@ int mdiobus_read(struct mii_bus *bus, in
- EXPORT_SYMBOL(mdiobus_read);
-
- /**
-+ * mdiobus_read_paged - Convenience function for reading a given paged MII mgmt register
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: register page to access
-+ * @regnum: register number to read
-+ *
-+ * NOTE: MUST NOT be called from interrupt context,
-+ * because the bus read/write functions may wait for an interrupt
-+ * to conclude the operation.
-+ */
-+int mdiobus_read_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum)
-+{
-+ int retval;
-+
-+ mutex_lock(&bus->mdio_lock);
-+ retval = __mdiobus_read_paged(bus, addr, page, regnum);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return retval;
-+}
-+EXPORT_SYMBOL(mdiobus_read_paged);
-+
-+/**
- * mdiobus_write_nested - Nested version of the mdiobus_write function
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -895,6 +1127,33 @@ int mdiobus_write_nested(struct mii_bus
- EXPORT_SYMBOL(mdiobus_write_nested);
-
- /**
-+ * mdiobus_write_paged_nested - Nested version of the mdiobus_write_aged function
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to access
-+ * @regnum: register number to write
-+ * @val: value to write to @regnum
-+ *
-+ * In case of nested MDIO bus access avoid lockdep false positives by
-+ * using mutex_lock_nested().
-+ *
-+ * NOTE: MUST NOT be called from interrupt context,
-+ * because the bus read/write functions may wait for an interrupt
-+ * to conclude the operation.
-+ */
-+int mdiobus_write_paged_nested(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 val)
-+{
-+ int err;
-+
-+ mutex_lock_nested(&bus->mdio_lock, MDIO_MUTEX_NESTED);
-+ err = __mdiobus_write_paged(bus, addr, page, regnum, val);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return err;
-+}
-+EXPORT_SYMBOL(mdiobus_write_paged_nested);
-+
-+/**
- * mdiobus_write - Convenience function for writing a given MII mgmt register
- * @bus: the mii_bus struct
- * @addr: the phy address
-@@ -918,6 +1177,30 @@ int mdiobus_write(struct mii_bus *bus, i
- EXPORT_SYMBOL(mdiobus_write);
-
- /**
-+ * mdiobus_write_paged - Convenience function for writing a given paged MII mgmt register
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to access
-+ * @regnum: register number to write
-+ * @val: value to write to @regnum
-+ *
-+ * NOTE: MUST NOT be called from interrupt context,
-+ * because the bus read/write functions may wait for an interrupt
-+ * to conclude the operation.
-+ */
-+int mdiobus_write_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 val)
-+{
-+ int err;
-+
-+ mutex_lock(&bus->mdio_lock);
-+ err = __mdiobus_write_paged(bus, addr, page, regnum, val);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return err;
-+}
-+EXPORT_SYMBOL(mdiobus_write_paged);
-+
-+/**
- * mdiobus_modify - Convenience function for modifying a given mdio device
- * register
- * @bus: the mii_bus struct
-@@ -939,6 +1222,51 @@ int mdiobus_modify(struct mii_bus *bus,
- EXPORT_SYMBOL_GPL(mdiobus_modify);
-
- /**
-+ * mdiobus_modify_paged - Convenience function for modifying a given mdio device
-+ * register
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to access
-+ * @regnum: register number to write
-+ * @mask: bit mask of bits to clear
-+ * @set: bit mask of bits to set
-+ */
-+int mdiobus_modify_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 mask, u16 set)
-+{
-+ int err;
-+
-+ mutex_lock(&bus->mdio_lock);
-+ err = __mdiobus_modify_changed_paged(bus, addr, page, regnum, mask, set);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return err < 0 ? err : 0;
-+}
-+EXPORT_SYMBOL_GPL(mdiobus_modify_paged);
-+
-+/**
-+ * mdiobus_modify_changed_paged - Convenience function for modifying a given paged
-+ * mdio device register and returning if it changed
-+ * @bus: the mii_bus struct
-+ * @addr: the phy address
-+ * @page: the register page to access
-+ * @regnum: register number to write
-+ * @mask: bit mask of bits to clear
-+ * @set: bit mask of bits to set
-+ */
-+int mdiobus_modify_changed_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum,
-+ u16 mask, u16 set)
-+{
-+ int err;
-+
-+ mutex_lock(&bus->mdio_lock);
-+ err = __mdiobus_modify_changed_paged(bus, addr, page, regnum, mask, set);
-+ mutex_unlock(&bus->mdio_lock);
-+
-+ return err;
-+}
-+EXPORT_SYMBOL_GPL(mdiobus_modify_changed_paged);
-+
-+/**
- * mdio_bus_match - determine if given MDIO driver supports the given
- * MDIO device
- * @dev: target MDIO device
---- a/drivers/net/phy/phy-core.c
-+++ b/drivers/net/phy/phy-core.c
-@@ -481,10 +481,16 @@ int __phy_read_mmd(struct phy_device *ph
- struct mii_bus *bus = phydev->mdio.bus;
- int phy_addr = phydev->mdio.addr;
-
-- mmd_phy_indirect(bus, phy_addr, devad, regnum);
--
-- /* Read the content of the MMD's selected register */
-- val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
-+ if (bus->access_capabilities & MDIOBUS_ACCESS_C22_MMD) {
-+ val = __mdiobus_c22_mmd_read(phydev->mdio.bus,
-+ phydev->mdio.addr,
-+ devad, regnum);
-+ } else {
-+ mmd_phy_indirect(bus, phy_addr, devad, regnum);
-+
-+ /* Read the content of the MMD's selected register */
-+ val = __mdiobus_read(bus, phy_addr, MII_MMD_DATA);
-+ }
- }
- return val;
- }
-@@ -537,12 +543,18 @@ int __phy_write_mmd(struct phy_device *p
- struct mii_bus *bus = phydev->mdio.bus;
- int phy_addr = phydev->mdio.addr;
-
-- mmd_phy_indirect(bus, phy_addr, devad, regnum);
-+ if (bus->access_capabilities & MDIOBUS_ACCESS_C22_MMD) {
-+ ret = __mdiobus_c22_mmd_write(phydev->mdio.bus,
-+ phydev->mdio.addr,
-+ devad, regnum, val);
-+ } else {
-+ mmd_phy_indirect(bus, phy_addr, devad, regnum);
-
-- /* Write the data into MMD's selected register */
-- __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
-+ /* Write the data into MMD's selected register */
-+ __mdiobus_write(bus, phy_addr, MII_MMD_DATA, val);
-
-- ret = 0;
-+ ret = 0;
-+ }
- }
- return ret;
- }
-@@ -748,6 +760,13 @@ EXPORT_SYMBOL_GPL(phy_modify_mmd);
-
- static int __phy_read_page(struct phy_device *phydev)
- {
-+ if (phydev->drv && phydev->drv->flags & PHY_HAS_REALTEK_PAGES) {
-+ struct mii_bus *bus = phydev->mdio.bus;
-+ int phy_addr = phydev->mdio.addr;
-+
-+ return bus->selected_page[phy_addr];
-+ }
-+
- if (WARN_ONCE(!phydev->drv->read_page, "read_page callback not available, PHY driver not loaded?\n"))
- return -EOPNOTSUPP;
-
-@@ -756,6 +775,13 @@ static int __phy_read_page(struct phy_de
-
- static int __phy_write_page(struct phy_device *phydev, int page)
- {
-+ if (phydev->drv && phydev->drv->flags & PHY_HAS_REALTEK_PAGES) {
-+ struct mii_bus *bus = phydev->mdio.bus;
-+ int phy_addr = phydev->mdio.addr;
-+
-+ return __mdiobus_select_page(bus, phy_addr, page);
-+ }
-+
- if (WARN_ONCE(!phydev->drv->write_page, "write_page callback not available, PHY driver not loaded?\n"))
- return -EOPNOTSUPP;
-
-@@ -857,6 +883,18 @@ int phy_read_paged(struct phy_device *ph
- {
- int ret = 0, oldpage;
-
-+ if (phydev->drv && phydev->drv->flags & PHY_HAS_REALTEK_PAGES) {
-+ struct mii_bus *bus = phydev->mdio.bus;
-+ int phy_addr = phydev->mdio.addr;
-+
-+ if (bus->read_paged) {
-+ phy_lock_mdio_bus(phydev);
-+ ret = bus->read_paged(bus, phy_addr, page, regnum);
-+ phy_unlock_mdio_bus(phydev);
-+ return ret;
-+ }
-+ }
-+
- oldpage = phy_select_page(phydev, page);
- if (oldpage >= 0)
- ret = __phy_read(phydev, regnum);
-@@ -878,6 +916,18 @@ int phy_write_paged(struct phy_device *p
- {
- int ret = 0, oldpage;
-
-+ if (phydev->drv && phydev->drv->flags & PHY_HAS_REALTEK_PAGES) {
-+ struct mii_bus *bus = phydev->mdio.bus;
-+ int phy_addr = phydev->mdio.addr;
-+
-+ if (bus->write_paged) {
-+ phy_lock_mdio_bus(phydev);
-+ ret = bus->write_paged(bus, phy_addr, page, regnum, val);
-+ phy_unlock_mdio_bus(phydev);
-+ return ret;
-+ }
-+ }
-+
- oldpage = phy_select_page(phydev, page);
- if (oldpage >= 0)
- ret = __phy_write(phydev, regnum, val);
---- a/include/linux/mdio.h
-+++ b/include/linux/mdio.h
-@@ -14,6 +14,7 @@
- * IEEE 802.3ae clause 45 addressing mode used by 10GIGE phy chips.
- */
- #define MII_ADDR_C45 (1<<30)
-+#define MII_ADDR_C22_MMD (1<<29)
- #define MII_DEVADDR_C45_SHIFT 16
- #define MII_DEVADDR_C45_MASK GENMASK(20, 16)
- #define MII_REGADDR_C45_MASK GENMASK(15, 0)
-@@ -327,11 +328,19 @@ static inline void mii_10gbt_stat_mod_li
- advertising, lpa & MDIO_AN_10GBT_STAT_LP10G);
- }
-
-+int __mdiobus_select_page(struct mii_bus *bus, int addr, u16 page);
- int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
- int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
- int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
- u16 mask, u16 set);
-
-+int __mdiobus_read_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum);
-+int __mdiobus_write_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 val);
-+int __mdiobus_modify_changed_paged(struct mii_bus *bus, int addr, u32 regnum, u16 page,
-+ u16 mask, u16 set);
-+
-+int mdiobus_select_page(struct mii_bus *bus, int addr, u16 page);
-+int mdiobus_select_page_nested(struct mii_bus *bus, int addr, u16 page);
- int mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
- int mdiobus_read_nested(struct mii_bus *bus, int addr, u32 regnum);
- int mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
-@@ -339,11 +348,51 @@ int mdiobus_write_nested(struct mii_bus
- int mdiobus_modify(struct mii_bus *bus, int addr, u32 regnum, u16 mask,
- u16 set);
-
-+int mdiobus_read_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum);
-+int mdiobus_read_nested_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum);
-+int mdiobus_write_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 val);
-+int mdiobus_write_nested_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 val);
-+int mdiobus_modify_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum, u16 mask,
-+ u16 set);
-+int mdiobus_modify_changed_paged(struct mii_bus *bus, int addr, u16 page, u32 regnum,
-+ u16 mask, u16 set);
-+
-+static inline int mdiodev_read_paged(struct mdio_device *mdiodev, u16 page,
-+ u32 regnum)
-+{
-+ return mdiobus_read_paged(mdiodev->bus, mdiodev->addr, page, regnum);
-+}
-+
-+static inline int mdiodev_write_paged(struct mdio_device *mdiodev, u16 page,
-+ u32 regnum, u16 val)
-+{
-+ return mdiobus_write_paged(mdiodev->bus, mdiodev->addr, page, regnum, val);
-+}
-+
-+static inline int mdiodev_modify_paged(struct mdio_device *mdiodev, u16 page,
-+ u32 regnum, u16 mask, u16 set)
-+{
-+ return mdiobus_modify_paged(mdiodev->bus, mdiodev->addr, page, regnum,
-+ mask, set);
-+}
-+
-+static inline int mdiodev_modify_changed_paged(struct mdio_device *mdiodev, u16 page,
-+ u32 regnum, u16 mask, u16 set)
-+{
-+ return mdiobus_modify_changed_paged(mdiodev->bus, mdiodev->addr, page, regnum,
-+ mask, set);
-+}
-+
- static inline u32 mdiobus_c45_addr(int devad, u16 regnum)
- {
- return MII_ADDR_C45 | devad << MII_DEVADDR_C45_SHIFT | regnum;
- }
-
-+static inline u32 mdiobus_c22_mmd_addr(int devad, u16 regnum)
-+{
-+ return MII_ADDR_C22_MMD | devad << MII_DEVADDR_C45_SHIFT | regnum;
-+}
-+
- static inline u16 mdiobus_c45_regad(u32 regnum)
- {
- return FIELD_GET(MII_REGADDR_C45_MASK, regnum);
-@@ -367,6 +416,19 @@ static inline int __mdiobus_c45_write(st
- val);
- }
-
-+static inline int __mdiobus_c22_mmd_read(struct mii_bus *bus, int prtad,
-+ int devad, u16 regnum)
-+{
-+ return __mdiobus_read(bus, prtad, mdiobus_c22_mmd_addr(devad, regnum));
-+}
-+
-+static inline int __mdiobus_c22_mmd_write(struct mii_bus *bus, int prtad,
-+ int devad, u16 regnum, u16 val)
-+{
-+ return __mdiobus_write(bus, prtad, mdiobus_c22_mmd_addr(devad, regnum),
-+ val);
-+}
-+
- static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
- u16 regnum)
- {
---- a/include/linux/phy.h
-+++ b/include/linux/phy.h
-@@ -80,6 +80,7 @@ extern const int phy_10gbit_features_arr
- #define PHY_IS_INTERNAL 0x00000001
- #define PHY_RST_AFTER_CLK_EN 0x00000002
- #define PHY_POLL_CABLE_TEST 0x00000004
-+#define PHY_HAS_REALTEK_PAGES 0x00000010
- #define MDIO_DEVICE_IS_PHY 0x80000000
-
- /**
-@@ -374,6 +375,22 @@ struct mii_bus {
-
- /** @shared: shared state across different PHYs */
- struct phy_package_shared *shared[PHY_MAX_ADDR];
-+
-+ /** @access_capabilities: hardware-assisted access capabilties */
-+ enum {
-+ MDIOBUS_ACCESS_SOFTWARE_ONLY = 0,
-+ MDIOBUS_ACCESS_C22_MMD = 0x1,
-+ } access_capabilities;
-+
-+ /** @read: Perform a read transfer on the bus, offloading page access */
-+ int (*read_paged)(struct mii_bus *bus, int addr, u16 page, int regnum);
-+ /** @write: Perform a write transfer on the bus, offloading page access */
-+ int (*write_paged)(struct mii_bus *bus, int addr, u16 page, int regnum, u16 val);
-+ /** currently selected page when page access is offloaded
-+ * array should be PHY_MAX_ADDR+1size, but current design of the MDIO driver
-+ * uses port addresses as phy addresses and they are up to 6 bit.
-+ */
-+ u16 selected_page[64];
- };
- #define to_mii_bus(d) container_of(d, struct mii_bus, dev)
-
-@@ -1651,6 +1668,66 @@ static inline int __phy_package_read(str
- return __mdiobus_read(phydev->mdio.bus, shared->addr, regnum);
- }
-
-+static inline int phy_package_read_port(struct phy_device *phydev, u16 port, u32 regnum)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return mdiobus_read(phydev->mdio.bus, shared->addr + port, regnum);
-+}
-+
-+static inline int __phy_package_read_port(struct phy_device *phydev, u16 port, u32 regnum)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return __mdiobus_read(phydev->mdio.bus, shared->addr + port, regnum);
-+}
-+
-+static inline int phy_package_read_paged(struct phy_device *phydev, u16 page, u32 regnum)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return mdiobus_read_paged(phydev->mdio.bus, shared->addr, page, regnum);
-+}
-+
-+static inline int __phy_package_read_paged(struct phy_device *phydev, u16 page, u32 regnum)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return __mdiobus_read_paged(phydev->mdio.bus, shared->addr, page, regnum);
-+}
-+
-+static inline int phy_package_port_read_paged(struct phy_device *phydev, u16 port, u16 page, u32 regnum)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return mdiobus_read_paged(phydev->mdio.bus, shared->addr + port, page, regnum);
-+}
-+
-+static inline int __phy_package_port_read_paged(struct phy_device *phydev, u16 port, u16 page, u32 regnum)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return __mdiobus_read_paged(phydev->mdio.bus, shared->addr + port, page, regnum);
-+}
-+
- static inline int phy_package_write(struct phy_device *phydev,
- u32 regnum, u16 val)
- {
-@@ -1673,6 +1750,72 @@ static inline int __phy_package_write(st
- return __mdiobus_write(phydev->mdio.bus, shared->addr, regnum, val);
- }
-
-+static inline int phy_package_port_write(struct phy_device *phydev,
-+ u16 port, u32 regnum, u16 val)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return mdiobus_write(phydev->mdio.bus, shared->addr + port, regnum, val);
-+}
-+
-+static inline int __phy_package_port_write(struct phy_device *phydev,
-+ u16 port, u32 regnum, u16 val)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return __mdiobus_write(phydev->mdio.bus, shared->addr + port, regnum, val);
-+}
-+
-+static inline int phy_package_port_write_paged(struct phy_device *phydev,
-+ u16 port, u16 page, u32 regnum, u16 val)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return mdiobus_write_paged(phydev->mdio.bus, shared->addr + port, page, regnum, val);
-+}
-+
-+static inline int __phy_package_port_write_paged(struct phy_device *phydev,
-+ u16 port, u16 page, u32 regnum, u16 val)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return __mdiobus_write_paged(phydev->mdio.bus, shared->addr + port, page, regnum, val);
-+}
-+
-+static inline int phy_package_write_paged(struct phy_device *phydev,
-+ u16 page, u32 regnum, u16 val)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return mdiobus_write_paged(phydev->mdio.bus, shared->addr, page, regnum, val);
-+}
-+
-+static inline int __phy_package_write_paged(struct phy_device *phydev,
-+ u16 page, u32 regnum, u16 val)
-+{
-+ struct phy_package_shared *shared = phydev->shared;
-+
-+ if (!shared)
-+ return -EIO;
-+
-+ return __mdiobus_write_paged(phydev->mdio.bus, shared->addr, page, regnum, val);
-+}
-+
- static inline bool __phy_package_set_once(struct phy_device *phydev,
- unsigned int b)
- {
---- a/include/uapi/linux/mii.h
-+++ b/include/uapi/linux/mii.h
-@@ -36,6 +36,7 @@
- #define MII_RESV2 0x1a /* Reserved... */
- #define MII_TPISTATUS 0x1b /* TPI status for 10mbps */
- #define MII_NCONFIG 0x1c /* Network interface config */
-+#define MII_MAINPAGE 0x1f /* Page register */
-
- /* Basic mode control register. */
- #define BMCR_RESV 0x003f /* Unused... */