]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
econet: add EN7528 subtarget support
authorAhmed Naseef <naseefkm@gmail.com>
Mon, 29 Dec 2025 09:12:20 +0000 (13:12 +0400)
committerHauke Mehrtens <hauke@hauke-m.de>
Sun, 15 Feb 2026 00:12:52 +0000 (01:12 +0100)
The EN7528 is a little endian dual-core MIPS 1004Kc SoC used in xPON
devices. Unlike the big endian EN751221, EN7528 uses the MIPS GIC
interrupt controller for SMP.

This adds minimal boot support for EN7528:
- New en7528 subtarget with mipsel architecture
- Kernel patches for EN7528 SoC with GIC support
- Timer driver extended to support GIC shared interrupts per CPU
- SPI driver fix for EN7528 chip select handling
- Generic device tree for initial bring-up

Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
Link: https://github.com/openwrt/openwrt/pull/21326
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
15 files changed:
target/linux/econet/Makefile
target/linux/econet/dts/en7528.dtsi [new file with mode: 0644]
target/linux/econet/dts/en7528_generic.dts [new file with mode: 0644]
target/linux/econet/en751221/config-6.12
target/linux/econet/en751221/target.mk
target/linux/econet/en7528/config-6.12 [new file with mode: 0644]
target/linux/econet/en7528/profiles/00-default.mk [new file with mode: 0644]
target/linux/econet/en7528/target.mk [new file with mode: 0644]
target/linux/econet/image/en7528.mk [new file with mode: 0644]
target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch [new file with mode: 0644]
target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch [new file with mode: 0644]
target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch [new file with mode: 0644]
target/linux/econet/patches-6.12/310-usb-enable-econet-usb.patch
target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch [new file with mode: 0644]
target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch [new file with mode: 0644]

index 28b8ab33adb6d139ba1fa4110a05682a01c18828..f3e8af3945c23d483857c6d055a51135458f37b8 100644 (file)
@@ -4,11 +4,10 @@
 
 include $(TOPDIR)/rules.mk
 
-ARCH:=mips
 BOARD:=econet
 BOARDNAME:=EcoNet EN75xx MIPS
 FEATURES:=dt source-only squashfs nand usb
-SUBTARGETS:=en751221
+SUBTARGETS:=en751221 en7528
 
 KERNEL_PATCHVER:=6.12
 
diff --git a/target/linux/econet/dts/en7528.dtsi b/target/linux/econet/dts/en7528.dtsi
new file mode 100644 (file)
index 0000000..78eab98
--- /dev/null
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+#include <dt-bindings/interrupt-controller/mips-gic.h>
+
+/ {
+       compatible = "econet,en7528";
+       #address-cells = <1>;
+       #size-cells = <1>;
+
+       hpt_clock: clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <200000000>;  /* 200 MHz */
+       };
+
+       spi_clock: spi-clock {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <40000000>;  /* 40 MHz */
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu@0 {
+                       device_type = "cpu";
+                       compatible = "mips,mips1004Kc";
+                       reg = <0>;
+               };
+
+               cpu@1 {
+                       device_type = "cpu";
+                       compatible = "mips,mips1004Kc";
+                       reg = <1>;
+               };
+       };
+
+       cpuintc: interrupt-controller {
+               compatible = "mti,cpu-interrupt-controller";
+               interrupt-controller;
+               #address-cells = <0>;
+               #interrupt-cells = <1>;
+       };
+
+       gic: interrupt-controller@1f8c0000 {
+               compatible = "mti,gic";
+               reg = <0x1f8c0000 0x20000>;
+
+               interrupt-controller;
+               #interrupt-cells = <3>;
+
+               interrupt-parent = <&cpuintc>;
+               interrupts = <2>;
+       };
+
+       timer_hpt: timer@1fbf0400 {
+               compatible = "econet,en7528-timer";
+               reg = <0x1fbf0400 0x14>,
+                     <0x1fbe0000 0x14>;
+
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_SHARED 30 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SHARED 29 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SHARED 37 IRQ_TYPE_LEVEL_HIGH>,
+                            <GIC_SHARED 36 IRQ_TYPE_LEVEL_HIGH>;
+
+               clocks = <&hpt_clock>;
+       };
+
+       spi_ctrl: spi@1fa10000 {
+               compatible = "airoha,en7581-snand";
+               reg = <0x1fa10000 0x140>,
+                     <0x1fa11000 0x160>;
+
+               clocks = <&spi_clock>;
+               clock-names = "spi";
+
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               nand: nand@0 {
+                       compatible = "spi-nand";
+                       reg = <0>;
+                       spi-max-frequency = <40000000>;
+                       spi-tx-bus-width = <1>;
+                       spi-rx-bus-width = <2>;
+               };
+       };
+
+       uart: serial@1fbf0000 {
+               compatible = "airoha,en7523-uart";
+               reg = <0x1fbf0000 0x30>;
+               reg-io-width = <4>;
+               reg-shift = <2>;
+
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_SHARED 2 IRQ_TYPE_LEVEL_HIGH>;
+
+               clock-frequency = <7372800>;
+       };
+};
diff --git a/target/linux/econet/dts/en7528_generic.dts b/target/linux/econet/dts/en7528_generic.dts
new file mode 100644 (file)
index 0000000..2a3835e
--- /dev/null
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/dts-v1/;
+
+#include "en7528.dtsi"
+
+/ {
+       model = "Generic EN7528";
+       compatible = "econet,en7528-generic", "econet,en7528";
+
+       memory@0 {
+               // We hope at least 64MB will be available on every device
+               device_type = "memory";
+               reg = <0x00000000 0x4000000>;
+       };
+
+       chosen {
+               stdout-path = "serial0:115200n8";
+               linux,usable-memory-range = <0x00020000 0x3fe0000>;
+       };
+
+       aliases {
+               serial0 = &uart;
+       };
+};
+
+&nand {
+       status = "okay";
+
+       partitions {
+               compatible = "fixed-partitions";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               partition@1 {
+                       // We don't know how big the flash is
+                       // Put 1GB and let it truncate
+                       label = "all_flash";
+                       reg = <0x0 0x40000000>;
+                       read-only;
+               };
+
+               partition@2 {
+                       // We don't know how big the bootloader
+                       // is, but when we're doing testing, lets
+                       // make sure nobody touches anything below 4MB
+                       label = "bootloader";
+                       reg = <0x0 0x00400000>;
+                       read-only;
+               };
+
+               partition@3 {
+                       label = "rest_of_flash";
+                       reg = <0x00400000 0x40000000>;
+               };
+       };
+};
index b8a52c0f9d9b680df1e96e9e492210d28c71986c..e9137a0e9fc4c587328bdcb3372dc1c258e65227 100644 (file)
@@ -147,6 +147,7 @@ CONFIG_RESET_CONTROLLER=y
 CONFIG_RFS_ACCEL=y
 CONFIG_RPS=y
 CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES=y
+# CONFIG_SERIAL_8250_AIROHA is not set
 CONFIG_SERIAL_MCTRL_GPIO=y
 CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SGL_ALLOC=y
@@ -154,8 +155,10 @@ CONFIG_SMP=y
 CONFIG_SMP_UP=y
 CONFIG_SOCK_RX_QUEUE_MAPPING=y
 CONFIG_SOC_ECONET_EN751221=y
+# CONFIG_SOC_ECONET_EN7528 is not set
 CONFIG_SPI=y
 CONFIG_SPI_AIROHA_EN7523=y
+# CONFIG_SPI_AIROHA_SNFI is not set
 CONFIG_SPI_MASTER=y
 CONFIG_SPI_MEM=y
 CONFIG_SYSCTL_EXCEPTION_TRACE=y
index e54fb3e6f629682829a72e536f5e96c57e7882f7..823ffde7cf956a65335b5e1cda4fa21ccc4a2550 100644 (file)
@@ -1,3 +1,4 @@
+ARCH:=mips
 BOARDNAME:=en751221
 CPU_TYPE:=24kc
 KERNELNAME:=vmlinuz.bin
diff --git a/target/linux/econet/en7528/config-6.12 b/target/linux/econet/en7528/config-6.12
new file mode 100644 (file)
index 0000000..c956eb0
--- /dev/null
@@ -0,0 +1,216 @@
+CONFIG_ARCH_32BIT_OFF_T=y
+CONFIG_ARCH_HIBERNATION_POSSIBLE=y
+CONFIG_ARCH_KEEP_MEMBLOCK=y
+CONFIG_ARCH_MMAP_RND_BITS_MAX=15
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MAX=15
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_BOARD_SCACHE=y
+CONFIG_CLKSRC_MMIO=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+# CONFIG_COMMON_CLK_EN7523 is not set
+CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
+CONFIG_COMPAT_32BIT_TIME=y
+CONFIG_CONTEXT_TRACKING=y
+CONFIG_CONTEXT_TRACKING_IDLE=y
+CONFIG_CPU_GENERIC_DUMP_TLB=y
+CONFIG_CPU_HAS_DIEI=y
+CONFIG_CPU_HAS_PREFETCH=y
+CONFIG_CPU_HAS_RIXI=y
+CONFIG_CPU_HAS_SYNC=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_MIPS32=y
+# CONFIG_CPU_MIPS32_R1 is not set
+CONFIG_CPU_MIPS32_R2=y
+CONFIG_CPU_MIPSR2=y
+CONFIG_CPU_MIPSR2_IRQ_EI=y
+CONFIG_CPU_MIPSR2_IRQ_VI=y
+CONFIG_CPU_MITIGATIONS=y
+CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y
+CONFIG_CPU_R4K_CACHE_TLB=y
+CONFIG_CPU_RMAP=y
+CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
+CONFIG_CPU_SUPPORTS_HIGHMEM=y
+CONFIG_CPU_SUPPORTS_MSA=y
+CONFIG_CRC16=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_HASH_INFO=y
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+CONFIG_CRYPTO_LIB_GF128MUL=y
+CONFIG_CRYPTO_LIB_POLY1305_RSIZE=2
+CONFIG_CRYPTO_LIB_SHA1=y
+CONFIG_CRYPTO_LIB_UTILS=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_ZSTD=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_ZBOOT=y
+CONFIG_DMA_NEED_SYNC=y
+CONFIG_DMA_NONCOHERENT=y
+CONFIG_DTB_ECONET_NONE=y
+CONFIG_DTC=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_EARLY_PRINTK_8250=y
+CONFIG_ECONET=y
+CONFIG_ECONET_EN751221_TIMER=y
+CONFIG_EXCLUSIVE_SYSTEM_RAM=y
+CONFIG_FS_IOMAP=y
+CONFIG_FUNCTION_ALIGNMENT=0
+CONFIG_FW_LOADER_PAGED_BUF=y
+CONFIG_FW_LOADER_SYSFS=y
+CONFIG_GENERIC_ATOMIC64=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CMOS_UPDATE=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IOMAP=y
+CONFIG_GENERIC_IRQ_CHIP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_LIB_ASHLDI3=y
+CONFIG_GENERIC_LIB_ASHRDI3=y
+CONFIG_GENERIC_LIB_CMPDI2=y
+CONFIG_GENERIC_LIB_LSHRDI3=y
+CONFIG_GENERIC_LIB_UCMPDI2=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GPIO_CDEV=y
+CONFIG_HARDWARE_WATCHPOINTS=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HZ_PERIODIC=y
+CONFIG_INITRAMFS_SOURCE=""
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_MIPS_CPU=y
+CONFIG_IRQ_WORK=y
+# CONFIG_JFFS2_FS is not set
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_MIGRATION=y
+CONFIG_MIPS=y
+CONFIG_MIPS_ASID_BITS=8
+CONFIG_MIPS_ASID_SHIFT=0
+CONFIG_MIPS_CM=y
+# CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set
+CONFIG_MIPS_CMDLINE_FROM_DTB=y
+CONFIG_MIPS_CPC=y
+CONFIG_MIPS_CPS=y
+# CONFIG_MIPS_CPS_NS16550_BOOL is not set
+CONFIG_MIPS_CPU_SCACHE=y
+CONFIG_MIPS_GIC=y
+CONFIG_MIPS_L1_CACHE_SHIFT=5
+CONFIG_MIPS_MT=y
+CONFIG_MIPS_MT_FPAFF=y
+CONFIG_MIPS_MT_SMP=y
+# CONFIG_MIPS_NO_APPENDED_DTB is not set
+CONFIG_MIPS_NR_CPU_NR_MAP=4
+CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y
+CONFIG_MIPS_RAW_APPENDED_DTB=y
+CONFIG_MIPS_SPRAM=y
+CONFIG_MMU_LAZY_TLB_REFCOUNT=y
+CONFIG_MODULES_USE_ELF_REL=y
+CONFIG_MTD_NAND_CORE=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_MTK_BMT=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=13
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SRCU_NMI_SAFE=y
+CONFIG_NET_EGRESS=y
+CONFIG_NET_FLOW_LIMIT=y
+CONFIG_NET_INGRESS=y
+CONFIG_NET_XGRESS=y
+CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y
+CONFIG_NR_CPUS=4
+CONFIG_NVMEM=y
+CONFIG_NVMEM_LAYOUTS=y
+CONFIG_NVMEM_SYSFS=y
+CONFIG_OF=y
+CONFIG_OF_ADDRESS=y
+CONFIG_OF_EARLY_FLATTREE=y
+CONFIG_OF_FLATTREE=y
+CONFIG_OF_GPIO=y
+CONFIG_OF_IRQ=y
+CONFIG_OF_KOBJ=y
+CONFIG_PADATA=y
+CONFIG_PAGE_POOL=y
+CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
+CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
+CONFIG_PCI_DRIVERS_LEGACY=y
+CONFIG_PERF_USE_VMALLOC=y
+CONFIG_PGTABLE_LEVELS=2
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_RANDSTRUCT_NONE=y
+CONFIG_RATIONAL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RPS=y
+# CONFIG_SCHED_CORE is not set
+CONFIG_SCHED_SMT=y
+CONFIG_SERIAL_8250_AIROHA=y
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SGL_ALLOC=y
+CONFIG_SMP=y
+CONFIG_SMP_UP=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+# CONFIG_SOC_ECONET_EN751221 is not set
+CONFIG_SOC_ECONET_EN7528=y
+CONFIG_SPI=y
+# CONFIG_SPI_AIROHA_EN7523 is not set
+CONFIG_SPI_AIROHA_SNFI=y
+CONFIG_SPI_MASTER=y
+CONFIG_SPI_MEM=y
+CONFIG_SPLIT_PTE_PTLOCKS=y
+CONFIG_SYNC_R4K=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+CONFIG_SYS_HAS_CPU_MIPS32_R1=y
+CONFIG_SYS_HAS_CPU_MIPS32_R2=y
+CONFIG_SYS_HAS_EARLY_PRINTK=y
+CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
+CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
+CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
+CONFIG_SYS_SUPPORTS_HIGHMEM=y
+CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y
+CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y
+CONFIG_SYS_SUPPORTS_MIPS16=y
+CONFIG_SYS_SUPPORTS_MIPS_CPS=y
+CONFIG_SYS_SUPPORTS_MULTITHREADING=y
+CONFIG_SYS_SUPPORTS_SCHED_SMT=y
+CONFIG_SYS_SUPPORTS_SMP=y
+CONFIG_SYS_SUPPORTS_ZBOOT=y
+CONFIG_SYS_SUPPORTS_ZBOOT_UART16550=y
+CONFIG_TARGET_ISA_REV=2
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_UBIFS_FS=y
+CONFIG_USE_GENERIC_EARLY_PRINTK_8250=y
+CONFIG_USE_OF=y
+CONFIG_WEAK_ORDERING=y
+CONFIG_XPS=y
+CONFIG_XXHASH=y
+CONFIG_ZBOOT_LOAD_ADDRESS=0x80020000
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZSTD_COMMON=y
+CONFIG_ZSTD_COMPRESS=y
+CONFIG_ZSTD_DECOMPRESS=y
diff --git a/target/linux/econet/en7528/profiles/00-default.mk b/target/linux/econet/en7528/profiles/00-default.mk
new file mode 100644 (file)
index 0000000..8388859
--- /dev/null
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Copyright (C) 2025 OpenWrt.org
+
+define Profile/Default
+       NAME:=Default Profile
+endef
+
+define Profile/Default/Description
+       Default package set compatible with most EN7528 boards.
+endef
+$(eval $(call Profile,Default))
diff --git a/target/linux/econet/en7528/target.mk b/target/linux/econet/en7528/target.mk
new file mode 100644 (file)
index 0000000..1f174f7
--- /dev/null
@@ -0,0 +1,11 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+ARCH:=mipsel
+SUBTARGET:=en7528
+BOARDNAME:=EN7528 based boards
+CPU_TYPE:=24kc
+KERNELNAME:=vmlinuz.bin
+
+define Target/Description
+       Build firmware images for EcoNet EN7528 based boards.
+endef
diff --git a/target/linux/econet/image/en7528.mk b/target/linux/econet/image/en7528.mk
new file mode 100644 (file)
index 0000000..1bd8cb5
--- /dev/null
@@ -0,0 +1,6 @@
+define Device/en7528_generic
+  DEVICE_VENDOR := EN7528
+  DEVICE_MODEL := Generic
+  DEVICE_DTS := en7528_generic
+endef
+TARGET_DEVICES += en7528_generic
diff --git a/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch b/target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch
new file mode 100644 (file)
index 0000000..f11c6d3
--- /dev/null
@@ -0,0 +1,119 @@
+From: Ahmed Naseef <naseefkm@gmail.com>
+Subject: mips: econet: add EN7528 SoC support
+
+The EN7528 is a little endian dual-core MIPS 1004Kc SoC used in xPON
+devices. Unlike the big endian EN751221, EN7528 uses the MIPS GIC
+interrupt controller for SMP.
+
+This adds boot support for the EN7528 SoC family:
+- New SOC_ECONET_EN7528 Kconfig option
+- Little endian support for ECONET platform
+- UART base address adjustment for endianness
+- CPS SMP ops registration for multi-core support
+
+Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
+--- a/arch/mips/Kconfig
++++ b/arch/mips/Kconfig
+@@ -391,13 +391,13 @@ config MACH_DECSTATION
+ config ECONET
+       bool "EcoNet MIPS family"
+       select BOOT_RAW
+-      select CPU_BIG_ENDIAN
+       select DEBUG_ZBOOT if DEBUG_KERNEL
+       select EARLY_PRINTK_8250
+       select ECONET_EN751221_TIMER
+       select SERIAL_8250
+       select SERIAL_OF_PLATFORM
+       select SYS_SUPPORTS_BIG_ENDIAN
++      select SYS_SUPPORTS_LITTLE_ENDIAN
+       select SYS_HAS_CPU_MIPS32_R1
+       select SYS_HAS_CPU_MIPS32_R2
+       select SYS_HAS_EARLY_PRINTK
+--- a/arch/mips/econet/Kconfig
++++ b/arch/mips/econet/Kconfig
+@@ -12,6 +12,7 @@ choice
+       config SOC_ECONET_EN751221
+               bool "EN751221 family"
+               select COMMON_CLK
++              select CPU_BIG_ENDIAN
+               select ECONET_EN751221_INTC
+               select IRQ_MIPS_CPU
+               select SMP
+@@ -22,6 +23,23 @@ choice
+                 They are based on single core MIPS 34Kc processors. To boot
+                 this kernel, you will need a device tree such as
+                 MIPS_RAW_APPENDED_DTB=y, and a root filesystem.
++
++      config SOC_ECONET_EN7528
++              bool "EN7528 family"
++              select COMMON_CLK
++              select CPU_LITTLE_ENDIAN
++              select IRQ_MIPS_CPU
++              select MIPS_CPU_SCACHE
++              select MIPS_GIC
++              select SMP
++              select SMP_UP
++              select SYS_SUPPORTS_HIGHMEM
++              select SYS_SUPPORTS_MIPS_CPS
++              select SYS_SUPPORTS_MULTITHREADING
++              select SYS_SUPPORTS_SMP
++              help
++                The EN7528 family with dual-core MIPS 1004Kc.
++                Requires MIPS_RAW_APPENDED_DTB=y for boot.
+ endchoice
+ choice
+--- a/arch/mips/econet/init.c
++++ b/arch/mips/econet/init.c
+@@ -16,11 +16,16 @@
+ #include <asm/prom.h>
+ #include <asm/smp-ops.h>
+ #include <asm/reboot.h>
++#include <asm/mips-cps.h>
+ #define CR_AHB_RSTCR          ((void __iomem *)CKSEG1ADDR(0x1fb00040))
+ #define RESET                 BIT(31)
+-#define UART_BASE             CKSEG1ADDR(0x1fbf0003)
++#ifdef CONFIG_CPU_LITTLE_ENDIAN
++#define UART_BASE             CKSEG1ADDR(0x1fbf0000)  /* LE: byte at offset 0 */
++#else
++#define UART_BASE             CKSEG1ADDR(0x1fbf0003)  /* BE: byte at offset 3 */
++#endif
+ #define UART_REG_SHIFT                2
+ static void hw_reset(char *command)
+@@ -51,11 +56,18 @@ void __init plat_mem_setup(void)
+       early_init_dt_scan_memory();
+ }
+-/* 3. Overload __weak device_tree_init(), add SMP_UP ops */
++/* 3. Overload __weak device_tree_init(), register SMP ops */
+ void __init device_tree_init(void)
+ {
+       unflatten_and_copy_device_tree();
++      /* EN7528 dual-core: probe CM/CPC and register CPS SMP ops */
++      mips_cm_probe();
++      mips_cpc_probe();
++
++      if (!register_cps_smp_ops())
++              return;
++
+       register_up_smp_ops();
+ }
+--- a/arch/mips/boot/compressed/uart-16550.c
++++ b/arch/mips/boot/compressed/uart-16550.c
+@@ -21,7 +21,11 @@
+ #endif
+ #ifdef CONFIG_ECONET
++#ifdef CONFIG_CPU_LITTLE_ENDIAN
++#define EN75_UART_BASE        0x1fbf0000
++#else
+ #define EN75_UART_BASE        0x1fbf0003
++#endif
+ #define PORT(offset)  (CKSEG1ADDR(EN75_UART_BASE) + (4 * (offset)))
+ #endif
diff --git a/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch b/target/linux/econet/patches-6.12/101-econet-timer-add-en7528-support.patch
new file mode 100644 (file)
index 0000000..3d86414
--- /dev/null
@@ -0,0 +1,264 @@
+From: Ahmed Naseef <naseefkm@gmail.com>
+Subject: mips: econet: timer: add EN7528 support to EN751221 timer driver
+
+Extend the existing EN751221 timer driver to support EN7528/EN751627 SoCs.
+The driver now auto-detects the IRQ mode based on device tree:
+- EN751221: Single percpu IRQ (legacy interrupt controller)
+- EN7528/EN751627: Separate IRQ per CPU (GIC shared interrupts)
+
+Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
+--- a/drivers/clocksource/Kconfig
++++ b/drivers/clocksource/Kconfig
+@@ -79,7 +79,10 @@ config ECONET_EN751221_TIMER
+       select CLKSRC_MMIO
+       select TIMER_OF
+       help
+-        Support for CPU timer found on EcoNet MIPS based SoCs.
++        Support for CPU timer found on EcoNet EN75xx MIPS based SoCs
++        (EN751221, EN751627, EN7528). The driver supports both GIC-based
++        (separate IRQ per CPU) and legacy interrupt controller (percpu IRQ)
++        modes.
+ config FTTMR010_TIMER
+       bool "Faraday Technology timer driver" if COMPILE_TEST
+--- a/drivers/clocksource/timer-econet-en751221.c
++++ b/drivers/clocksource/timer-econet-en751221.c
+@@ -2,12 +2,20 @@
+ /*
+  * Timer present on EcoNet EN75xx MIPS based SoCs.
+  *
++ * This driver supports both:
++ * - EN751221: Single percpu IRQ mode (legacy interrupt controller)
++ * - EN7528/EN751627: Separate IRQ per CPU mode (GIC shared interrupts)
++ *
++ * The mode is auto-detected based on IRQ count in device tree.
++ *
+  * Copyright (C) 2025 by Caleb James DeLisle <cjd@cjdns.fr>
++ * Copyright (C) 2025 by Ahmed Naseef <naseefkm@gmail.com>
+  */
+ #include <linux/io.h>
+ #include <linux/cpumask.h>
+ #include <linux/interrupt.h>
++#include <linux/irq.h>
+ #include <linux/clockchips.h>
+ #include <linux/sched_clock.h>
+ #include <linux/of.h>
+@@ -21,10 +29,14 @@
+ #define ECONET_MAX_DELTA              GENMASK(ECONET_BITS - 2, 0)
+ /* 34Kc hardware has 1 block and 1004Kc has 2. */
+ #define ECONET_NUM_BLOCKS             DIV_ROUND_UP(NR_CPUS, 2)
++#define ECONET_MAX_IRQS                       4
+ static struct {
+       void __iomem    *membase[ECONET_NUM_BLOCKS];
+       u32             freq_hz;
++      int             irqs[ECONET_MAX_IRQS];
++      int             num_irqs;
++      bool            use_percpu_irq;
+ } econet_timer __ro_after_init;
+ static DEFINE_PER_CPU(struct clock_event_device, econet_timer_pcpu);
+@@ -98,12 +110,21 @@ static int cevt_init_cpu(uint cpu)
+       struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, cpu);
+       u32 reg;
++      if (!econet_timer.use_percpu_irq && cpu >= econet_timer.num_irqs)
++              return -EINVAL;
++
+       pr_debug("%s: Setting up clockevent for CPU %d\n", cd->name, cpu);
+       reg = ioread32(reg_ctl(cpu)) | ctl_bit_enabled(cpu);
+       iowrite32(reg, reg_ctl(cpu));
+-      enable_percpu_irq(cd->irq, IRQ_TYPE_NONE);
++      if (econet_timer.use_percpu_irq) {
++              enable_percpu_irq(cd->irq, IRQ_TYPE_NONE);
++      } else {
++              if (irq_force_affinity(econet_timer.irqs[cpu], cpumask_of(cpu)))
++                      pr_warn("%s: failed to set IRQ %d affinity to CPU %d\n",
++                              cd->name, econet_timer.irqs[cpu], cpu);
++      }
+       /* Do this last because it synchronously configures the timer */
+       clockevents_config_and_register(cd, econet_timer.freq_hz,
+@@ -126,7 +147,21 @@ static void __init cevt_dev_init(uint cp
+       iowrite32(U32_MAX, reg_compare(cpu));
+ }
+-static int __init cevt_init(struct device_node *np)
++static void __init cevt_setup_clockevent(struct clock_event_device *cd,
++                                       struct device_node *np,
++                                       int irq, int cpu)
++{
++      cd->rating              = 310;
++      cd->features            = CLOCK_EVT_FEAT_ONESHOT |
++                                CLOCK_EVT_FEAT_C3STOP |
++                                CLOCK_EVT_FEAT_PERCPU;
++      cd->set_next_event      = cevt_set_next_event;
++      cd->irq                 = irq;
++      cd->cpumask             = cpumask_of(cpu);
++      cd->name                = np->name;
++}
++
++static int __init cevt_init_percpu(struct device_node *np)
+ {
+       int i, irq, ret;
+@@ -137,42 +172,85 @@ static int __init cevt_init(struct devic
+       }
+       ret = request_percpu_irq(irq, cevt_interrupt, np->name, &econet_timer_pcpu);
+-
+       if (ret < 0) {
+               pr_err("%pOFn: IRQ %d setup failed (%d)\n", np, irq, ret);
+-              goto err_unmap_irq;
++              irq_dispose_mapping(irq);
++              return ret;
+       }
+       for_each_possible_cpu(i) {
+               struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i);
+-              cd->rating              = 310,
+-              cd->features            = CLOCK_EVT_FEAT_ONESHOT |
+-                                        CLOCK_EVT_FEAT_C3STOP |
+-                                        CLOCK_EVT_FEAT_PERCPU;
+-              cd->set_next_event      = cevt_set_next_event;
+-              cd->irq                 = irq;
+-              cd->cpumask             = cpumask_of(i);
+-              cd->name                = np->name;
++              cevt_setup_clockevent(cd, np, irq, i);
++              cevt_dev_init(i);
++      }
++
++      return 0;
++}
++
++static int __init cevt_init_separate(struct device_node *np)
++{
++      int i, ret;
++
++      for (i = 0; i < econet_timer.num_irqs; i++) {
++              struct clock_event_device *cd = &per_cpu(econet_timer_pcpu, i);
++
++              econet_timer.irqs[i] = irq_of_parse_and_map(np, i);
++              if (econet_timer.irqs[i] <= 0) {
++                      pr_err("%pOFn: irq_of_parse_and_map failed", np);
++                      ret = -EINVAL;
++                      goto err_free_irqs;
++              }
++
++              ret = request_irq(econet_timer.irqs[i], cevt_interrupt,
++                                IRQF_TIMER | IRQF_NOBALANCING,
++                                np->name, NULL);
++              if (ret < 0) {
++                      pr_err("%pOFn: IRQ %d setup failed (%d)\n", np,
++                             econet_timer.irqs[i], ret);
++                      irq_dispose_mapping(econet_timer.irqs[i]);
++                      goto err_free_irqs;
++              }
++              cevt_setup_clockevent(cd, np, econet_timer.irqs[i], i);
+               cevt_dev_init(i);
+       }
+-      cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
+-                        "clockevents/econet/timer:starting",
+-                        cevt_init_cpu, NULL);
+       return 0;
+-err_unmap_irq:
+-      irq_dispose_mapping(irq);
++err_free_irqs:
++      while (--i >= 0) {
++              free_irq(econet_timer.irqs[i], NULL);
++              irq_dispose_mapping(econet_timer.irqs[i]);
++      }
+       return ret;
+ }
++static int __init cevt_init(struct device_node *np)
++{
++      econet_timer.num_irqs = of_irq_count(np);
++      if (econet_timer.num_irqs <= 0 || econet_timer.num_irqs > ECONET_MAX_IRQS) {
++              pr_err("%pOFn: invalid IRQ count %d\n", np, econet_timer.num_irqs);
++              return -EINVAL;
++      }
++
++      /* Auto-detect mode based on IRQ count:
++       * 1 IRQ = percpu mode (EN751221)
++       * N IRQs = separate IRQ per CPU (EN7528/EN751627)
++       */
++      econet_timer.use_percpu_irq = (econet_timer.num_irqs == 1);
++
++      if (econet_timer.use_percpu_irq)
++              return cevt_init_percpu(np);
++      else
++              return cevt_init_separate(np);
++}
++
+ static int __init timer_init(struct device_node *np)
+ {
+       int num_blocks = DIV_ROUND_UP(num_possible_cpus(), 2);
+       struct clk *clk;
+-      int ret;
++      int ret, i;
+       clk = of_clk_get(np, 0);
+       if (IS_ERR(clk)) {
+@@ -182,11 +260,12 @@ static int __init timer_init(struct devi
+       econet_timer.freq_hz = clk_get_rate(clk);
+-      for (int i = 0; i < num_blocks; i++) {
++      for (i = 0; i < num_blocks; i++) {
+               econet_timer.membase[i] = of_iomap(np, i);
+               if (!econet_timer.membase[i]) {
+                       pr_err("%pOFn: failed to map register [%d]\n", np, i);
+-                      return -ENXIO;
++                      ret = -ENXIO;
++                      goto err_unmap;
+               }
+       }
+@@ -196,21 +275,34 @@ static int __init timer_init(struct devi
+                                   clocksource_mmio_readl_up);
+       if (ret) {
+               pr_err("%pOFn: clocksource_mmio_init failed: %d", np, ret);
+-              return ret;
++              goto err_unmap;
+       }
+       ret = cevt_init(np);
+       if (ret < 0)
+-              return ret;
++              goto err_unmap;
++
++      cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
++                        "clockevents/econet/timer:starting",
++                        cevt_init_cpu, NULL);
+       sched_clock_register(sched_clock_read, ECONET_BITS,
+                            econet_timer.freq_hz);
+-      pr_info("%pOFn: using %u.%03u MHz high precision timer\n", np,
++      pr_info("%pOFn: using %u.%03u MHz high precision timer (%s mode)\n", np,
+               econet_timer.freq_hz / 1000000,
+-              (econet_timer.freq_hz / 1000) % 1000);
++              (econet_timer.freq_hz / 1000) % 1000,
++              econet_timer.use_percpu_irq ? "percpu" : "separate IRQ");
+       return 0;
++
++err_unmap:
++      for (i = 0; i < num_blocks; i++) {
++              if (econet_timer.membase[i])
++                      iounmap(econet_timer.membase[i]);
++      }
++      return ret;
+ }
+-TIMER_OF_DECLARE(econet_timer_hpt, "econet,en751221-timer", timer_init);
++TIMER_OF_DECLARE(econet_en751221_timer, "econet,en751221-timer", timer_init);
++TIMER_OF_DECLARE(econet_en7528_timer, "econet,en7528-timer", timer_init);
diff --git a/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch b/target/linux/econet/patches-6.12/303-spi-airoha-snfi-enable-for-econet.patch
new file mode 100644 (file)
index 0000000..8556633
--- /dev/null
@@ -0,0 +1,21 @@
+spi: airoha-snfi: enable for EcoNet EN7528
+
+Enable the Airoha SNFI (SPI NAND Flash Interface) driver for EcoNet
+EN7528 SoC. The EN7528 shares the same SPI controller and NFI DMA
+engine as the Airoha EN7523/EN7581, with identical register layouts.
+
+Using the DMA-capable SNFI driver provides significantly better
+performance compared to the manual mode spi-en7523 driver.
+
+Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
+--- a/drivers/spi/Kconfig
++++ b/drivers/spi/Kconfig
+@@ -59,7 +59,7 @@ comment "SPI Master Controller Drivers"
+ config SPI_AIROHA_SNFI
+       tristate "Airoha SPI NAND Flash Interface"
+-      depends on ARCH_AIROHA || COMPILE_TEST
++      depends on ARCH_AIROHA || ECONET || COMPILE_TEST
+       depends on SPI_MASTER
+       select REGMAP_MMIO
+       help
index 15deffaa0cbb6284f35121899ce2198736dd972b..39ed0c43f54567f1f9cdbd4c46623457608b116f 100644 (file)
@@ -1,13 +1,13 @@
 --- a/arch/mips/Kconfig
 +++ b/arch/mips/Kconfig
-@@ -392,6 +392,7 @@ config ECONET
+@@ -391,6 +391,7 @@ config MACH_DECSTATION
+ config ECONET
        bool "EcoNet MIPS family"
        select BOOT_RAW
-       select CPU_BIG_ENDIAN
 +      select DMA_NONCOHERENT
        select DEBUG_ZBOOT if DEBUG_KERNEL
        select EARLY_PRINTK_8250
-       select ECONET_EN751221_TIMER
+       select SERIAL_8250
 --- a/drivers/usb/host/Kconfig
 +++ b/drivers/usb/host/Kconfig
 @@ -71,7 +71,7 @@ config USB_XHCI_HISTB
diff --git a/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch b/target/linux/econet/patches-6.12/886-uart-add-en7523-support.patch
new file mode 100644 (file)
index 0000000..cad2a71
--- /dev/null
@@ -0,0 +1,206 @@
+--- /dev/null
++++ b/drivers/tty/serial/8250/8250_en7523.c
+@@ -0,0 +1,94 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Airoha EN7523 driver.
++ *
++ * Copyright (c) 2022 Genexis Sweden AB
++ * Author: Benjamin Larsson <benjamin.larsson@genexis.eu>
++ */
++#include <linux/clk.h>
++#include <linux/io.h>
++#include <linux/module.h>
++#include <linux/of_irq.h>
++#include <linux/of_platform.h>
++#include <linux/pinctrl/consumer.h>
++#include <linux/platform_device.h>
++#include <linux/pm_runtime.h>
++#include <linux/serial_8250.h>
++#include <linux/serial_reg.h>
++#include <linux/console.h>
++#include <linux/dma-mapping.h>
++#include <linux/tty.h>
++#include <linux/tty_flip.h>
++
++#include "8250.h"
++
++
++/* The Airoha UART is 16550-compatible except for the baud rate calculation.
++ *
++ * crystal_clock = 20 MHz
++ * xindiv_clock = crystal_clock / clock_div
++ * (x/y) = XYD, 32 bit register with 16 bits of x and and then 16 bits of y
++ * clock_div = XINCLK_DIVCNT (default set to 10 (0x4)),
++ *           - 3 bit register [ 1, 2, 4, 8, 10, 12, 16, 20 ]
++ *
++ * baud_rate = ((xindiv_clock) * (x/y)) / ([BRDH,BRDL] * 16)
++ *
++ * XYD_y seems to need to be larger then XYD_x for things to work.
++ * Setting [BRDH,BRDL] to [0,1] and XYD_y to 65000 give even values
++ * for usual baud rates.
++ *
++ * Selecting divider needs to fulfill
++ * 1.8432 MHz <= xindiv_clk <= APB clock / 2
++ * The clocks are unknown but a divider of value 1 did not work.
++ *
++ * Optimally the XYD, BRD and XINCLK_DIVCNT registers could be searched to
++ * find values that gives the least error for every baud rate. But searching
++ * the space takes time and in practise only a few rates are of interest.
++ * With some value combinations not working a tested subset is used giving
++ * a usable range from 110 to 460800 baud.
++ */
++
++#define CLOCK_DIV_TAB_ELEMS 3
++#define XYD_Y 65000
++#define XINDIV_CLOCK 20000000
++#define UART_BRDL_20M 0x01
++#define UART_BRDH_20M 0x00
++
++static int clock_div_tab[] = { 10, 4, 2};
++static int clock_div_reg[] = {  4, 2, 1};
++
++
++int en7523_set_uart_baud_rate (struct uart_port *port, unsigned int baud)
++{
++      struct uart_8250_port *up = up_to_u8250p(port);
++      unsigned int xyd_x, nom, denom;
++      int i;
++
++      /* set DLAB to access the baud rate divider registers (BRDH, BRDL) */
++      serial_port_out(port, UART_LCR, up->lcr | UART_LCR_DLAB);
++
++      /* set baud rate calculation defaults */
++
++      /* set BRDIV ([BRDH,BRDL]) to 1 */
++      serial_port_out(port, UART_BRDL, UART_BRDL_20M);
++      serial_port_out(port, UART_BRDH, UART_BRDH_20M);
++
++      /* calculate XYD_x and XINCLKDR register */
++
++      for (i = 0 ; i < CLOCK_DIV_TAB_ELEMS ; i++) {
++              denom = (XINDIV_CLOCK/40) / clock_div_tab[i];
++              nom = (baud * (XYD_Y/40));
++              xyd_x = ((nom/denom) << 4);
++              if (xyd_x < XYD_Y) break;
++      }
++
++      serial_port_out(port, UART_XINCLKDR, clock_div_reg[i]);
++      serial_port_out(port, UART_XYD, (xyd_x<<16) | XYD_Y);
++
++      /* unset DLAB */
++      serial_port_out(port, UART_LCR, up->lcr);
++
++      return 0;
++}
++
++EXPORT_SYMBOL_GPL(en7523_set_uart_baud_rate);
+--- a/drivers/tty/serial/8250/8250_of.c
++++ b/drivers/tty/serial/8250/8250_of.c
+@@ -341,6 +341,7 @@ static const struct of_device_id of_plat
+       { .compatible = "ti,da830-uart", .data = (void *)PORT_DA830, },
+       { .compatible = "nuvoton,wpcm450-uart", .data = (void *)PORT_NPCM, },
+       { .compatible = "nuvoton,npcm750-uart", .data = (void *)PORT_NPCM, },
++      { .compatible = "airoha,en7523-uart", .data = (void *)PORT_AIROHA, },
+       { /* end of list */ },
+ };
+ MODULE_DEVICE_TABLE(of, of_platform_serial_table);
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -319,6 +319,14 @@ static const struct serial8250_config ua
+               .rxtrig_bytes   = {1, 8, 16, 30},
+               .flags          = UART_CAP_FIFO | UART_CAP_AFE,
+       },
++      [PORT_AIROHA] = {
++              .name           = "Airoha 16550",
++              .fifo_size      = 8,
++              .tx_loadsz      = 1,
++              .fcr            = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_01,
++              .rxtrig_bytes   = {1, 4},
++              .flags          = UART_CAP_FIFO,
++      },
+ };
+ /* Uart divisor latch read */
+@@ -2835,6 +2843,12 @@ serial8250_do_set_termios(struct uart_po
+       serial8250_set_divisor(port, baud, quot, frac);
++#ifdef CONFIG_SERIAL_8250_AIROHA
++      /* Airoha SoCs have custom registers for baud rate settings */
++      if (port->type == PORT_AIROHA)
++              en7523_set_uart_baud_rate(port, baud);
++#endif
++
+       /*
+        * LCR DLAB must be set to enable 64-byte FIFO mode. If the FCR
+        * is written without DLAB set, this mode will be disabled.
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -355,6 +355,16 @@ config SERIAL_8250_ACORN
+         system, say Y to this option.  The driver can handle 1, 2, or 3 port
+         cards.  If unsure, say N.
++config SERIAL_8250_AIROHA
++      tristate "Airoha UART support"
++      depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250
++      help
++        Selecting this option enables an Airoha SoC specific baud rate
++        calculation routine on an otherwise 16550 compatible UART hardware.
++
++        If you have an Airoha based board and want to use the serial port,
++        say Y to this option. If unsure, say N.
++
+ config SERIAL_8250_BCM2835AUX
+       tristate "BCM2835 auxiliar mini UART support"
+       depends on ARCH_BCM2835 || COMPILE_TEST
+--- a/drivers/tty/serial/8250/Makefile
++++ b/drivers/tty/serial/8250/Makefile
+@@ -20,6 +20,7 @@ obj-$(CONFIG_SERIAL_8250_CONSOLE)    += 825
+ obj-$(CONFIG_SERIAL_8250_ACCENT)      += 8250_accent.o
+ obj-$(CONFIG_SERIAL_8250_ACORN)               += 8250_acorn.o
++obj-$(CONFIG_SERIAL_8250_AIROHA)      += 8250_en7523.o
+ obj-$(CONFIG_SERIAL_8250_ASPEED_VUART)        += 8250_aspeed_vuart.o
+ obj-$(CONFIG_SERIAL_8250_BCM2835AUX)  += 8250_bcm2835aux.o
+ obj-$(CONFIG_SERIAL_8250_BCM7271)     += 8250_bcm7271.o
+--- a/include/uapi/linux/serial_reg.h
++++ b/include/uapi/linux/serial_reg.h
+@@ -383,5 +383,17 @@
+ #define UART_ALTR_EN_TXFIFO_LW        0x01    /* Enable the TX FIFO Low Watermark */
+ #define UART_ALTR_TX_LOW      0x41    /* Tx FIFO Low Watermark */
++/*
++ * These are definitions for the Airoha EN75XX uart registers
++ * Normalized because of 32 bits registers.
++ */
++#define UART_BRDL             0
++#define UART_BRDH             1
++#define UART_XINCLKDR         10
++#define UART_XYD              11
++#define UART_TXLVLCNT         12
++#define UART_RXLVLCNT         13
++#define UART_FINTLVL          14
++
+ #endif /* _LINUX_SERIAL_REG_H */
+--- a/include/uapi/linux/serial_core.h
++++ b/include/uapi/linux/serial_core.h
+@@ -31,6 +31,7 @@
+ #define PORT_ALTR_16550_F128 28 /* Altera 16550 UART with 128 FIFOs */
+ #define PORT_RT2880   29      /* Ralink RT2880 internal UART */
+ #define PORT_16550A_FSL64 30  /* Freescale 16550 UART with 64 FIFOs */
++#define PORT_AIROHA    31     /* Airoha 16550 UART */
+ /*
+  * ARM specific type numbers.  These are not currently guaranteed
+--- a/include/linux/serial_8250.h
++++ b/include/linux/serial_8250.h
+@@ -195,6 +195,7 @@ void serial8250_do_set_mctrl(struct uart
+ void serial8250_do_set_divisor(struct uart_port *port, unsigned int baud,
+                              unsigned int quot);
+ int fsl8250_handle_irq(struct uart_port *port);
++int en7523_set_uart_baud_rate(struct uart_port *port, unsigned int baud);
+ int serial8250_handle_irq(struct uart_port *port, unsigned int iir);
+ u16 serial8250_rx_chars(struct uart_8250_port *up, u16 lsr);
+ void serial8250_read_char(struct uart_8250_port *up, u16 lsr);
diff --git a/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch b/target/linux/econet/patches-6.12/887-uart-airoha-add-econet-support.patch
new file mode 100644 (file)
index 0000000..b25d02e
--- /dev/null
@@ -0,0 +1,18 @@
+serial: 8250: airoha: add EcoNet platform support
+
+The EcoNet EN75xx SoCs use the same UART IP core as the Airoha
+AN7523 SoCs. Add ECONET to the Kconfig dependency to enable
+the Airoha UART driver for EcoNet platforms.
+
+Signed-off-by: Ahmed Naseef <naseefkm@gmail.com>
+--- a/drivers/tty/serial/8250/Kconfig
++++ b/drivers/tty/serial/8250/Kconfig
+@@ -357,7 +357,7 @@ config SERIAL_8250_ACORN
+ config SERIAL_8250_AIROHA
+       tristate "Airoha UART support"
+-      depends on (ARCH_AIROHA || COMPILE_TEST) && OF && SERIAL_8250
++      depends on (ARCH_AIROHA || ECONET || COMPILE_TEST) && OF && SERIAL_8250
+       help
+         Selecting this option enables an Airoha SoC specific baud rate
+         calculation routine on an otherwise 16550 compatible UART hardware.