mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-02-19 15:51:15 +01:00
econet: add EN7528 subtarget 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 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>
This commit is contained in:
parent
862b46dd8f
commit
fab098cb61
15 changed files with 1041 additions and 5 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
103
target/linux/econet/dts/en7528.dtsi
Normal file
103
target/linux/econet/dts/en7528.dtsi
Normal file
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
57
target/linux/econet/dts/en7528_generic.dts
Normal file
57
target/linux/econet/dts/en7528_generic.dts
Normal file
|
|
@ -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>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
ARCH:=mips
|
||||
BOARDNAME:=en751221
|
||||
CPU_TYPE:=24kc
|
||||
KERNELNAME:=vmlinuz.bin
|
||||
|
|
|
|||
216
target/linux/econet/en7528/config-6.12
Normal file
216
target/linux/econet/en7528/config-6.12
Normal file
|
|
@ -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
|
||||
12
target/linux/econet/en7528/profiles/00-default.mk
Normal file
12
target/linux/econet/en7528/profiles/00-default.mk
Normal file
|
|
@ -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))
|
||||
11
target/linux/econet/en7528/target.mk
Normal file
11
target/linux/econet/en7528/target.mk
Normal file
|
|
@ -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
|
||||
6
target/linux/econet/image/en7528.mk
Normal file
6
target/linux/econet/image/en7528.mk
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
define Device/en7528_generic
|
||||
DEVICE_VENDOR := EN7528
|
||||
DEVICE_MODEL := Generic
|
||||
DEVICE_DTS := en7528_generic
|
||||
endef
|
||||
TARGET_DEVICES += en7528_generic
|
||||
119
target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch
Normal file
119
target/linux/econet/patches-6.12/100-econet-add-en7528-soc.patch
Normal file
|
|
@ -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
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
@ -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.
|
||||
Loading…
Add table
Reference in a new issue