]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
airoha: Introduce support for Airoha AN7583 SoC
authorChristian Marangi <ansuelsmth@gmail.com>
Fri, 26 Sep 2025 02:55:19 +0000 (04:55 +0200)
committerChristian Marangi <ansuelsmth@gmail.com>
Fri, 26 Sep 2025 03:00:07 +0000 (05:00 +0200)
Introduce initial support for Airoha AN7583 SoC and add all the required
patch for basic functionality of the SoC.

Airoha AN7583 is based on Airoha EN7581 SoC with some major changes on
the PHY handling and Serdes. It can be see as a lower spec of EN7581
with modern and simplified implementations.

All the patch are sent upstream and are pending revision. Support for
PCIe and USB will come later as soon as DT structure is accepted
upstream.

Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
31 files changed:
target/linux/airoha/Makefile
target/linux/airoha/an7581/config-6.12
target/linux/airoha/an7583/base-files/etc/board.d/02_network [new file with mode: 0644]
target/linux/airoha/an7583/config-6.12 [new file with mode: 0644]
target/linux/airoha/an7583/target.mk [new file with mode: 0644]
target/linux/airoha/dts/an7583-evb.dts [new file with mode: 0644]
target/linux/airoha/dts/an7583.dtsi [new file with mode: 0644]
target/linux/airoha/image/an7583.mk [new file with mode: 0644]
target/linux/airoha/patches-6.12/090-v6.17-net-mdio-Add-MDIO-bus-controller-for-Airoha-AN7583.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/120-02-pinctrl-mediatek-airoha-generalize-pins-group-functi.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/120-03-pinctrl-airoha-convert-PHY-LED-GPIO-to-macro.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/120-04-pinctrl-airoha-convert-PWM-GPIO-to-macro.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/120-05-pinctrl-airoha-add-support-for-Airoha-AN7583-PINs.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/401-02-net-dsa-mt7530-Add-AN7583-support.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/402-01-thermal-airoha-convert-to-regmap-API.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/402-02-thermal-drivers-airoha-Generalize-probe-function.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/402-03-thermal-drivers-airoha-generalize-get_thermal_ADC-an.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/403-cpufreq-airoha-Add-support-for-AN7583-SoC.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-02-clk-en7523-generalize-register-clocks-function.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-03-clk-en7523-convert-to-full-clk_hw-implementation.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-04-clk-en7523-add-support-for-.set_rate.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-05-clk-en7523-permit-to-reference-Chip-SCU-from-phandle.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-07-clk-en7523-reword-and-clean-clk_probe-variables.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-08-clk-en7523-add-support-for-probing-SCU-child.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-09-dt-bindings-clock-airoha-Document-support-for-AN7583.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/600-10-clk-en7523-add-support-for-Airoha-AN7583-clock.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/604-01-net-pcs-airoha-add-support-for-AN7583.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/605-net-pcs-airoha-add-support-for-optional-xfi-reset-li.patch [new file with mode: 0644]

index 7e64485ae19078732910d957a90eb254fec95de8..970a3398f975b3eb6f8cd95575c36da355b29eb2 100644 (file)
@@ -3,7 +3,7 @@ include $(TOPDIR)/rules.mk
 ARCH:=arm
 BOARD:=airoha
 BOARDNAME:=Airoha ARM
-SUBTARGETS:=en7523 an7581
+SUBTARGETS:=en7523 an7581 an7583
 FEATURES:=dt squashfs nand ramdisk gpio
 
 KERNEL_PATCHVER:=6.12
index 6899f3251af8813d5cbcbfb6d844a582eaef3987..e5b92811459f8127e117c3ae077439d8f56ccb10 100644 (file)
@@ -213,6 +213,7 @@ CONFIG_LZO_COMPRESS=y
 CONFIG_LZO_DECOMPRESS=y
 CONFIG_MDIO_BUS=y
 CONFIG_MDIO_DEVICE=y
+# CONFIG_MDIO_AIROHA is not set
 CONFIG_MDIO_DEVRES=y
 # CONFIG_MEDIATEK_GE_SOC_PHY is not set
 # CONFIG_MEMCG is not set
@@ -289,6 +290,7 @@ CONFIG_PCI_DOMAINS=y
 CONFIG_PCI_DOMAINS_GENERIC=y
 CONFIG_PCI_MSI=y
 CONFIG_PCS_AIROHA_AN7581=y
+# CONFIG_PCS_AIROHA_AN7583 is not set
 CONFIG_PERF_EVENTS=y
 CONFIG_PER_VMA_LOCK=y
 CONFIG_PGTABLE_LEVELS=3
diff --git a/target/linux/airoha/an7583/base-files/etc/board.d/02_network b/target/linux/airoha/an7583/base-files/etc/board.d/02_network
new file mode 100644 (file)
index 0000000..077d193
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# Copyright (c) 2015 The Linux Foundation. All rights reserved.
+# Copyright (c) 2011-2015 OpenWrt.org
+#
+
+. /lib/functions/uci-defaults.sh
+. /lib/functions/system.sh
+
+an7583_setup_interfaces()
+{
+       local board="$1"
+
+       case "$board" in
+       airoha,an7583-evb)
+               ucidef_set_interface_lan "lan1 lan2 lan3 lan4 eth1"
+               ;;
+       *)
+               echo "Unsupported hardware. Network interfaces not initialized"
+               ;;
+       esac
+}
+
+board_config_update
+board=$(board_name)
+an7583_setup_interfaces $board
+board_config_flush
+
+exit 0
diff --git a/target/linux/airoha/an7583/config-6.12 b/target/linux/airoha/an7583/config-6.12
new file mode 100644 (file)
index 0000000..b95bfa6
--- /dev/null
@@ -0,0 +1,402 @@
+CONFIG_64BIT=y
+CONFIG_AIROHA_CPU_PM_DOMAIN=y
+CONFIG_AIROHA_SCU_SSR=y
+CONFIG_AIROHA_THERMAL=y
+CONFIG_AIROHA_WATCHDOG=y
+CONFIG_AMPERE_ERRATUM_AC03_CPU_38=y
+CONFIG_ARCH_AIROHA=y
+CONFIG_ARCH_BINFMT_ELF_EXTRA_PHDRS=y
+CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE=y
+CONFIG_ARCH_DEFAULT_KEXEC_IMAGE_VERIFY_SIG=y
+CONFIG_ARCH_DMA_ADDR_T_64BIT=y
+CONFIG_ARCH_FORCE_MAX_ORDER=10
+CONFIG_ARCH_KEEP_MEMBLOCK=y
+CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
+CONFIG_ARCH_MMAP_RND_BITS=18
+CONFIG_ARCH_MMAP_RND_BITS_MAX=24
+CONFIG_ARCH_MMAP_RND_BITS_MIN=18
+CONFIG_ARCH_MMAP_RND_COMPAT_BITS_MIN=11
+CONFIG_ARCH_PROC_KCORE_TEXT=y
+CONFIG_ARCH_SPARSEMEM_ENABLE=y
+CONFIG_ARCH_STACKWALK=y
+CONFIG_ARCH_SUSPEND_POSSIBLE=y
+CONFIG_ARCH_WANTS_NO_INSTR=y
+CONFIG_ARCH_WANTS_THP_SWAP=y
+CONFIG_ARM64=y
+CONFIG_ARM64_4K_PAGES=y
+CONFIG_ARM64_ERRATUM_843419=y
+CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
+CONFIG_ARM64_PA_BITS=48
+CONFIG_ARM64_PA_BITS_48=y
+CONFIG_ARM64_PLATFORM_DEVICES=y
+CONFIG_ARM64_TAGGED_ADDR_ABI=y
+CONFIG_ARM64_VA_BITS=39
+CONFIG_ARM64_VA_BITS_39=y
+# CONFIG_ARM64_VA_BITS_48 is not set
+# CONFIG_ARM64_VA_BITS_52 is not set
+CONFIG_ARM_AIROHA_SOC_CPUFREQ=y
+CONFIG_ARM_AMBA=y
+CONFIG_ARM_ARCH_TIMER=y
+CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
+# CONFIG_ARM_DEBUG_WX is not set
+CONFIG_ARM_GIC=y
+CONFIG_ARM_GIC_V2M=y
+CONFIG_ARM_GIC_V3=y
+CONFIG_ARM_GIC_V3_ITS=y
+CONFIG_ARM_PMU=y
+CONFIG_ARM_PMUV3=y
+CONFIG_ARM_PSCI_FW=y
+CONFIG_ARM_SMCCC_SOC_ID=y
+# CONFIG_ARM_SMMU is not set
+# CONFIG_ARM_SMMU_V3 is not set
+CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
+CONFIG_BLK_MQ_PCI=y
+CONFIG_BLK_PM=y
+CONFIG_BUFFER_HEAD=y
+CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y
+CONFIG_CC_HAVE_SHADOW_CALL_STACK=y
+CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
+CONFIG_CLONE_BACKWARDS=y
+CONFIG_COMMON_CLK=y
+CONFIG_COMMON_CLK_EN7523=y
+CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
+# CONFIG_COMPAT_32BIT_TIME is not set
+# CONFIG_COMPRESSED_INSTALL is not set
+CONFIG_CONTEXT_TRACKING=y
+CONFIG_CONTEXT_TRACKING_IDLE=y
+CONFIG_CPUFREQ_DT=y
+CONFIG_CPUFREQ_DT_PLATDEV=y
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
+# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
+CONFIG_CPU_FREQ_GOV_ATTR_SET=y
+CONFIG_CPU_FREQ_GOV_COMMON=y
+CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
+CONFIG_CPU_FREQ_GOV_ONDEMAND=y
+CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
+CONFIG_CPU_FREQ_GOV_POWERSAVE=y
+CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_STAT=y
+CONFIG_CPU_LITTLE_ENDIAN=y
+CONFIG_CPU_RMAP=y
+CONFIG_CRC16=y
+CONFIG_CRC_CCITT=y
+CONFIG_CRYPTO_CRC32C=y
+CONFIG_CRYPTO_DEFLATE=y
+CONFIG_CRYPTO_DEV_EIP93=y
+CONFIG_CRYPTO_DRBG=y
+CONFIG_CRYPTO_DRBG_HMAC=y
+CONFIG_CRYPTO_DRBG_MENU=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_HASH_INFO=y
+CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_JITTERENTROPY=y
+CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64
+CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32
+CONFIG_CRYPTO_JITTERENTROPY_OSR=1
+CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
+CONFIG_CRYPTO_LIB_GF128MUL=y
+CONFIG_CRYPTO_LIB_SHA1=y
+CONFIG_CRYPTO_LIB_SHA256=y
+CONFIG_CRYPTO_LIB_UTILS=y
+CONFIG_CRYPTO_LZO=y
+CONFIG_CRYPTO_RNG=y
+CONFIG_CRYPTO_RNG2=y
+CONFIG_CRYPTO_RNG_DEFAULT=y
+CONFIG_CRYPTO_SHA256=y
+CONFIG_CRYPTO_SHA3=y
+CONFIG_CRYPTO_SHA512=y
+CONFIG_CRYPTO_ZSTD=y
+CONFIG_DCACHE_WORD_ACCESS=y
+CONFIG_DEBUG_MISC=y
+CONFIG_DMADEVICES=y
+CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y
+CONFIG_DMA_DIRECT_REMAP=y
+CONFIG_DMA_ENGINE=y
+CONFIG_DMA_NEED_SYNC=y
+CONFIG_DMA_OF=y
+CONFIG_DMA_OPS_HELPERS=y
+CONFIG_DTC=y
+CONFIG_EDAC_SUPPORT=y
+CONFIG_EXT4_FS=y
+CONFIG_FIXED_PHY=y
+CONFIG_FIX_EARLYCON_MEM=y
+CONFIG_FRAME_POINTER=y
+CONFIG_FS_IOMAP=y
+CONFIG_FS_MBCACHE=y
+CONFIG_FUNCTION_ALIGNMENT=4
+CONFIG_FUNCTION_ALIGNMENT_4B=y
+CONFIG_FWNODE_MDIO=y
+CONFIG_FW_CACHE=y
+# CONFIG_FW_LOADER_USER_HELPER is not set
+CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y
+CONFIG_GENERIC_ALLOCATOR=y
+CONFIG_GENERIC_ARCH_TOPOLOGY=y
+CONFIG_GENERIC_BUG=y
+CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
+CONFIG_GENERIC_CLOCKEVENTS=y
+CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
+CONFIG_GENERIC_CPU_AUTOPROBE=y
+CONFIG_GENERIC_CPU_DEVICES=y
+CONFIG_GENERIC_CPU_VULNERABILITIES=y
+CONFIG_GENERIC_CSUM=y
+CONFIG_GENERIC_EARLY_IOREMAP=y
+CONFIG_GENERIC_GETTIMEOFDAY=y
+CONFIG_GENERIC_IDLE_POLL_SETUP=y
+CONFIG_GENERIC_IOREMAP=y
+CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
+CONFIG_GENERIC_IRQ_SHOW=y
+CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
+CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
+CONFIG_GENERIC_MSI_IRQ=y
+CONFIG_GENERIC_PCI_IOMAP=y
+CONFIG_GENERIC_PHY=y
+CONFIG_GENERIC_PINCONF=y
+CONFIG_GENERIC_PINCTRL_GROUPS=y
+CONFIG_GENERIC_PINMUX_FUNCTIONS=y
+CONFIG_GENERIC_SCHED_CLOCK=y
+CONFIG_GENERIC_SMP_IDLE_THREAD=y
+CONFIG_GENERIC_STRNCPY_FROM_USER=y
+CONFIG_GENERIC_STRNLEN_USER=y
+CONFIG_GENERIC_TIME_VSYSCALL=y
+CONFIG_GLOB=y
+CONFIG_GPIOLIB_IRQCHIP=y
+CONFIG_GPIO_CDEV=y
+CONFIG_GPIO_EN7523=y
+CONFIG_GPIO_GENERIC=y
+CONFIG_GRO_CELLS=y
+CONFIG_HARDIRQS_SW_RESEND=y
+CONFIG_HAS_DMA=y
+CONFIG_HAS_IOMEM=y
+CONFIG_HAS_IOPORT=y
+CONFIG_HAS_IOPORT_MAP=y
+CONFIG_HOTPLUG_CORE_SYNC=y
+CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_AIROHA=y
+# CONFIG_HISILICON_ERRATUM_162100801 is not set
+# CONFIG_IDPF is not set
+CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
+CONFIG_INET_AH=y
+CONFIG_INET_ESP=y
+# CONFIG_INET_ESP_OFFLOAD is not set
+CONFIG_INET_IPCOMP=y
+CONFIG_INET_TUNNEL=y
+CONFIG_INET_XFRM_TUNNEL=y
+CONFIG_IO_URING=y
+CONFIG_IPC_NS=y
+CONFIG_IPV6=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_IPV6_SUBTREES is not set
+CONFIG_IP_MROUTE=y
+CONFIG_IP_MROUTE_COMMON=y
+# CONFIG_IP_MROUTE_MULTIPLE_TABLES is not set
+CONFIG_IP_PNP=y
+# CONFIG_IP_PNP_BOOTP is not set
+# CONFIG_IP_PNP_DHCP is not set
+# CONFIG_IP_PNP_RARP is not set
+# CONFIG_IP_ROUTE_MULTIPATH is not set
+# CONFIG_IP_ROUTE_VERBOSE is not set
+CONFIG_IRQCHIP=y
+CONFIG_IRQ_DOMAIN=y
+CONFIG_IRQ_DOMAIN_HIERARCHY=y
+CONFIG_IRQ_FORCED_THREADING=y
+CONFIG_IRQ_MSI_LIB=y
+CONFIG_IRQ_WORK=y
+CONFIG_JBD2=y
+CONFIG_LIBFDT=y
+CONFIG_LOCK_DEBUGGING_SUPPORT=y
+CONFIG_LOCK_SPIN_ON_OWNER=y
+CONFIG_LRU_GEN_WALKS_MMU=y
+CONFIG_LZO_COMPRESS=y
+CONFIG_LZO_DECOMPRESS=y
+CONFIG_MDIO_BUS=y
+CONFIG_MDIO_DEVICE=y
+CONFIG_MDIO_AIROHA=y
+CONFIG_MDIO_DEVRES=y
+# CONFIG_MEDIATEK_GE_SOC_PHY is not set
+# CONFIG_MEMCG is not set
+CONFIG_MFD_SYSCON=y
+CONFIG_MIGRATION=y
+CONFIG_MMC=y
+CONFIG_MMC_BLOCK=y
+CONFIG_MMC_CQHCI=y
+CONFIG_MMC_MTK=y
+CONFIG_MMU_LAZY_TLB_REFCOUNT=y
+CONFIG_MODULES_TREE_LOOKUP=y
+CONFIG_MODULES_USE_ELF_RELA=y
+CONFIG_MTD_NAND_CORE=y
+CONFIG_MTD_NAND_ECC=y
+CONFIG_MTD_NAND_MTK_BMT=y
+CONFIG_MTD_RAW_NAND=y
+CONFIG_MTD_SPI_NAND=y
+CONFIG_MTD_SPLIT_FIRMWARE=y
+CONFIG_MTD_SPLIT_FIT_FW=y
+CONFIG_MTD_UBI=y
+CONFIG_MTD_UBI_BEB_LIMIT=20
+CONFIG_MTD_UBI_BLOCK=y
+CONFIG_MTD_UBI_WL_THRESHOLD=4096
+CONFIG_MUTEX_SPIN_ON_OWNER=y
+CONFIG_NEED_DMA_MAP_STATE=y
+CONFIG_NEED_SG_DMA_LENGTH=y
+CONFIG_NET_AIROHA=y
+CONFIG_NET_AIROHA_FLOW_STATS=y
+CONFIG_NET_DEVLINK=y
+CONFIG_NET_DSA=y
+CONFIG_NET_DSA_MT7530=y
+CONFIG_NET_DSA_MT7530_MDIO=y
+CONFIG_NET_DSA_MT7530_MMIO=y
+CONFIG_NET_DSA_TAG_MTK=y
+CONFIG_NET_FLOW_LIMIT=y
+# CONFIG_NET_MEDIATEK_SOC is not set
+CONFIG_NET_SELFTESTS=y
+# CONFIG_NET_VENDOR_3COM is not set
+CONFIG_NET_VENDOR_AIROHA=y
+# CONFIG_NET_VENDOR_MEDIATEK is not set
+CONFIG_NLS=y
+CONFIG_NO_HZ_COMMON=y
+CONFIG_NO_HZ_IDLE=y
+CONFIG_NR_CPUS=4
+CONFIG_NVMEM=y
+CONFIG_NVMEM_BLOCK=y
+CONFIG_NVMEM_LAYOUTS=y
+CONFIG_NVMEM_LAYOUT_ASCII_ENV=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_OF_MDIO=y
+CONFIG_PAGE_POOL=y
+CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
+CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
+CONFIG_PARTITION_PERCPU=y
+CONFIG_PCI=y
+CONFIG_PCIEAER=y
+CONFIG_PCIEASPM=y
+# CONFIG_PCIEASPM_DEFAULT is not set
+CONFIG_PCIEASPM_PERFORMANCE=y
+# CONFIG_PCIEASPM_POWERSAVE is not set
+# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCIE_MEDIATEK=y
+CONFIG_PCIE_MEDIATEK_GEN3=y
+CONFIG_PCIE_PME=y
+CONFIG_PCI_DOMAINS=y
+CONFIG_PCI_DOMAINS_GENERIC=y
+CONFIG_PCI_MSI=y
+# CONFIG_PCS_AIROHA_AN7581 is not set
+CONFIG_PCS_AIROHA_AN7583=y
+CONFIG_PERF_EVENTS=y
+CONFIG_PER_VMA_LOCK=y
+CONFIG_PGTABLE_LEVELS=3
+CONFIG_PHYLIB=y
+CONFIG_PHYLIB_LEDS=y
+CONFIG_PHYLINK=y
+CONFIG_PHYS_ADDR_T_64BIT=y
+CONFIG_PHY_AIROHA_PCIE=y
+# CONFIG_PHY_AIROHA_USB  is not set
+CONFIG_PINCTRL=y
+CONFIG_PINCTRL_AIROHA=y
+# CONFIG_PINCTRL_MT2712 is not set
+# CONFIG_PINCTRL_MT6765 is not set
+# CONFIG_PINCTRL_MT6795 is not set
+# CONFIG_PINCTRL_MT6797 is not set
+# CONFIG_PINCTRL_MT7622 is not set
+# CONFIG_PINCTRL_MT7981 is not set
+# CONFIG_PINCTRL_MT7986 is not set
+# CONFIG_PINCTRL_MT8173 is not set
+# CONFIG_PINCTRL_MT8183 is not set
+# CONFIG_PINCTRL_MT8186 is not set
+# CONFIG_PINCTRL_MT8188 is not set
+# CONFIG_PINCTRL_MT8516 is not set
+CONFIG_PM=y
+CONFIG_PM_CLK=y
+CONFIG_PM_OPP=y
+CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
+CONFIG_POWER_RESET=y
+CONFIG_POWER_RESET_SYSCON=y
+CONFIG_POWER_SUPPLY=y
+CONFIG_PTP_1588_CLOCK_OPTIONAL=y
+CONFIG_QUEUED_RWLOCKS=y
+CONFIG_QUEUED_SPINLOCKS=y
+CONFIG_RANDSTRUCT_NONE=y
+CONFIG_RAS=y
+CONFIG_RATIONAL=y
+CONFIG_REGMAP=y
+CONFIG_REGMAP_MMIO=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_FIXED_VOLTAGE=y
+CONFIG_RELOCATABLE=y
+CONFIG_RESET_CONTROLLER=y
+CONFIG_RFS_ACCEL=y
+CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
+CONFIG_RPS=y
+CONFIG_RTL8261N_PHY=y
+CONFIG_RWSEM_SPIN_ON_OWNER=y
+CONFIG_SERIAL_8250_AIROHA=y
+CONFIG_SERIAL_8250_EXTENDED=y
+CONFIG_SERIAL_8250_FSL=y
+CONFIG_SERIAL_8250_NR_UARTS=5
+CONFIG_SERIAL_8250_RUNTIME_UARTS=5
+CONFIG_SERIAL_8250_SHARE_IRQ=y
+CONFIG_SERIAL_MCTRL_GPIO=y
+CONFIG_SERIAL_OF_PLATFORM=y
+CONFIG_SGL_ALLOC=y
+CONFIG_SKB_EXTENSIONS=y
+CONFIG_SMP=y
+CONFIG_SOCK_RX_QUEUE_MAPPING=y
+CONFIG_SOC_BUS=y
+CONFIG_SOFTIRQ_ON_OWN_STACK=y
+CONFIG_SPARSEMEM=y
+CONFIG_SPARSEMEM_EXTREME=y
+CONFIG_SPARSEMEM_VMEMMAP=y
+CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
+CONFIG_SPARSE_IRQ=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_SQUASHFS_DECOMP_MULTI_PERCPU=y
+CONFIG_SWIOTLB=y
+CONFIG_SWPHY=y
+CONFIG_SYSCTL_EXCEPTION_TRACE=y
+# CONFIG_TEST_FPU is not set
+CONFIG_THERMAL=y
+CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
+CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
+CONFIG_THERMAL_GOV_STEP_WISE=y
+CONFIG_THERMAL_OF=y
+CONFIG_THREAD_INFO_IN_TASK=y
+CONFIG_TICK_CPU_ACCOUNTING=y
+CONFIG_TIMER_OF=y
+CONFIG_TIMER_PROBE=y
+CONFIG_TRACE_IRQFLAGS_NMI_SUPPORT=y
+CONFIG_TREE_RCU=y
+CONFIG_TREE_SRCU=y
+CONFIG_UBIFS_FS=y
+# CONFIG_UNMAP_KERNEL_AT_EL0 is not set
+CONFIG_USER_STACKTRACE_SUPPORT=y
+CONFIG_VDSO_GETRANDOM=y
+CONFIG_VMAP_STACK=y
+CONFIG_WATCHDOG_CORE=y
+# CONFIG_WLAN is not set
+# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
+CONFIG_XFRM_AH=y
+CONFIG_XFRM_ALGO=y
+CONFIG_XFRM_ESP=y
+CONFIG_XFRM_IPCOMP=y
+CONFIG_XFRM_MIGRATE=y
+CONFIG_XPS=y
+CONFIG_XXHASH=y
+CONFIG_ZLIB_DEFLATE=y
+CONFIG_ZLIB_INFLATE=y
+CONFIG_ZONE_DMA32=y
+CONFIG_ZSTD_COMMON=y
+CONFIG_ZSTD_COMPRESS=y
+CONFIG_ZSTD_DECOMPRESS=y
diff --git a/target/linux/airoha/an7583/target.mk b/target/linux/airoha/an7583/target.mk
new file mode 100644 (file)
index 0000000..dacbe09
--- /dev/null
@@ -0,0 +1,11 @@
+ARCH:=aarch64
+SUBTARGET:=an7583
+BOARDNAME:=AN7583
+CPU_TYPE:=cortex-a53
+KERNELNAME:=Image dtbs
+FEATURES+=pwm source-only
+
+define Target/Description
+       Build firmware images for Airoha an7583 ARM based boards.
+endef
+
diff --git a/target/linux/airoha/dts/an7583-evb.dts b/target/linux/airoha/dts/an7583-evb.dts
new file mode 100644 (file)
index 0000000..fdd5b2a
--- /dev/null
@@ -0,0 +1,215 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+/dts-v1/;
+
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/input/input.h>
+#include "an7583.dtsi"
+
+/ {
+       model = "Airoha AN7583 Evaluation Board";
+       compatible = "airoha,an7583-evb", "airoha,an7583", "airoha,en7583";
+
+       aliases {
+               serial0 = &uart1;
+       };
+
+       chosen {
+               bootargs = "console=ttyS0,115200 earlycon";
+               stdout-path = "serial0:115200n8";
+       };
+
+       memory@80000000 {
+               device_type = "memory";
+               reg = <0x0 0x80000000 0x2 0x00000000>;
+       };
+};
+
+&an7583_pinctrl {
+       gpio-ranges = <&an7583_pinctrl 0 2 53>;
+
+       mdio0_pins: mdio0-pins {
+               conf {
+                       pins = "mdio_0";
+                       output-high;
+               };
+       };
+
+       pcie0_rst_pins: pcie0-rst-pins {
+               conf {
+                       pins = "pcie_reset0";
+                       drive-open-drain = <1>;
+               };
+       };
+
+       pcie1_rst_pins: pcie1-rst-pins {
+               conf {
+                       pins = "pcie_reset1";
+                       drive-open-drain = <1>;
+               };
+       };
+
+       gswp1_led0_pins: gswp1-led0-pins {
+               mux {
+                       function = "phy1_led0";
+                       pins = "gpio1";
+               };
+       };
+};
+
+&snfi {
+       status = "okay";
+};
+
+
+&spi_nand {
+       partitions {
+               compatible = "fixed-partitions";
+               #address-cells = <1>;
+               #size-cells = <1>;
+
+               bl2@0 {
+                       label = "bl2";
+                       reg = <0x0 0x20000>;
+               };
+
+               ubi@20000 {
+                       label = "ubi";
+                       reg = <0x20000 0x0>;
+               };
+       };
+};
+
+&i2c0 {
+       status = "okay";
+};
+
+&eth {
+       status = "okay";
+};
+
+&gdm1 {
+       status = "okay";
+};
+
+&switch {
+       status = "okay";
+};
+
+&gsw_phy1 {
+       pinctrl-names = "gbe-led";
+       pinctrl-0 = <&gswp1_led0_pins>;
+       status = "okay";
+};
+
+&gsw_phy1_led0 {
+       status = "okay";
+       active-low;
+};
+
+&gsw_port2 {
+       status = "disabled";
+};
+
+&gsw_port3 {
+       status = "disabled";
+};
+
+&gsw_port4 {
+       status = "disabled";
+};
+
+&gsw_phy2 {
+       status = "disabled";
+};
+
+&gsw_phy3 {
+       status = "disabled";
+};
+
+&gsw_phy4 {
+       status = "disabled";
+};
+
+&mdio_0 {
+       pinctrl-names = "default";
+       pinctrl-0 = <&mdio0_pins>;
+
+       as21xx_0: ethernet-phy@1d {
+               reg = <0x1d>;
+               compatible = "ethernet-phy-ieee802.3-c45";
+
+               firmware-name = "as21x1x_fw.bin";
+
+               reset-deassert-us = <350000>;
+               reset-assert-us = <200000>;
+               reset-gpios = <&an7583_pinctrl 34 GPIO_ACTIVE_LOW>;
+
+               leds {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       led@0 {
+                               reg = <0>;
+                               color = <LED_COLOR_ID_GREEN>;
+                               function = LED_FUNCTION_LAN;
+                               function-enumerator = <0>;
+                               default-state = "keep";
+                       };
+
+                       led@1 {
+                               reg = <1>;
+                               color = <LED_COLOR_ID_GREEN>;
+                               function = LED_FUNCTION_LAN;
+                               function-enumerator = <1>;
+                               default-state = "keep";
+                       };
+               };
+       };
+
+       as21xx_1: ethernet-phy@1f {
+               reg = <0x1f>;
+               compatible = "ethernet-phy-ieee802.3-c45";
+
+               firmware-name = "as21x1x_fw.bin";
+
+               reset-deassert-us = <350000>;
+               reset-assert-us = <200000>;
+               reset-gpios = <&an7583_pinctrl 35 GPIO_ACTIVE_LOW>;
+
+               leds {
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       led@0 {
+                               reg = <0>;
+                               color = <LED_COLOR_ID_GREEN>;
+                               function = LED_FUNCTION_LAN;
+                               function-enumerator = <0>;
+                               default-state = "keep";
+                       };
+
+                       led@1 {
+                               reg = <1>;
+                               color = <LED_COLOR_ID_GREEN>;
+                               function = LED_FUNCTION_LAN;
+                               function-enumerator = <1>;
+                               default-state = "keep";
+                       };
+               };
+       };
+};
+
+&gdm3 {
+       status = "okay";
+
+       phy-handle = <&as21xx_1>;
+       phy-mode = "usxgmii";
+};
+
+&gdm2 {
+       status = "okay";
+
+       phy-handle = <&as21xx_0>;
+       phy-mode = "usxgmii";
+};
diff --git a/target/linux/airoha/dts/an7583.dtsi b/target/linux/airoha/dts/an7583.dtsi
new file mode 100644 (file)
index 0000000..43e60eb
--- /dev/null
@@ -0,0 +1,818 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/clock/en7523-clk.h>
+#include <dt-bindings/phy/phy.h>
+#include <dt-bindings/reset/airoha,an7583-reset.h>
+#include <dt-bindings/leds/common.h>
+#include <dt-bindings/thermal/thermal.h>
+
+/ {
+       interrupt-parent = <&gic>;
+       #address-cells = <2>;
+       #size-cells = <2>;
+
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               atf@80000000 {
+                       no-map;
+                       reg = <0x0 0x80000000 0x0 0x200000>;
+               };
+
+               npu_binary: npu-binary@84000000 {
+                       no-map;
+                       reg = <0x0 0x84000000 0x0 0xa00000>;
+               };
+
+               qdma0_buf: qdma0-buf@87000000 {
+                       no-map;
+                       reg = <0x0 0x87000000 0x0 0x2000000>;
+               };
+
+               qdma1_buf: qdma1-buf@89000000 {
+                       no-map;
+                       reg = <0x0 0x89000000 0x0 0x1000000>;
+               };
+       };
+
+       psci {
+               compatible = "arm,psci-1.0";
+               method = "smc";
+       };
+
+       cpus {
+               #address-cells = <1>;
+               #size-cells = <0>;
+
+               cpu-map {
+                       cluster0 {
+                               core0 {
+                                       cpu = <&cpu0>;
+                               };
+
+                               core1 {
+                                       cpu = <&cpu1>;
+                               };
+                       };
+               };
+
+               cpu0: cpu@0 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x0>;
+                       operating-points-v2 = <&cpu_opp_table>;
+                       enable-method = "psci";
+                       clocks = <&cpufreq>;
+                       clock-names = "cpu";
+                       power-domains = <&cpufreq>;
+                       power-domain-names = "perf";
+                       next-level-cache = <&l2>;
+                       #cooling-cells = <2>;
+               };
+
+               cpu1: cpu@1 {
+                       device_type = "cpu";
+                       compatible = "arm,cortex-a53";
+                       reg = <0x1>;
+                       operating-points-v2 = <&cpu_opp_table>;
+                       enable-method = "psci";
+                       clocks = <&cpufreq>;
+                       clock-names = "cpu";
+                       power-domains = <&cpufreq>;
+                       power-domain-names = "perf";
+                       next-level-cache = <&l2>;
+                       #cooling-cells = <2>;
+               };
+
+               l2: l2-cache {
+                       compatible = "cache";
+                       cache-size = <0x80000>;
+                       cache-line-size = <64>;
+                       cache-level = <2>;
+                       cache-unified;
+               };
+       };
+
+       cpufreq: cpufreq {
+               compatible = "airoha,en7581-cpufreq";
+
+               operating-points-v2 = <&cpu_smcc_opp_table>;
+
+               #power-domain-cells = <0>;
+               #clock-cells = <0>;
+       };
+
+       cpu_opp_table: opp-table {
+               compatible = "operating-points-v2";
+               opp-shared;
+
+               opp-500000000 {
+                       opp-hz = /bits/ 64 <500000000>;
+                       required-opps = <&smcc_opp0>;
+               };
+
+               opp-550000000 {
+                       opp-hz = /bits/ 64 <550000000>;
+                       required-opps = <&smcc_opp1>;
+               };
+
+               opp-600000000 {
+                       opp-hz = /bits/ 64 <600000000>;
+                       required-opps = <&smcc_opp2>;
+               };
+
+               opp-650000000 {
+                       opp-hz = /bits/ 64 <650000000>;
+                       required-opps = <&smcc_opp3>;
+               };
+
+               opp-7000000000 {
+                       opp-hz = /bits/ 64 <700000000>;
+                       required-opps = <&smcc_opp4>;
+               };
+
+               opp-7500000000 {
+                       opp-hz = /bits/ 64 <750000000>;
+                       required-opps = <&smcc_opp5>;
+               };
+
+               opp-8000000000 {
+                       opp-hz = /bits/ 64 <800000000>;
+                       required-opps = <&smcc_opp6>;
+               };
+
+               opp-8500000000 {
+                       opp-hz = /bits/ 64 <850000000>;
+                       required-opps = <&smcc_opp7>;
+               };
+
+               opp-9000000000 {
+                       opp-hz = /bits/ 64 <900000000>;
+                       required-opps = <&smcc_opp8>;
+               };
+
+               opp-9500000000 {
+                       opp-hz = /bits/ 64 <950000000>;
+                       required-opps = <&smcc_opp9>;
+               };
+
+               opp-10000000000 {
+                       opp-hz = /bits/ 64 <1000000000>;
+                       required-opps = <&smcc_opp10>;
+               };
+
+               opp-10500000000 {
+                       opp-hz = /bits/ 64 <1050000000>;
+                       required-opps = <&smcc_opp11>;
+               };
+
+               opp-11000000000 {
+                       opp-hz = /bits/ 64 <1100000000>;
+                       required-opps = <&smcc_opp12>;
+               };
+
+               opp-11500000000 {
+                       opp-hz = /bits/ 64 <1150000000>;
+                       required-opps = <&smcc_opp13>;
+               };
+
+               opp-12000000000 {
+                       opp-hz = /bits/ 64 <1200000000>;
+                       required-opps = <&smcc_opp14>;
+               };
+       };
+
+       cpu_smcc_opp_table: opp-table-cpu-smcc {
+               compatible = "operating-points-v2";
+
+               smcc_opp0: opp0 {
+                       opp-level = <0>;
+               };
+
+               smcc_opp1: opp1 {
+                       opp-level = <1>;
+               };
+
+               smcc_opp2: opp2 {
+                       opp-level = <2>;
+               };
+
+               smcc_opp3: opp3 {
+                       opp-level = <3>;
+               };
+
+               smcc_opp4: opp4 {
+                       opp-level = <4>;
+               };
+
+               smcc_opp5: opp5 {
+                       opp-level = <5>;
+               };
+
+               smcc_opp6: opp6 {
+                       opp-level = <6>;
+               };
+
+               smcc_opp7: opp7 {
+                       opp-level = <7>;
+               };
+
+               smcc_opp8: opp8 {
+                       opp-level = <8>;
+               };
+
+               smcc_opp9: opp9 {
+                       opp-level = <9>;
+               };
+
+               smcc_opp10: opp10 {
+                       opp-level = <10>;
+               };
+
+               smcc_opp11: opp11 {
+                       opp-level = <11>;
+               };
+
+               smcc_opp12: opp12 {
+                       opp-level = <12>;
+               };
+
+               smcc_opp13: opp13 {
+                       opp-level = <13>;
+               };
+
+               smcc_opp14: opp14 {
+                       opp-level = <14>;
+               };
+       };
+
+       timer {
+               compatible = "arm,armv8-timer";
+               interrupt-parent = <&gic>;
+               interrupts = <GIC_PPI 13 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_PPI 14 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_PPI 11 IRQ_TYPE_LEVEL_LOW>,
+                            <GIC_PPI 10 IRQ_TYPE_LEVEL_LOW>;
+       };
+
+       thermal-zones {
+               cpu_thermal: cpu-thermal {
+                       polling-delay-passive = <10000>;
+                       polling-delay = <5000>;
+
+                       thermal-sensors = <&thermal 0>;
+
+                       trips {
+                               cpu_hot: cpu-hot {
+                                       temperature = <95000>;
+                                       hysteresis = <1000>;
+                                       type = "hot";
+                               };
+
+                               cpu-critical {
+                                       temperature = <110000>;
+                                       hysteresis = <1000>;
+                                       type = "critical";
+                               };
+                       };
+
+                       cooling-maps {
+                               map0 {
+                                       trip = <&cpu_hot>;
+                                       cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+                                                        <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+                               };
+                       };
+               };
+       };
+
+       clk25m: oscillator {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <25000000>;
+               clock-output-names = "clkxtal";
+       };
+
+       sys_hclk: clk-oscillator-100mhz {
+               compatible = "fixed-clock";
+               #clock-cells = <0>;
+               clock-frequency = <100000000>;
+               clock-output-names = "sys_hclk";
+       };
+
+       vmmc_3v3: regulator-vmmc-3v3 {
+               compatible = "regulator-fixed";
+               regulator-name = "vmmc";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               regulator-always-on;
+       };
+
+       sfp1: sfp1 {
+               compatible = "sff,sfp";
+       };
+
+       sfp2: sfp2 {
+               compatible = "sff,sfp";
+       };
+
+       soc {
+               compatible = "simple-bus";
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               gic: interrupt-controller@9000000 {
+                       compatible = "arm,gic-v3";
+                       interrupt-controller;
+                       #interrupt-cells = <3>;
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+                       reg = <0x0 0x09000000 0x0 0x20000>,
+                             <0x0 0x09080000 0x0 0x80000>,
+                             <0x0 0x09400000 0x0 0x2000>,
+                             <0x0 0x09500000 0x0 0x2000>,
+                             <0x0 0x09600000 0x0 0x20000>;
+                       interrupts = <GIC_PPI 9 IRQ_TYPE_LEVEL_LOW>;
+               };
+
+               chip_scu: syscon@1fa20000 {
+                       compatible = "airoha,en7581-chip-scu", "syscon", "simple-mfd";
+                       reg = <0x0 0x1fa20000 0x0 0x388>;
+
+                       thermal: thermal {
+                               compatible = "airoha,an7583-thermal";
+
+                               #thermal-sensor-cells = <0>;
+                       };
+               };
+
+               pbus_csr: syscon@1fbe3400 {
+                       compatible = "airoha,en7581-pbus-csr", "syscon";
+                       reg = <0x0 0x1fbe3400 0x0 0xff>;
+               };
+
+               scuclk: system-controller@1fa20000 {
+                       compatible = "airoha,an7583-scu", "syscon";
+                       reg = <0x0 0x1fb00000 0x0 0x970>;
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       #clock-cells = <1>;
+                       #reset-cells = <1>;
+
+                       airoha,chip-scu = <&chip_scu>;
+
+                       mdio_0: mdio-bus@c8 {
+                               compatible = "airoha,an7583-mdio";
+                               reg = <0xc8>;
+
+                               clocks = <&scuclk AN7583_CLK_MDIO0>;
+                               resets = <&scuclk AN7583_MDIO0>;
+                       };
+
+                       mdio_1: mdio-bus@cc {
+                               compatible = "airoha,an7583-mdio";
+                               reg = <0xcc>;
+
+                               clocks = <&scuclk AN7583_CLK_MDIO1>;
+                               resets = <&scuclk AN7583_MDIO1>;
+                       };
+               };
+
+               system-controller@1fbf0200 {
+                       compatible = "syscon", "simple-mfd";
+                       reg = <0x0 0x1fbf0200 0x0 0xc0>;
+
+                       an7583_pinctrl: pinctrl {
+                               compatible = "airoha,an7583-pinctrl";
+
+                               interrupt-parent = <&gic>;
+                               interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
+
+                               gpio-controller;
+                               #gpio-cells = <2>;
+
+                               interrupt-controller;
+                               #interrupt-cells = <2>;
+                       };
+               };
+
+               i2cclock: i2cclock@0 {
+                       #clock-cells = <0>;
+                       compatible = "fixed-clock";
+
+                       /* 20 MHz */
+                       clock-frequency = <20000000>;
+               };
+
+               i2c0: i2c0@1fbf8000 {
+                       compatible = "airoha,an7581-i2c";
+                       reg = <0x0 0x1fbf8000 0x0 0x100>;
+
+                       clocks = <&i2cclock>;
+
+                       /* 100 kHz */
+                       clock-frequency = <100000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       status = "disable";
+               };
+
+               i2c1: i2c1@1fbf8100 {
+                       compatible = "airoha,an7581-i2c";
+                       reg = <0x0 0x1fbf8100 0x0 0x100>;
+
+                       clocks = <&i2cclock>;
+
+                       /* 100 kHz */
+                       clock-frequency = <100000>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       status = "disable";
+               };
+
+               mmc0: mmc@1fa0e000 {
+                       compatible = "mediatek,mt7622-mmc";
+                       reg = <0x0 0x1fa0e000 0x0 0x1000>,
+                             <0x0 0x1fa0c000 0x0 0x60>;
+                       interrupts = <GIC_SPI 170 IRQ_TYPE_LEVEL_HIGH>;
+                       clocks = <&scuclk EN7581_CLK_EMMC>, <&clk25m>;
+                       clock-names = "source", "hclk";
+                       bus-width = <4>;
+                       max-frequency = <52000000>;
+                       vmmc-supply = <&vmmc_3v3>;
+                       disable-wp;
+                       cap-mmc-highspeed;
+                       non-removable;
+
+                       status = "disabled";
+               };
+
+               snfi: spi@1fa10000 {
+                       compatible = "airoha,en7581-snand";
+                       reg = <0x0 0x1fa10000 0x0 0x140>,
+                             <0x0 0x1fa11000 0x0 0x160>;
+
+                       clocks = <&scuclk EN7523_CLK_SPI>;
+                       clock-names = "spi";
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       status = "disabled";
+
+                       spi_nand: nand@0 {
+                               compatible = "spi-nand";
+                               reg = <0>;
+                               spi-max-frequency = <50000000>;
+                               spi-tx-bus-width = <1>;
+                               spi-rx-bus-width = <2>;
+                       };
+               };
+
+               uart1: serial@1fbf0000 {
+                       compatible = "ns16550";
+                       reg = <0x0 0x1fbf0000 0x0 0x30>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <1843200>;
+               };
+
+               watchdog@1fbf0100 {
+                       compatible = "airoha,en7581-wdt";
+                       reg = <0x0 0x1fbf0100 0x0 0x38>;
+
+                       clocks = <&sys_hclk>;
+                       clock-names = "bus";
+               };
+
+               uart2: serial@1fbf0300 {
+                       compatible = "airoha,en7523-uart";
+                       reg = <0x0 0x1fbf0300 0x0 0x30>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <7372800>;
+
+                       status = "disabled";
+               };
+
+               hsuart3: serial@1fbe1000 {
+                       compatible = "airoha,en7523-uart";
+                       reg = <0x0 0x1fbe1000 0x0 0x40>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <7372800>;
+
+                       status = "disabled";
+               };
+
+               uart4: serial@1fbf0600 {
+                       compatible = "airoha,en7523-uart";
+                       reg = <0x0 0x1fbf0600 0x0 0x30>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <7372800>;
+
+                       status = "disabled";
+               };
+
+               uart5: serial@1fbf0700 {
+                       compatible = "airoha,en7523-uart";
+                       reg = <0x0 0x1fbf0700 0x0 0x30>;
+                       reg-io-width = <4>;
+                       reg-shift = <2>;
+                       interrupts = <GIC_SPI 18 IRQ_TYPE_LEVEL_HIGH>;
+                       clock-frequency = <7372800>;
+
+                       status = "disabled";
+               };
+
+               crypto@1e004000 {
+                       compatible = "inside-secure,safexcel-eip93ies";
+                       reg = <0x0 0x1fb70000 0x0 0x1000>;
+
+                       interrupts = <GIC_SPI 44 IRQ_TYPE_LEVEL_HIGH>;
+               };
+
+               pon_pcs: pcs@1fa08000 {
+                       compatible = "airoha,an7583-pcs-pon";
+                       reg = <0x0 0x1fa08000 0x0 0x1000>,
+                             <0x0 0x1fa80000 0x0 0x60>,
+                             <0x0 0x1fa80a00 0x0 0x164>,
+                             <0x0 0x1fa84000 0x0 0x450>,
+                             <0x0 0x1fa85900 0x0 0x338>,
+                             <0x0 0x1fa86000 0x0 0x300>,
+                             <0x0 0x1fa8f000 0x0 0x1000>,
+                             <0x0 0x1fa8e000 0x0 0x1000>;
+                       reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs",
+                                   "multi_sgmii", "usxgmii",
+                                   "hsgmii_rate_adp", "xfi_ana", "xfi_pma";
+
+                       resets = <&scuclk AN7583_XPON_MAC_RST>,
+                                <&scuclk AN7583_XPON_PHY_RST>,
+                                <&scuclk AN7583_XPON_XFI_RST>;
+                       reset-names = "mac", "phy", "xfi";
+
+                       airoha,scu = <&scuclk>;
+               };
+
+               eth_pcs: pcs@1fa09000 {
+                       compatible = "airoha,an7583-pcs-eth";
+                       reg = <0x0 0x1fa09000 0x0 0x1000>,
+                             <0x0 0x1fa70000 0x0 0x60>,
+                             <0x0 0x1fa70a00 0x0 0x164>,
+                             <0x0 0x1fa74000 0x0 0x450>,
+                             <0x0 0x1fa75900 0x0 0x338>,
+                             <0x0 0x1fa76000 0x0 0x300>,
+                             <0x0 0x1fa7f000 0x0 0x1000>,
+                             <0x0 0x1fa7e000 0x0 0x1000>;
+                       reg-names = "xfi_mac", "hsgmii_an", "hsgmii_pcs",
+                                   "multi_sgmii", "usxgmii",
+                                   "hsgmii_rate_adp", "xfi_ana", "xfi_pma";
+
+                       resets = <&scuclk AN7583_XSI_MAC_RST>,
+                                <&scuclk AN7583_XSI_PHY_RST>;
+                       reset-names = "mac", "phy";
+
+                       airoha,scu = <&scuclk>;
+               };
+
+               eth: ethernet@1fb50000 {
+                       compatible = "airoha,an7583-eth";
+                       reg = <0 0x1fb50000 0 0x2600>,
+                             <0 0x1fb54000 0 0x2000>,
+                             <0 0x1fb56000 0 0x2000>;
+                       reg-names = "fe", "qdma0", "qdma1";
+
+                       resets = <&scuclk AN7583_FE_RST>,
+                                <&scuclk AN7583_FE_PDMA_RST>,
+                                <&scuclk AN7583_FE_QDMA_RST>,
+                                <&scuclk AN7583_DUAL_HSI0_MAC_RST>,
+                                <&scuclk AN7583_DUAL_HSI1_MAC_RST>,
+                                <&scuclk AN7583_XFP_MAC_RST>;
+                       reset-names = "fe", "pdma", "qdma",
+                                     "hsi0-mac", "hsi1-mac",
+                                     "xfp-mac";
+
+                       interrupts = <GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 38 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 49 IRQ_TYPE_LEVEL_HIGH>,
+                                    <GIC_SPI 64 IRQ_TYPE_LEVEL_HIGH>;
+
+                       memory-region = <&qdma0_buf>, <&qdma1_buf>;
+                       memory-region-names = "qdma0-buf", "qdma1-buf";
+
+                       status = "disabled";
+
+                       #address-cells = <1>;
+                       #size-cells = <0>;
+
+                       gdm1: ethernet@1 {
+                               compatible = "airoha,eth-mac";
+                               reg = <1>;
+                               phy-mode = "internal";
+                               status = "disabled";
+
+                               fixed-link {
+                                       speed = <10000>;
+                                       full-duplex;
+                                       pause;
+                               };
+                       };
+
+                       gdm2: ethernet@2 {
+                               compatible = "airoha,eth-mac";
+                               reg = <2>;
+                               pcs = <&pon_pcs>;
+
+                               status = "disabled";
+                       };
+
+                       gdm3: ethernet@3 {
+                               compatible = "airoha,eth-mac";
+                               reg = <3>;
+                               pcs = <&eth_pcs>;
+                               airoha,gdm-srcport = <0x16>;
+
+                               status = "disabled";
+                       };
+               };
+
+               switch: switch@1fb58000 {
+                       compatible = "airoha,an7583-switch";
+                       reg = <0 0x1fb58000 0 0x8000>;
+                       resets = <&scuclk AN7583_GSW_RST>;
+
+                       interrupt-controller;
+                       #interrupt-cells = <1>;
+                       interrupt-parent = <&gic>;
+                       interrupts = <GIC_SPI 209 IRQ_TYPE_LEVEL_HIGH>;
+
+                       status = "disabled";
+
+                       #address-cells = <1>;
+                       #size-cells = <1>;
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               gsw_port1: port@1 {
+                                       reg = <1>;
+                                       label = "lan1";
+                                       phy-mode = "internal";
+                                       phy-handle = <&gsw_phy1>;
+                               };
+
+                               gsw_port2: port@2 {
+                                       reg = <2>;
+                                       label = "lan2";
+                                       phy-mode = "internal";
+                                       phy-handle = <&gsw_phy2>;
+                               };
+
+                               gsw_port3: port@3 {
+                                       reg = <3>;
+                                       label = "lan3";
+                                       phy-mode = "internal";
+                                       phy-handle = <&gsw_phy3>;
+                               };
+
+                               gsw_port4: port@4 {
+                                       reg = <4>;
+                                       label = "lan4";
+                                       phy-mode = "internal";
+                                       phy-handle = <&gsw_phy4>;
+                               };
+
+                               port@6 {
+                                       reg = <6>;
+                                       label = "cpu";
+                                       ethernet = <&gdm1>;
+                                       phy-mode = "internal";
+
+                                       fixed-link {
+                                               speed = <10000>;
+                                               full-duplex;
+                                               pause;
+                                       };
+                               };
+                       };
+
+                       mdio: mdio {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               gsw_phy1: ethernet-phy@1 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <9>;
+                                       phy-mode = "internal";
+
+                                       leds {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+
+                                               gsw_phy1_led0: gsw-phy1-led0@0 {
+                                                       reg = <0>;
+                                                       function = "phy1_led0";
+                                                       status = "disabled";
+                                               };
+
+                                               gsw_phy1_led1: gsw-phy1-led1@1 {
+                                                       reg = <1>;
+                                                       function = "phy1_led1";
+                                                       status = "disabled";
+                                               };
+                                       };
+                               };
+
+                               gsw_phy2: ethernet-phy@2 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <10>;
+                                       phy-mode = "internal";
+
+                                       leds {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+
+                                               gsw_phy2_led0: gsw-phy2-led0@0 {
+                                                       reg = <0>;
+                                                       function = "phy2_led0";
+                                                       status = "disabled";
+                                               };
+
+                                               gsw_phy2_led1: gsw-phy2-led1@1 {
+                                                       reg = <1>;
+                                                       function = "phy1_led1";
+                                                       status = "disabled";
+                                               };
+                                       };
+                               };
+
+                               gsw_phy3: ethernet-phy@3 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <11>;
+                                       phy-mode = "internal";
+
+                                       leds {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+
+                                               gsw_phy3_led0: gsw-phy3-led0@0 {
+                                                       reg = <0>;
+                                                       function = LED_FUNCTION_LAN;
+                                                       status = "disabled";
+                                               };
+
+                                               gsw_phy3_led1: gsw-phy3-led1@1 {
+                                                       reg = <1>;
+                                                       function = LED_FUNCTION_LAN;
+                                                       status = "disabled";
+                                               };
+                                       };
+                               };
+
+                               gsw_phy4: ethernet-phy@4 {
+                                       compatible = "ethernet-phy-ieee802.3-c22";
+                                       reg = <12>;
+                                       phy-mode = "internal";
+
+                                       leds {
+                                               #address-cells = <1>;
+                                               #size-cells = <0>;
+
+                                               gsw_phy4_led0: gsw-phy4-led0@0 {
+                                                       reg = <0>;
+                                                       function = LED_FUNCTION_LAN;
+                                                       status = "disabled";
+                                               };
+
+                                               gsw_phy4_led1: gsw-phy4-led1@1 {
+                                                       reg = <1>;
+                                                       function = LED_FUNCTION_LAN;
+                                                       status = "disabled";
+                                               };
+                                       };
+                               };
+                       };
+               };
+       };
+};
diff --git a/target/linux/airoha/image/an7583.mk b/target/linux/airoha/image/an7583.mk
new file mode 100644 (file)
index 0000000..6ebec7a
--- /dev/null
@@ -0,0 +1,55 @@
+define Build/an7583-bl2-bl31-uboot
+  head -c $$((0x800)) /dev/zero > $@
+  cat $(STAGING_DIR_IMAGE)/an7583_$1-bl2.fip >> $@
+  dd if=$(STAGING_DIR_IMAGE)/an7583_$1-bl31-uboot.img of=$@ bs=1 seek=$$((0x20000)) conv=notrunc
+endef
+
+define Build/an7583-emmc-bl2-bl31-uboot
+  head -c $$((0x800)) /dev/zero > $@
+  cat $(STAGING_DIR_IMAGE)/an7583_$1-bl2.fip >> $@
+  dd if=$(STAGING_DIR_IMAGE)/an7583_$1-bl31-u-boot.fip of=$@ bs=1 seek=$$((0x20000)) conv=notrunc
+endef
+
+define Build/an7583-preloader
+  cat $(STAGING_DIR_IMAGE)/an7583_$1-bl2.fip >> $@
+endef
+
+define Build/an7583-bl31-uboot
+  cat $(STAGING_DIR_IMAGE)/an7583_$1-bl31-u-boot.fip >> $@
+endef
+
+define Device/FitImageLzma
+       KERNEL_SUFFIX := -uImage.itb
+       KERNEL = kernel-bin | lzma | fit lzma $$(KDIR)/image-$$(DEVICE_DTS).dtb
+       KERNEL_NAME := Image
+endef
+
+define Device/airoha_an7583-evb
+  $(call Device/FitImageLzma)
+  DEVICE_VENDOR := Airoha
+  DEVICE_MODEL := AN7583 Evaluation Board (SNAND)
+  DEVICE_PACKAGES := kmod-leds-pwm kmod-input-gpio-keys-polled
+  DEVICE_DTS := an7583-evb
+  DEVICE_DTS_DIR := ../dts
+  DEVICE_DTS_CONFIG := config@1
+  KERNEL_LOADADDR := 0x80088000
+  IMAGE/sysupgrade.bin := append-kernel | pad-to 128k | append-rootfs | pad-rootfs | append-metadata
+  ARTIFACT/bl2-bl31-uboot.bin := an7583-bl2-bl31-uboot rfb
+  ARTIFACT/preloader.bin := an7583-preloader rfb
+  ARTIFACT/bl31-uboot.fip := an7583-bl31-uboot rfb
+  ARTIFACTS := bl2-bl31-uboot.bin preloader.bin bl31-uboot.fip
+endef
+TARGET_DEVICES += airoha_an7583-evb
+
+define Device/airoha_an7583-evb-emmc
+  DEVICE_VENDOR := Airoha
+  DEVICE_MODEL := AN7583 Evaluation Board (EMMC)
+  DEVICE_DTS := an7583-evb-emmc
+  DEVICE_DTS_DIR := ../dts
+  DEVICE_PACKAGES := kmod-i2c-an7581
+  ARTIFACT/preloader.bin := an7583-preloader rfb
+  ARTIFACT/bl31-uboot.fip := an7583-bl31-uboot rfb
+  ARTIFACT/bl2-bl31-uboot.bin := an7583-emmc-bl2-bl31-uboot rfb
+  ARTIFACTS := bl2-bl31-uboot.bin preloader.bin bl31-uboot.fip
+endef
+TARGET_DEVICES += airoha_an7583-evb-emmc
diff --git a/target/linux/airoha/patches-6.12/090-v6.17-net-mdio-Add-MDIO-bus-controller-for-Airoha-AN7583.patch b/target/linux/airoha/patches-6.12/090-v6.17-net-mdio-Add-MDIO-bus-controller-for-Airoha-AN7583.patch
new file mode 100644 (file)
index 0000000..37b0ed5
--- /dev/null
@@ -0,0 +1,342 @@
+From 67e3ba978361cb262f8f8981ab88ccb97f1e2bda Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 17 Jun 2025 11:16:53 +0200
+Subject: [PATCH] net: mdio: Add MDIO bus controller for Airoha AN7583
+
+Airoha AN7583 SoC have 2 dedicated MDIO bus controller in the SCU
+register map. To driver register an MDIO controller based on the DT
+reg property and access the register by accessing the parent syscon.
+
+The MDIO bus logic is similar to the MT7530 internal MDIO bus but
+deviates of some setting and some HW bug.
+
+On Airoha AN7583 the MDIO clock is set to 25MHz by default and needs to
+be correctly setup to 2.5MHz to correctly work (by setting the divisor
+to 10x).
+
+There seems to be Hardware bug where AN7583_MII_RWDATA
+is not wiped in the context of unconnected PHY and the
+previous read value is returned.
+
+Example: (only one PHY on the BUS at 0x1f)
+ - read at 0x1f report at 0x2 0x7500
+ - read at 0x0 report 0x7500 on every address
+
+To workaround this, we reset the Mdio BUS at every read
+to have consistent values on read operation.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/mdio/Kconfig       |   7 +
+ drivers/net/mdio/Makefile      |   1 +
+ drivers/net/mdio/mdio-airoha.c | 276 +++++++++++++++++++++++++++++++++
+ 3 files changed, 284 insertions(+)
+ create mode 100644 drivers/net/mdio/mdio-airoha.c
+
+--- a/drivers/net/mdio/Kconfig
++++ b/drivers/net/mdio/Kconfig
+@@ -46,6 +46,13 @@ if MDIO_BUS
+ config MDIO_DEVRES
+       tristate
++config MDIO_AIROHA
++      tristate "Airoha AN7583 MDIO bus controller"
++      depends on ARCH_AIROHA || COMPILE_TEST
++      help
++        This module provides a driver for the MDIO busses found in the
++        Airoha AN7583 SoC's.
++
+ config MDIO_SUN4I
+       tristate "Allwinner sun4i MDIO interface support"
+       depends on ARCH_SUNXI || COMPILE_TEST
+--- a/drivers/net/mdio/Makefile
++++ b/drivers/net/mdio/Makefile
+@@ -5,6 +5,7 @@ obj-$(CONFIG_ACPI_MDIO)                += acpi_mdio.o
+ obj-$(CONFIG_FWNODE_MDIO)     += fwnode_mdio.o
+ obj-$(CONFIG_OF_MDIO)         += of_mdio.o
++obj-$(CONFIG_MDIO_AIROHA)             += mdio-airoha.o
+ obj-$(CONFIG_MDIO_ASPEED)             += mdio-aspeed.o
+ obj-$(CONFIG_MDIO_BCM_IPROC)          += mdio-bcm-iproc.o
+ obj-$(CONFIG_MDIO_BCM_UNIMAC)         += mdio-bcm-unimac.o
+--- /dev/null
++++ b/drivers/net/mdio/mdio-airoha.c
+@@ -0,0 +1,276 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Airoha AN7583 MDIO interface driver
++ *
++ * Copyright (C) 2025 Christian Marangi <ansuelsmth@gmail.com>
++ */
++
++#include <linux/clk.h>
++#include <linux/delay.h>
++#include <linux/kernel.h>
++#include <linux/mfd/syscon.h>
++#include <linux/module.h>
++#include <linux/of_mdio.h>
++#include <linux/of_address.h>
++#include <linux/platform_device.h>
++#include <linux/regmap.h>
++#include <linux/reset.h>
++
++/* MII address register definitions */
++#define   AN7583_MII_BUSY                     BIT(31)
++#define   AN7583_MII_RDY                      BIT(30) /* RO signal BUS is ready */
++#define   AN7583_MII_CL22_REG_ADDR            GENMASK(29, 25)
++#define   AN7583_MII_CL45_DEV_ADDR            AN7583_MII_CL22_REG_ADDR
++#define   AN7583_MII_PHY_ADDR                 GENMASK(24, 20)
++#define   AN7583_MII_CMD                      GENMASK(19, 18)
++#define   AN7583_MII_CMD_CL22_WRITE           FIELD_PREP_CONST(AN7583_MII_CMD, 0x1)
++#define   AN7583_MII_CMD_CL22_READ            FIELD_PREP_CONST(AN7583_MII_CMD, 0x2)
++#define   AN7583_MII_CMD_CL45_ADDR            FIELD_PREP_CONST(AN7583_MII_CMD, 0x0)
++#define   AN7583_MII_CMD_CL45_WRITE           FIELD_PREP_CONST(AN7583_MII_CMD, 0x1)
++#define   AN7583_MII_CMD_CL45_POSTREAD_INCADDR        FIELD_PREP_CONST(AN7583_MII_CMD, 0x2)
++#define   AN7583_MII_CMD_CL45_READ            FIELD_PREP_CONST(AN7583_MII_CMD, 0x3)
++#define   AN7583_MII_ST                               GENMASK(17, 16)
++#define   AN7583_MII_ST_CL45                  FIELD_PREP_CONST(AN7583_MII_ST, 0x0)
++#define   AN7583_MII_ST_CL22                  FIELD_PREP_CONST(AN7583_MII_ST, 0x1)
++#define   AN7583_MII_RWDATA                   GENMASK(15, 0)
++#define   AN7583_MII_CL45_REG_ADDR            AN7583_MII_RWDATA
++
++#define AN7583_MII_MDIO_DELAY_USEC            100
++#define AN7583_MII_MDIO_RETRY_MSEC            100
++
++struct airoha_mdio_data {
++      u32 base_addr;
++      struct regmap *regmap;
++      struct clk *clk;
++      struct reset_control *reset;
++};
++
++static int airoha_mdio_wait_busy(struct airoha_mdio_data *priv)
++{
++      u32 busy;
++
++      return regmap_read_poll_timeout(priv->regmap, priv->base_addr, busy,
++                                      !(busy & AN7583_MII_BUSY),
++                                      AN7583_MII_MDIO_DELAY_USEC,
++                                      AN7583_MII_MDIO_RETRY_MSEC * USEC_PER_MSEC);
++}
++
++static void airoha_mdio_reset(struct airoha_mdio_data *priv)
++{
++      /* There seems to be Hardware bug where AN7583_MII_RWDATA
++       * is not wiped in the context of unconnected PHY and the
++       * previous read value is returned.
++       *
++       * Example: (only one PHY on the BUS at 0x1f)
++       *  - read at 0x1f report at 0x2 0x7500
++       *  - read at 0x0 report 0x7500 on every address
++       *
++       * To workaround this, we reset the Mdio BUS at every read
++       * to have consistent values on read operation.
++       */
++      reset_control_assert(priv->reset);
++      reset_control_deassert(priv->reset);
++}
++
++static int airoha_mdio_read(struct mii_bus *bus, int addr, int regnum)
++{
++      struct airoha_mdio_data *priv = bus->priv;
++      u32 val;
++      int ret;
++
++      airoha_mdio_reset(priv);
++
++      val = AN7583_MII_BUSY | AN7583_MII_ST_CL22 |
++            AN7583_MII_CMD_CL22_READ;
++      val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr);
++      val |= FIELD_PREP(AN7583_MII_CL22_REG_ADDR, regnum);
++
++      ret = regmap_write(priv->regmap, priv->base_addr, val);
++      if (ret)
++              return ret;
++
++      ret = airoha_mdio_wait_busy(priv);
++      if (ret)
++              return ret;
++
++      ret = regmap_read(priv->regmap, priv->base_addr, &val);
++      if (ret)
++              return ret;
++
++      return FIELD_GET(AN7583_MII_RWDATA, val);
++}
++
++static int airoha_mdio_write(struct mii_bus *bus, int addr, int regnum,
++                           u16 value)
++{
++      struct airoha_mdio_data *priv = bus->priv;
++      u32 val;
++      int ret;
++
++      val = AN7583_MII_BUSY | AN7583_MII_ST_CL22 |
++            AN7583_MII_CMD_CL22_WRITE;
++      val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr);
++      val |= FIELD_PREP(AN7583_MII_CL22_REG_ADDR, regnum);
++      val |= FIELD_PREP(AN7583_MII_RWDATA, value);
++
++      ret = regmap_write(priv->regmap, priv->base_addr, val);
++      if (ret)
++              return ret;
++
++      ret = airoha_mdio_wait_busy(priv);
++
++      return ret;
++}
++
++static int airoha_mdio_cl45_read(struct mii_bus *bus, int addr, int devnum,
++                               int regnum)
++{
++      struct airoha_mdio_data *priv = bus->priv;
++      u32 val;
++      int ret;
++
++      airoha_mdio_reset(priv);
++
++      val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 |
++            AN7583_MII_CMD_CL45_ADDR;
++      val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr);
++      val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum);
++      val |= FIELD_PREP(AN7583_MII_CL45_REG_ADDR, regnum);
++
++      ret = regmap_write(priv->regmap, priv->base_addr, val);
++      if (ret)
++              return ret;
++
++      ret = airoha_mdio_wait_busy(priv);
++      if (ret)
++              return ret;
++
++      val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 |
++            AN7583_MII_CMD_CL45_READ;
++      val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr);
++      val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum);
++
++      ret = regmap_write(priv->regmap, priv->base_addr, val);
++      if (ret)
++              return ret;
++
++      ret = airoha_mdio_wait_busy(priv);
++      if (ret)
++              return ret;
++
++      ret = regmap_read(priv->regmap, priv->base_addr, &val);
++      if (ret)
++              return ret;
++
++      return FIELD_GET(AN7583_MII_RWDATA, val);
++}
++
++static int airoha_mdio_cl45_write(struct mii_bus *bus, int addr, int devnum,
++                                int regnum, u16 value)
++{
++      struct airoha_mdio_data *priv = bus->priv;
++      u32 val;
++      int ret;
++
++      val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 |
++            AN7583_MII_CMD_CL45_ADDR;
++      val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr);
++      val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum);
++      val |= FIELD_PREP(AN7583_MII_CL45_REG_ADDR, regnum);
++
++      ret = regmap_write(priv->regmap, priv->base_addr, val);
++      if (ret)
++              return ret;
++
++      ret = airoha_mdio_wait_busy(priv);
++      if (ret)
++              return ret;
++
++      val = AN7583_MII_BUSY | AN7583_MII_ST_CL45 |
++            AN7583_MII_CMD_CL45_WRITE;
++      val |= FIELD_PREP(AN7583_MII_PHY_ADDR, addr);
++      val |= FIELD_PREP(AN7583_MII_CL45_DEV_ADDR, devnum);
++      val |= FIELD_PREP(AN7583_MII_RWDATA, value);
++
++      ret = regmap_write(priv->regmap, priv->base_addr, val);
++      if (ret)
++              return ret;
++
++      ret = airoha_mdio_wait_busy(priv);
++
++      return ret;
++}
++
++static int airoha_mdio_probe(struct platform_device *pdev)
++{
++      struct device *dev = &pdev->dev;
++      struct airoha_mdio_data *priv;
++      struct mii_bus *bus;
++      u32 addr, freq;
++      int ret;
++
++      ret = of_property_read_u32(dev->of_node, "reg", &addr);
++      if (ret)
++              return ret;
++
++      bus = devm_mdiobus_alloc_size(dev, sizeof(*priv));
++      if (!bus)
++              return -ENOMEM;
++
++      priv = bus->priv;
++      priv->base_addr = addr;
++      priv->regmap = device_node_to_regmap(dev->parent->of_node);
++
++      priv->clk = devm_clk_get_enabled(dev, NULL);
++      if (IS_ERR(priv->clk))
++              return PTR_ERR(priv->clk);
++
++      priv->reset = devm_reset_control_get_exclusive(dev, NULL);
++      if (IS_ERR(priv->reset))
++              return PTR_ERR(priv->reset);
++
++      reset_control_deassert(priv->reset);
++
++      bus->name = "airoha_mdio_bus";
++      snprintf(bus->id, MII_BUS_ID_SIZE, "%s-mii", dev_name(dev));
++      bus->parent = dev;
++      bus->read = airoha_mdio_read;
++      bus->write = airoha_mdio_write;
++      bus->read_c45 = airoha_mdio_cl45_read;
++      bus->write_c45 = airoha_mdio_cl45_write;
++
++      /* Check if a custom frequency is defined in DT or default to 2.5 MHz */
++      if (of_property_read_u32(dev->of_node, "clock-frequency", &freq))
++              freq = 2500000;
++
++      ret = clk_set_rate(priv->clk, freq);
++      if (ret)
++              return ret;
++
++      ret = devm_of_mdiobus_register(dev, bus, dev->of_node);
++      if (ret) {
++              reset_control_assert(priv->reset);
++              return ret;
++      }
++
++      return 0;
++}
++
++static const struct of_device_id airoha_mdio_dt_ids[] = {
++      { .compatible = "airoha,an7583-mdio" },
++      { }
++};
++MODULE_DEVICE_TABLE(of, airoha_mdio_dt_ids);
++
++static struct platform_driver airoha_mdio_driver = {
++      .probe = airoha_mdio_probe,
++      .driver = {
++              .name = "airoha-mdio",
++              .of_match_table = airoha_mdio_dt_ids,
++      },
++};
++
++module_platform_driver(airoha_mdio_driver);
++
++MODULE_DESCRIPTION("Airoha AN7583 MDIO interface driver");
++MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
++MODULE_LICENSE("GPL");
diff --git a/target/linux/airoha/patches-6.12/120-02-pinctrl-mediatek-airoha-generalize-pins-group-functi.patch b/target/linux/airoha/patches-6.12/120-02-pinctrl-mediatek-airoha-generalize-pins-group-functi.patch
new file mode 100644 (file)
index 0000000..61989bc
--- /dev/null
@@ -0,0 +1,779 @@
+From e77c958d8eab1c29008ab57a2be82daefe886e0a Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sun, 25 May 2025 19:25:20 +0200
+Subject: [PATCH 2/5] pinctrl: mediatek: airoha: generalize
+ pins/group/function/confs handling
+
+In preparation for support of Airoha AN7583, generalize
+pins/group/function/confs handling and move them in match_data.
+Inner function will base the values on the pinctrl priv struct instead of
+relying on hardcoded struct.
+
+This permits to use different PIN data while keeping the same logic.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-airoha.c | 569 ++++++++++++----------
+ 1 file changed, 319 insertions(+), 250 deletions(-)
+
+--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c
++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
+@@ -30,20 +30,20 @@
+ #include "../pinconf.h"
+ #include "../pinmux.h"
+-#define PINCTRL_PIN_GROUP(id)                                         \
+-      PINCTRL_PINGROUP(#id, id##_pins, ARRAY_SIZE(id##_pins))
++#define PINCTRL_PIN_GROUP(id, table)                                  \
++      PINCTRL_PINGROUP(id, table##_pins, ARRAY_SIZE(table##_pins))
+-#define PINCTRL_FUNC_DESC(id)                                         \
++#define PINCTRL_FUNC_DESC(id, table)                                  \
+       {                                                               \
+               .desc = {                                               \
+                       .func = {                                       \
+                               .name = #id,                            \
+-                              .groups = id##_groups,                  \
+-                              .ngroups = ARRAY_SIZE(id##_groups),     \
++                              .groups = table##_groups,               \
++                              .ngroups = ARRAY_SIZE(table##_groups),  \
+                       }                                               \
+               },                                                      \
+-              .groups = id##_func_group,                              \
+-              .group_size = ARRAY_SIZE(id##_func_group),              \
++              .groups = table##_func_group,                           \
++              .group_size = ARRAY_SIZE(table##_func_group),           \
+       }
+ #define PINCTRL_CONF_DESC(p, offset, mask)                            \
+@@ -362,16 +362,46 @@ struct airoha_pinctrl_gpiochip {
+       u32 irq_type[AIROHA_NUM_PINS];
+ };
++struct airoha_pinctrl_confs_info {
++      const struct airoha_pinctrl_conf *confs;
++      unsigned int num_confs;
++};
++
++enum airoha_pinctrl_confs_type {
++      AIROHA_PINCTRL_CONFS_PULLUP,
++      AIROHA_PINCTRL_CONFS_PULLDOWN,
++      AIROHA_PINCTRL_CONFS_DRIVE_E2,
++      AIROHA_PINCTRL_CONFS_DRIVE_E4,
++      AIROHA_PINCTRL_CONFS_PCIE_RST_OD,
++
++      AIROHA_PINCTRL_CONFS_MAX,
++};
++
+ struct airoha_pinctrl {
+       struct pinctrl_dev *ctrl;
++      struct pinctrl_desc desc;
++      const struct pingroup *grps;
++      const struct airoha_pinctrl_func *funcs;
++      const struct airoha_pinctrl_confs_info *confs_info;
++
+       struct regmap *chip_scu;
+       struct regmap *regmap;
+       struct airoha_pinctrl_gpiochip gpiochip;
+ };
+-static struct pinctrl_pin_desc airoha_pinctrl_pins[] = {
++struct airoha_pinctrl_match_data {
++      const struct pinctrl_pin_desc *pins;
++      const unsigned int num_pins;
++      const struct pingroup *grps;
++      const unsigned int num_grps;
++      const struct airoha_pinctrl_func *funcs;
++      const unsigned int num_funcs;
++      const struct airoha_pinctrl_confs_info confs_info[AIROHA_PINCTRL_CONFS_MAX];
++};
++
++static struct pinctrl_pin_desc en7581_pinctrl_pins[] = {
+       PINCTRL_PIN(0, "uart1_txd"),
+       PINCTRL_PIN(1, "uart1_rxd"),
+       PINCTRL_PIN(2, "i2c_scl"),
+@@ -432,172 +462,172 @@ static struct pinctrl_pin_desc airoha_pi
+       PINCTRL_PIN(63, "pcie_reset2"),
+ };
+-static const int pon_pins[] = { 49, 50, 51, 52, 53, 54 };
+-static const int pon_tod_1pps_pins[] = { 46 };
+-static const int gsw_tod_1pps_pins[] = { 46 };
+-static const int sipo_pins[] = { 16, 17 };
+-static const int sipo_rclk_pins[] = { 16, 17, 43 };
+-static const int mdio_pins[] = { 14, 15 };
+-static const int uart2_pins[] = { 48, 55 };
+-static const int uart2_cts_rts_pins[] = { 46, 47 };
+-static const int hsuart_pins[] = { 28, 29 };
+-static const int hsuart_cts_rts_pins[] = { 26, 27 };
+-static const int uart4_pins[] = { 38, 39 };
+-static const int uart5_pins[] = { 18, 19 };
+-static const int i2c0_pins[] = { 2, 3 };
+-static const int i2c1_pins[] = { 14, 15 };
+-static const int jtag_udi_pins[] = { 16, 17, 18, 19, 20 };
+-static const int jtag_dfd_pins[] = { 16, 17, 18, 19, 20 };
+-static const int i2s_pins[] = { 26, 27, 28, 29 };
+-static const int pcm1_pins[] = { 22, 23, 24, 25 };
+-static const int pcm2_pins[] = { 18, 19, 20, 21 };
+-static const int spi_quad_pins[] = { 32, 33 };
+-static const int spi_pins[] = { 4, 5, 6, 7 };
+-static const int spi_cs1_pins[] = { 34 };
+-static const int pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 };
+-static const int pcm_spi_int_pins[] = { 14 };
+-static const int pcm_spi_rst_pins[] = { 15 };
+-static const int pcm_spi_cs1_pins[] = { 43 };
+-static const int pcm_spi_cs2_pins[] = { 40 };
+-static const int pcm_spi_cs2_p128_pins[] = { 40 };
+-static const int pcm_spi_cs2_p156_pins[] = { 40 };
+-static const int pcm_spi_cs3_pins[] = { 41 };
+-static const int pcm_spi_cs4_pins[] = { 42 };
+-static const int emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 };
+-static const int pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 };
+-static const int gpio0_pins[] = { 13 };
+-static const int gpio1_pins[] = { 14 };
+-static const int gpio2_pins[] = { 15 };
+-static const int gpio3_pins[] = { 16 };
+-static const int gpio4_pins[] = { 17 };
+-static const int gpio5_pins[] = { 18 };
+-static const int gpio6_pins[] = { 19 };
+-static const int gpio7_pins[] = { 20 };
+-static const int gpio8_pins[] = { 21 };
+-static const int gpio9_pins[] = { 22 };
+-static const int gpio10_pins[] = { 23 };
+-static const int gpio11_pins[] = { 24 };
+-static const int gpio12_pins[] = { 25 };
+-static const int gpio13_pins[] = { 26 };
+-static const int gpio14_pins[] = { 27 };
+-static const int gpio15_pins[] = { 28 };
+-static const int gpio16_pins[] = { 29 };
+-static const int gpio17_pins[] = { 30 };
+-static const int gpio18_pins[] = { 31 };
+-static const int gpio19_pins[] = { 32 };
+-static const int gpio20_pins[] = { 33 };
+-static const int gpio21_pins[] = { 34 };
+-static const int gpio22_pins[] = { 35 };
+-static const int gpio23_pins[] = { 36 };
+-static const int gpio24_pins[] = { 37 };
+-static const int gpio25_pins[] = { 38 };
+-static const int gpio26_pins[] = { 39 };
+-static const int gpio27_pins[] = { 40 };
+-static const int gpio28_pins[] = { 41 };
+-static const int gpio29_pins[] = { 42 };
+-static const int gpio30_pins[] = { 43 };
+-static const int gpio31_pins[] = { 44 };
+-static const int gpio33_pins[] = { 46 };
+-static const int gpio34_pins[] = { 47 };
+-static const int gpio35_pins[] = { 48 };
+-static const int gpio36_pins[] = { 49 };
+-static const int gpio37_pins[] = { 50 };
+-static const int gpio38_pins[] = { 51 };
+-static const int gpio39_pins[] = { 52 };
+-static const int gpio40_pins[] = { 53 };
+-static const int gpio41_pins[] = { 54 };
+-static const int gpio42_pins[] = { 55 };
+-static const int gpio43_pins[] = { 56 };
+-static const int gpio44_pins[] = { 57 };
+-static const int gpio45_pins[] = { 58 };
+-static const int gpio46_pins[] = { 59 };
+-static const int pcie_reset0_pins[] = { 61 };
+-static const int pcie_reset1_pins[] = { 62 };
+-static const int pcie_reset2_pins[] = { 63 };
+-
+-static const struct pingroup airoha_pinctrl_groups[] = {
+-      PINCTRL_PIN_GROUP(pon),
+-      PINCTRL_PIN_GROUP(pon_tod_1pps),
+-      PINCTRL_PIN_GROUP(gsw_tod_1pps),
+-      PINCTRL_PIN_GROUP(sipo),
+-      PINCTRL_PIN_GROUP(sipo_rclk),
+-      PINCTRL_PIN_GROUP(mdio),
+-      PINCTRL_PIN_GROUP(uart2),
+-      PINCTRL_PIN_GROUP(uart2_cts_rts),
+-      PINCTRL_PIN_GROUP(hsuart),
+-      PINCTRL_PIN_GROUP(hsuart_cts_rts),
+-      PINCTRL_PIN_GROUP(uart4),
+-      PINCTRL_PIN_GROUP(uart5),
+-      PINCTRL_PIN_GROUP(i2c0),
+-      PINCTRL_PIN_GROUP(i2c1),
+-      PINCTRL_PIN_GROUP(jtag_udi),
+-      PINCTRL_PIN_GROUP(jtag_dfd),
+-      PINCTRL_PIN_GROUP(i2s),
+-      PINCTRL_PIN_GROUP(pcm1),
+-      PINCTRL_PIN_GROUP(pcm2),
+-      PINCTRL_PIN_GROUP(spi),
+-      PINCTRL_PIN_GROUP(spi_quad),
+-      PINCTRL_PIN_GROUP(spi_cs1),
+-      PINCTRL_PIN_GROUP(pcm_spi),
+-      PINCTRL_PIN_GROUP(pcm_spi_int),
+-      PINCTRL_PIN_GROUP(pcm_spi_rst),
+-      PINCTRL_PIN_GROUP(pcm_spi_cs1),
+-      PINCTRL_PIN_GROUP(pcm_spi_cs2_p128),
+-      PINCTRL_PIN_GROUP(pcm_spi_cs2_p156),
+-      PINCTRL_PIN_GROUP(pcm_spi_cs2),
+-      PINCTRL_PIN_GROUP(pcm_spi_cs3),
+-      PINCTRL_PIN_GROUP(pcm_spi_cs4),
+-      PINCTRL_PIN_GROUP(emmc),
+-      PINCTRL_PIN_GROUP(pnand),
+-      PINCTRL_PIN_GROUP(gpio0),
+-      PINCTRL_PIN_GROUP(gpio1),
+-      PINCTRL_PIN_GROUP(gpio2),
+-      PINCTRL_PIN_GROUP(gpio3),
+-      PINCTRL_PIN_GROUP(gpio4),
+-      PINCTRL_PIN_GROUP(gpio5),
+-      PINCTRL_PIN_GROUP(gpio6),
+-      PINCTRL_PIN_GROUP(gpio7),
+-      PINCTRL_PIN_GROUP(gpio8),
+-      PINCTRL_PIN_GROUP(gpio9),
+-      PINCTRL_PIN_GROUP(gpio10),
+-      PINCTRL_PIN_GROUP(gpio11),
+-      PINCTRL_PIN_GROUP(gpio12),
+-      PINCTRL_PIN_GROUP(gpio13),
+-      PINCTRL_PIN_GROUP(gpio14),
+-      PINCTRL_PIN_GROUP(gpio15),
+-      PINCTRL_PIN_GROUP(gpio16),
+-      PINCTRL_PIN_GROUP(gpio17),
+-      PINCTRL_PIN_GROUP(gpio18),
+-      PINCTRL_PIN_GROUP(gpio19),
+-      PINCTRL_PIN_GROUP(gpio20),
+-      PINCTRL_PIN_GROUP(gpio21),
+-      PINCTRL_PIN_GROUP(gpio22),
+-      PINCTRL_PIN_GROUP(gpio23),
+-      PINCTRL_PIN_GROUP(gpio24),
+-      PINCTRL_PIN_GROUP(gpio25),
+-      PINCTRL_PIN_GROUP(gpio26),
+-      PINCTRL_PIN_GROUP(gpio27),
+-      PINCTRL_PIN_GROUP(gpio28),
+-      PINCTRL_PIN_GROUP(gpio29),
+-      PINCTRL_PIN_GROUP(gpio30),
+-      PINCTRL_PIN_GROUP(gpio31),
+-      PINCTRL_PIN_GROUP(gpio33),
+-      PINCTRL_PIN_GROUP(gpio34),
+-      PINCTRL_PIN_GROUP(gpio35),
+-      PINCTRL_PIN_GROUP(gpio36),
+-      PINCTRL_PIN_GROUP(gpio37),
+-      PINCTRL_PIN_GROUP(gpio38),
+-      PINCTRL_PIN_GROUP(gpio39),
+-      PINCTRL_PIN_GROUP(gpio40),
+-      PINCTRL_PIN_GROUP(gpio41),
+-      PINCTRL_PIN_GROUP(gpio42),
+-      PINCTRL_PIN_GROUP(gpio43),
+-      PINCTRL_PIN_GROUP(gpio44),
+-      PINCTRL_PIN_GROUP(gpio45),
+-      PINCTRL_PIN_GROUP(gpio46),
+-      PINCTRL_PIN_GROUP(pcie_reset0),
+-      PINCTRL_PIN_GROUP(pcie_reset1),
+-      PINCTRL_PIN_GROUP(pcie_reset2),
++static const int en7581_pon_pins[] = { 49, 50, 51, 52, 53, 54 };
++static const int en7581_pon_tod_1pps_pins[] = { 46 };
++static const int en7581_gsw_tod_1pps_pins[] = { 46 };
++static const int en7581_sipo_pins[] = { 16, 17 };
++static const int en7581_sipo_rclk_pins[] = { 16, 17, 43 };
++static const int en7581_mdio_pins[] = { 14, 15 };
++static const int en7581_uart2_pins[] = { 48, 55 };
++static const int en7581_uart2_cts_rts_pins[] = { 46, 47 };
++static const int en7581_hsuart_pins[] = { 28, 29 };
++static const int en7581_hsuart_cts_rts_pins[] = { 26, 27 };
++static const int en7581_uart4_pins[] = { 38, 39 };
++static const int en7581_uart5_pins[] = { 18, 19 };
++static const int en7581_i2c0_pins[] = { 2, 3 };
++static const int en7581_i2c1_pins[] = { 14, 15 };
++static const int en7581_jtag_udi_pins[] = { 16, 17, 18, 19, 20 };
++static const int en7581_jtag_dfd_pins[] = { 16, 17, 18, 19, 20 };
++static const int en7581_i2s_pins[] = { 26, 27, 28, 29 };
++static const int en7581_pcm1_pins[] = { 22, 23, 24, 25 };
++static const int en7581_pcm2_pins[] = { 18, 19, 20, 21 };
++static const int en7581_spi_quad_pins[] = { 32, 33 };
++static const int en7581_spi_pins[] = { 4, 5, 6, 7 };
++static const int en7581_spi_cs1_pins[] = { 34 };
++static const int en7581_pcm_spi_pins[] = { 18, 19, 20, 21, 22, 23, 24, 25 };
++static const int en7581_pcm_spi_int_pins[] = { 14 };
++static const int en7581_pcm_spi_rst_pins[] = { 15 };
++static const int en7581_pcm_spi_cs1_pins[] = { 43 };
++static const int en7581_pcm_spi_cs2_pins[] = { 40 };
++static const int en7581_pcm_spi_cs2_p128_pins[] = { 40 };
++static const int en7581_pcm_spi_cs2_p156_pins[] = { 40 };
++static const int en7581_pcm_spi_cs3_pins[] = { 41 };
++static const int en7581_pcm_spi_cs4_pins[] = { 42 };
++static const int en7581_emmc_pins[] = { 4, 5, 6, 30, 31, 32, 33, 34, 35, 36, 37 };
++static const int en7581_pnand_pins[] = { 4, 5, 6, 7, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42 };
++static const int en7581_gpio0_pins[] = { 13 };
++static const int en7581_gpio1_pins[] = { 14 };
++static const int en7581_gpio2_pins[] = { 15 };
++static const int en7581_gpio3_pins[] = { 16 };
++static const int en7581_gpio4_pins[] = { 17 };
++static const int en7581_gpio5_pins[] = { 18 };
++static const int en7581_gpio6_pins[] = { 19 };
++static const int en7581_gpio7_pins[] = { 20 };
++static const int en7581_gpio8_pins[] = { 21 };
++static const int en7581_gpio9_pins[] = { 22 };
++static const int en7581_gpio10_pins[] = { 23 };
++static const int en7581_gpio11_pins[] = { 24 };
++static const int en7581_gpio12_pins[] = { 25 };
++static const int en7581_gpio13_pins[] = { 26 };
++static const int en7581_gpio14_pins[] = { 27 };
++static const int en7581_gpio15_pins[] = { 28 };
++static const int en7581_gpio16_pins[] = { 29 };
++static const int en7581_gpio17_pins[] = { 30 };
++static const int en7581_gpio18_pins[] = { 31 };
++static const int en7581_gpio19_pins[] = { 32 };
++static const int en7581_gpio20_pins[] = { 33 };
++static const int en7581_gpio21_pins[] = { 34 };
++static const int en7581_gpio22_pins[] = { 35 };
++static const int en7581_gpio23_pins[] = { 36 };
++static const int en7581_gpio24_pins[] = { 37 };
++static const int en7581_gpio25_pins[] = { 38 };
++static const int en7581_gpio26_pins[] = { 39 };
++static const int en7581_gpio27_pins[] = { 40 };
++static const int en7581_gpio28_pins[] = { 41 };
++static const int en7581_gpio29_pins[] = { 42 };
++static const int en7581_gpio30_pins[] = { 43 };
++static const int en7581_gpio31_pins[] = { 44 };
++static const int en7581_gpio33_pins[] = { 46 };
++static const int en7581_gpio34_pins[] = { 47 };
++static const int en7581_gpio35_pins[] = { 48 };
++static const int en7581_gpio36_pins[] = { 49 };
++static const int en7581_gpio37_pins[] = { 50 };
++static const int en7581_gpio38_pins[] = { 51 };
++static const int en7581_gpio39_pins[] = { 52 };
++static const int en7581_gpio40_pins[] = { 53 };
++static const int en7581_gpio41_pins[] = { 54 };
++static const int en7581_gpio42_pins[] = { 55 };
++static const int en7581_gpio43_pins[] = { 56 };
++static const int en7581_gpio44_pins[] = { 57 };
++static const int en7581_gpio45_pins[] = { 58 };
++static const int en7581_gpio46_pins[] = { 59 };
++static const int en7581_pcie_reset0_pins[] = { 61 };
++static const int en7581_pcie_reset1_pins[] = { 62 };
++static const int en7581_pcie_reset2_pins[] = { 63 };
++
++static const struct pingroup en7581_pinctrl_groups[] = {
++      PINCTRL_PIN_GROUP("pon", en7581_pon),
++      PINCTRL_PIN_GROUP("pon_tod_1pps", en7581_pon_tod_1pps),
++      PINCTRL_PIN_GROUP("gsw_tod_1pps", en7581_gsw_tod_1pps),
++      PINCTRL_PIN_GROUP("sipo", en7581_sipo),
++      PINCTRL_PIN_GROUP("sipo_rclk", en7581_sipo_rclk),
++      PINCTRL_PIN_GROUP("mdio", en7581_mdio),
++      PINCTRL_PIN_GROUP("uart2", en7581_uart2),
++      PINCTRL_PIN_GROUP("uart2_cts_rts", en7581_uart2_cts_rts),
++      PINCTRL_PIN_GROUP("hsuart", en7581_hsuart),
++      PINCTRL_PIN_GROUP("hsuart_cts_rts", en7581_hsuart_cts_rts),
++      PINCTRL_PIN_GROUP("uart4", en7581_uart4),
++      PINCTRL_PIN_GROUP("uart5", en7581_uart5),
++      PINCTRL_PIN_GROUP("i2c0", en7581_i2c0),
++      PINCTRL_PIN_GROUP("i2c1", en7581_i2c1),
++      PINCTRL_PIN_GROUP("jtag_udi", en7581_jtag_udi),
++      PINCTRL_PIN_GROUP("jtag_dfd", en7581_jtag_dfd),
++      PINCTRL_PIN_GROUP("i2s", en7581_i2s),
++      PINCTRL_PIN_GROUP("pcm1", en7581_pcm1),
++      PINCTRL_PIN_GROUP("pcm2", en7581_pcm2),
++      PINCTRL_PIN_GROUP("spi", en7581_spi),
++      PINCTRL_PIN_GROUP("spi_quad", en7581_spi_quad),
++      PINCTRL_PIN_GROUP("spi_cs1", en7581_spi_cs1),
++      PINCTRL_PIN_GROUP("pcm_spi", en7581_pcm_spi),
++      PINCTRL_PIN_GROUP("pcm_spi_int", en7581_pcm_spi_int),
++      PINCTRL_PIN_GROUP("pcm_spi_rst", en7581_pcm_spi_rst),
++      PINCTRL_PIN_GROUP("pcm_spi_cs1", en7581_pcm_spi_cs1),
++      PINCTRL_PIN_GROUP("pcm_spi_cs2_p128", en7581_pcm_spi_cs2_p128),
++      PINCTRL_PIN_GROUP("pcm_spi_cs2_p156", en7581_pcm_spi_cs2_p156),
++      PINCTRL_PIN_GROUP("pcm_spi_cs2", en7581_pcm_spi_cs2),
++      PINCTRL_PIN_GROUP("pcm_spi_cs3", en7581_pcm_spi_cs3),
++      PINCTRL_PIN_GROUP("pcm_spi_cs4", en7581_pcm_spi_cs4),
++      PINCTRL_PIN_GROUP("emmc", en7581_emmc),
++      PINCTRL_PIN_GROUP("pnand", en7581_pnand),
++      PINCTRL_PIN_GROUP("gpio0", en7581_gpio0),
++      PINCTRL_PIN_GROUP("gpio1", en7581_gpio1),
++      PINCTRL_PIN_GROUP("gpio2", en7581_gpio2),
++      PINCTRL_PIN_GROUP("gpio3", en7581_gpio3),
++      PINCTRL_PIN_GROUP("gpio4", en7581_gpio4),
++      PINCTRL_PIN_GROUP("gpio5", en7581_gpio5),
++      PINCTRL_PIN_GROUP("gpio6", en7581_gpio6),
++      PINCTRL_PIN_GROUP("gpio7", en7581_gpio7),
++      PINCTRL_PIN_GROUP("gpio8", en7581_gpio8),
++      PINCTRL_PIN_GROUP("gpio9", en7581_gpio9),
++      PINCTRL_PIN_GROUP("gpio10", en7581_gpio10),
++      PINCTRL_PIN_GROUP("gpio11", en7581_gpio11),
++      PINCTRL_PIN_GROUP("gpio12", en7581_gpio12),
++      PINCTRL_PIN_GROUP("gpio13", en7581_gpio13),
++      PINCTRL_PIN_GROUP("gpio14", en7581_gpio14),
++      PINCTRL_PIN_GROUP("gpio15", en7581_gpio15),
++      PINCTRL_PIN_GROUP("gpio16", en7581_gpio16),
++      PINCTRL_PIN_GROUP("gpio17", en7581_gpio17),
++      PINCTRL_PIN_GROUP("gpio18", en7581_gpio18),
++      PINCTRL_PIN_GROUP("gpio19", en7581_gpio19),
++      PINCTRL_PIN_GROUP("gpio20", en7581_gpio20),
++      PINCTRL_PIN_GROUP("gpio21", en7581_gpio21),
++      PINCTRL_PIN_GROUP("gpio22", en7581_gpio22),
++      PINCTRL_PIN_GROUP("gpio23", en7581_gpio23),
++      PINCTRL_PIN_GROUP("gpio24", en7581_gpio24),
++      PINCTRL_PIN_GROUP("gpio25", en7581_gpio25),
++      PINCTRL_PIN_GROUP("gpio26", en7581_gpio26),
++      PINCTRL_PIN_GROUP("gpio27", en7581_gpio27),
++      PINCTRL_PIN_GROUP("gpio28", en7581_gpio28),
++      PINCTRL_PIN_GROUP("gpio29", en7581_gpio29),
++      PINCTRL_PIN_GROUP("gpio30", en7581_gpio30),
++      PINCTRL_PIN_GROUP("gpio31", en7581_gpio31),
++      PINCTRL_PIN_GROUP("gpio33", en7581_gpio33),
++      PINCTRL_PIN_GROUP("gpio34", en7581_gpio34),
++      PINCTRL_PIN_GROUP("gpio35", en7581_gpio35),
++      PINCTRL_PIN_GROUP("gpio36", en7581_gpio36),
++      PINCTRL_PIN_GROUP("gpio37", en7581_gpio37),
++      PINCTRL_PIN_GROUP("gpio38", en7581_gpio38),
++      PINCTRL_PIN_GROUP("gpio39", en7581_gpio39),
++      PINCTRL_PIN_GROUP("gpio40", en7581_gpio40),
++      PINCTRL_PIN_GROUP("gpio41", en7581_gpio41),
++      PINCTRL_PIN_GROUP("gpio42", en7581_gpio42),
++      PINCTRL_PIN_GROUP("gpio43", en7581_gpio43),
++      PINCTRL_PIN_GROUP("gpio44", en7581_gpio44),
++      PINCTRL_PIN_GROUP("gpio45", en7581_gpio45),
++      PINCTRL_PIN_GROUP("gpio46", en7581_gpio46),
++      PINCTRL_PIN_GROUP("pcie_reset0", en7581_pcie_reset0),
++      PINCTRL_PIN_GROUP("pcie_reset1", en7581_pcie_reset1),
++      PINCTRL_PIN_GROUP("pcie_reset2", en7581_pcie_reset2),
+ };
+ static const char *const pon_groups[] = { "pon" };
+@@ -1960,33 +1990,33 @@ static const struct airoha_pinctrl_func_
+       },
+ };
+-static const struct airoha_pinctrl_func airoha_pinctrl_funcs[] = {
+-      PINCTRL_FUNC_DESC(pon),
+-      PINCTRL_FUNC_DESC(tod_1pps),
+-      PINCTRL_FUNC_DESC(sipo),
+-      PINCTRL_FUNC_DESC(mdio),
+-      PINCTRL_FUNC_DESC(uart),
+-      PINCTRL_FUNC_DESC(i2c),
+-      PINCTRL_FUNC_DESC(jtag),
+-      PINCTRL_FUNC_DESC(pcm),
+-      PINCTRL_FUNC_DESC(spi),
+-      PINCTRL_FUNC_DESC(pcm_spi),
+-      PINCTRL_FUNC_DESC(i2s),
+-      PINCTRL_FUNC_DESC(emmc),
+-      PINCTRL_FUNC_DESC(pnand),
+-      PINCTRL_FUNC_DESC(pcie_reset),
+-      PINCTRL_FUNC_DESC(pwm),
+-      PINCTRL_FUNC_DESC(phy1_led0),
+-      PINCTRL_FUNC_DESC(phy2_led0),
+-      PINCTRL_FUNC_DESC(phy3_led0),
+-      PINCTRL_FUNC_DESC(phy4_led0),
+-      PINCTRL_FUNC_DESC(phy1_led1),
+-      PINCTRL_FUNC_DESC(phy2_led1),
+-      PINCTRL_FUNC_DESC(phy3_led1),
+-      PINCTRL_FUNC_DESC(phy4_led1),
++static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = {
++      PINCTRL_FUNC_DESC("pon", pon),
++      PINCTRL_FUNC_DESC("tod_1pps", tod_1pps),
++      PINCTRL_FUNC_DESC("sipo", sipo),
++      PINCTRL_FUNC_DESC("mdio", mdio),
++      PINCTRL_FUNC_DESC("uart", uart),
++      PINCTRL_FUNC_DESC("i2c", i2c),
++      PINCTRL_FUNC_DESC("jtag", jtag),
++      PINCTRL_FUNC_DESC("pcm", pcm),
++      PINCTRL_FUNC_DESC("spi", spi),
++      PINCTRL_FUNC_DESC("pcm_spi", pcm_spi),
++      PINCTRL_FUNC_DESC("i2s", i2s),
++      PINCTRL_FUNC_DESC("emmc", emmc),
++      PINCTRL_FUNC_DESC("pnand", pnand),
++      PINCTRL_FUNC_DESC("pcie_reset", pcie_reset),
++      PINCTRL_FUNC_DESC("pwm", pwm),
++      PINCTRL_FUNC_DESC("phy1_led0", phy1_led0),
++      PINCTRL_FUNC_DESC("phy2_led0", phy2_led0),
++      PINCTRL_FUNC_DESC("phy3_led0", phy3_led0),
++      PINCTRL_FUNC_DESC("phy4_led0", phy4_led0),
++      PINCTRL_FUNC_DESC("phy1_led1", phy1_led1),
++      PINCTRL_FUNC_DESC("phy2_led1", phy2_led1),
++      PINCTRL_FUNC_DESC("phy3_led1", phy3_led1),
++      PINCTRL_FUNC_DESC("phy4_led1", phy4_led1),
+ };
+-static const struct airoha_pinctrl_conf airoha_pinctrl_pullup_conf[] = {
++static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK),
+       PINCTRL_CONF_DESC(2, REG_I2C_SDA_PU, I2C_SDA_PU_MASK),
+@@ -2047,7 +2077,7 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK),
+ };
+-static const struct airoha_pinctrl_conf airoha_pinctrl_pulldown_conf[] = {
++static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK),
+       PINCTRL_CONF_DESC(2, REG_I2C_SDA_PD, I2C_SDA_PD_MASK),
+@@ -2108,7 +2138,7 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK),
+ };
+-static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e2_conf[] = {
++static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK),
+       PINCTRL_CONF_DESC(2, REG_I2C_SDA_E2, I2C_SDA_E2_MASK),
+@@ -2169,7 +2199,7 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK),
+ };
+-static const struct airoha_pinctrl_conf airoha_pinctrl_drive_e4_conf[] = {
++static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK),
+       PINCTRL_CONF_DESC(2, REG_I2C_SDA_E4, I2C_SDA_E4_MASK),
+@@ -2230,7 +2260,7 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK),
+ };
+-static const struct airoha_pinctrl_conf airoha_pinctrl_pcie_rst_od_conf[] = {
++static const struct airoha_pinctrl_conf en7581_pinctrl_pcie_rst_od_conf[] = {
+       PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK),
+       PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK),
+       PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK),
+@@ -2552,12 +2582,17 @@ airoha_pinctrl_get_conf_reg(const struct
+ }
+ static int airoha_pinctrl_get_conf(struct airoha_pinctrl *pinctrl,
+-                                 const struct airoha_pinctrl_conf *conf,
+-                                 int conf_size, int pin, u32 *val)
++                                 enum airoha_pinctrl_confs_type conf_type,
++                                 int pin, u32 *val)
+ {
++      const struct airoha_pinctrl_confs_info *confs_info;
+       const struct airoha_pinctrl_reg *reg;
+-      reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin);
++      confs_info = &pinctrl->confs_info[conf_type];
++
++      reg = airoha_pinctrl_get_conf_reg(confs_info->confs,
++                                        confs_info->num_confs,
++                                        pin);
+       if (!reg)
+               return -EINVAL;
+@@ -2570,12 +2605,17 @@ static int airoha_pinctrl_get_conf(struc
+ }
+ static int airoha_pinctrl_set_conf(struct airoha_pinctrl *pinctrl,
+-                                 const struct airoha_pinctrl_conf *conf,
+-                                 int conf_size, int pin, u32 val)
++                                 enum airoha_pinctrl_confs_type conf_type,
++                                 int pin, u32 val)
+ {
++      const struct airoha_pinctrl_confs_info *confs_info;
+       const struct airoha_pinctrl_reg *reg = NULL;
+-      reg = airoha_pinctrl_get_conf_reg(conf, conf_size, pin);
++      confs_info = &pinctrl->confs_info[conf_type];
++
++      reg = airoha_pinctrl_get_conf_reg(confs_info->confs,
++                                        confs_info->num_confs,
++                                        pin);
+       if (!reg)
+               return -EINVAL;
+@@ -2588,44 +2628,34 @@ static int airoha_pinctrl_set_conf(struc
+ }
+ #define airoha_pinctrl_get_pullup_conf(pinctrl, pin, val)                     \
+-      airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pullup_conf,          \
+-                              ARRAY_SIZE(airoha_pinctrl_pullup_conf),         \
++      airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP,         \
+                               (pin), (val))
+ #define airoha_pinctrl_get_pulldown_conf(pinctrl, pin, val)                   \
+-      airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pulldown_conf,        \
+-                              ARRAY_SIZE(airoha_pinctrl_pulldown_conf),       \
++      airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLDOWN,       \
+                               (pin), (val))
+ #define airoha_pinctrl_get_drive_e2_conf(pinctrl, pin, val)                   \
+-      airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e2_conf,        \
+-                              ARRAY_SIZE(airoha_pinctrl_drive_e2_conf),       \
++      airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E2,       \
+                               (pin), (val))
+ #define airoha_pinctrl_get_drive_e4_conf(pinctrl, pin, val)                   \
+-      airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_drive_e4_conf,        \
+-                              ARRAY_SIZE(airoha_pinctrl_drive_e4_conf),       \
++      airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E4,       \
+                               (pin), (val))
+ #define airoha_pinctrl_get_pcie_rst_od_conf(pinctrl, pin, val)                        \
+-      airoha_pinctrl_get_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf,     \
+-                              ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf),    \
++      airoha_pinctrl_get_conf((pinctrl), AIROHA_PINCTRL_CONFS_PCIE_RST_OD,    \
+                               (pin), (val))
+ #define airoha_pinctrl_set_pullup_conf(pinctrl, pin, val)                     \
+-      airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pullup_conf,          \
+-                              ARRAY_SIZE(airoha_pinctrl_pullup_conf),         \
++      airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLUP,         \
+                               (pin), (val))
+ #define airoha_pinctrl_set_pulldown_conf(pinctrl, pin, val)                   \
+-      airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pulldown_conf,        \
+-                              ARRAY_SIZE(airoha_pinctrl_pulldown_conf),       \
++      airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PULLDOWN,       \
+                               (pin), (val))
+ #define airoha_pinctrl_set_drive_e2_conf(pinctrl, pin, val)                   \
+-      airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e2_conf,        \
+-                              ARRAY_SIZE(airoha_pinctrl_drive_e2_conf),       \
++      airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E2,       \
+                               (pin), (val))
+ #define airoha_pinctrl_set_drive_e4_conf(pinctrl, pin, val)                   \
+-      airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_drive_e4_conf,        \
+-                              ARRAY_SIZE(airoha_pinctrl_drive_e4_conf),       \
++      airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_DRIVE_E4,       \
+                               (pin), (val))
+ #define airoha_pinctrl_set_pcie_rst_od_conf(pinctrl, pin, val)                        \
+-      airoha_pinctrl_set_conf((pinctrl), airoha_pinctrl_pcie_rst_od_conf,     \
+-                              ARRAY_SIZE(airoha_pinctrl_pcie_rst_od_conf),    \
++      airoha_pinctrl_set_conf((pinctrl), AIROHA_PINCTRL_CONFS_PCIE_RST_OD,    \
+                               (pin), (val))
+ static int airoha_pinconf_get_direction(struct pinctrl_dev *pctrl_dev, u32 p)
+@@ -2804,12 +2834,13 @@ static int airoha_pinconf_set(struct pin
+ static int airoha_pinconf_group_get(struct pinctrl_dev *pctrl_dev,
+                                   unsigned int group, unsigned long *config)
+ {
++      struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+       u32 cur_config = 0;
+       int i;
+-      for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) {
++      for (i = 0; i < pinctrl->grps[group].npins; i++) {
+               if (airoha_pinconf_get(pctrl_dev,
+-                                     airoha_pinctrl_groups[group].pins[i],
++                                     pinctrl->grps[group].pins[i],
+                                      config))
+                       return -ENOTSUPP;
+@@ -2826,13 +2857,14 @@ static int airoha_pinconf_group_set(stru
+                                   unsigned int group, unsigned long *configs,
+                                   unsigned int num_configs)
+ {
++      struct airoha_pinctrl *pinctrl = pinctrl_dev_get_drvdata(pctrl_dev);
+       int i;
+-      for (i = 0; i < airoha_pinctrl_groups[group].npins; i++) {
++      for (i = 0; i < pinctrl->grps[group].npins; i++) {
+               int err;
+               err = airoha_pinconf_set(pctrl_dev,
+-                                       airoha_pinctrl_groups[group].pins[i],
++                                       pinctrl->grps[group].pins[i],
+                                        configs, num_configs);
+               if (err)
+                       return err;
+@@ -2858,23 +2890,16 @@ static const struct pinctrl_ops airoha_p
+       .dt_free_map = pinconf_generic_dt_free_map,
+ };
+-static struct pinctrl_desc airoha_pinctrl_desc = {
+-      .name = KBUILD_MODNAME,
+-      .owner = THIS_MODULE,
+-      .pctlops = &airoha_pctlops,
+-      .pmxops = &airoha_pmxops,
+-      .confops = &airoha_confops,
+-      .pins = airoha_pinctrl_pins,
+-      .npins = ARRAY_SIZE(airoha_pinctrl_pins),
+-};
+-
+ static int airoha_pinctrl_probe(struct platform_device *pdev)
+ {
++      const struct airoha_pinctrl_match_data *data;
+       struct device *dev = &pdev->dev;
+       struct airoha_pinctrl *pinctrl;
+       struct regmap *map;
+       int err, i;
++      data = device_get_match_data(dev);
++
+       pinctrl = devm_kzalloc(dev, sizeof(*pinctrl), GFP_KERNEL);
+       if (!pinctrl)
+               return -ENOMEM;
+@@ -2889,14 +2914,23 @@ static int airoha_pinctrl_probe(struct p
+       pinctrl->chip_scu = map;
+-      err = devm_pinctrl_register_and_init(dev, &airoha_pinctrl_desc,
++      /* Init pinctrl desc struct */
++      pinctrl->desc.name = KBUILD_MODNAME;
++      pinctrl->desc.owner = THIS_MODULE,
++      pinctrl->desc.pctlops = &airoha_pctlops,
++      pinctrl->desc.pmxops = &airoha_pmxops,
++      pinctrl->desc.confops = &airoha_confops,
++      pinctrl->desc.pins = data->pins,
++      pinctrl->desc.npins = data->num_pins,
++
++      err = devm_pinctrl_register_and_init(dev, &pinctrl->desc,
+                                            pinctrl, &pinctrl->ctrl);
+       if (err)
+               return err;
+       /* build pin groups */
+-      for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_groups); i++) {
+-              const struct pingroup *grp = &airoha_pinctrl_groups[i];
++      for (i = 0; i < data->num_grps; i++) {
++              const struct pingroup *grp = &data->grps[i];
+               err = pinctrl_generic_add_group(pinctrl->ctrl, grp->name,
+                                               grp->pins, grp->npins,
+@@ -2909,10 +2943,10 @@ static int airoha_pinctrl_probe(struct p
+       }
+       /* build functions */
+-      for (i = 0; i < ARRAY_SIZE(airoha_pinctrl_funcs); i++) {
++      for (i = 0; i < data->num_funcs; i++) {
+               const struct airoha_pinctrl_func *func;
+-              func = &airoha_pinctrl_funcs[i];
++              func = &data->funcs[i];
+               err = pinmux_generic_add_function(pinctrl->ctrl,
+                                                 func->desc.func.name,
+                                                 func->desc.func.groups,
+@@ -2925,6 +2959,10 @@ static int airoha_pinctrl_probe(struct p
+               }
+       }
++      pinctrl->grps = data->grps;
++      pinctrl->funcs = data->funcs;
++      pinctrl->confs_info = data->confs_info;
++
+       err = pinctrl_enable(pinctrl->ctrl);
+       if (err)
+               return err;
+@@ -2933,8 +2971,39 @@ static int airoha_pinctrl_probe(struct p
+       return airoha_pinctrl_add_gpiochip(pinctrl, pdev);
+ }
++static const struct airoha_pinctrl_match_data en7581_pinctrl_match_data = {
++      .pins = en7581_pinctrl_pins,
++      .num_pins = ARRAY_SIZE(en7581_pinctrl_pins),
++      .grps = en7581_pinctrl_groups,
++      .num_grps = ARRAY_SIZE(en7581_pinctrl_groups),
++      .funcs = en7581_pinctrl_funcs,
++      .num_funcs = ARRAY_SIZE(en7581_pinctrl_funcs),
++      .confs_info = {
++              [AIROHA_PINCTRL_CONFS_PULLUP] = {
++                      .confs = en7581_pinctrl_pullup_conf,
++                      .num_confs = ARRAY_SIZE(en7581_pinctrl_pullup_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_PULLDOWN] = {
++                      .confs = en7581_pinctrl_pulldown_conf,
++                      .num_confs = ARRAY_SIZE(en7581_pinctrl_pulldown_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_DRIVE_E2] = {
++                      .confs = en7581_pinctrl_drive_e2_conf,
++                      .num_confs = ARRAY_SIZE(en7581_pinctrl_drive_e2_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_DRIVE_E4] = {
++                      .confs = en7581_pinctrl_drive_e4_conf,
++                      .num_confs = ARRAY_SIZE(en7581_pinctrl_drive_e4_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_PCIE_RST_OD] = {
++                      .confs = en7581_pinctrl_pcie_rst_od_conf,
++                      .num_confs = ARRAY_SIZE(en7581_pinctrl_pcie_rst_od_conf),
++              },
++      },
++};
++
+ static const struct of_device_id airoha_pinctrl_of_match[] = {
+-      { .compatible = "airoha,en7581-pinctrl" },
++      { .compatible = "airoha,en7581-pinctrl", .data = &en7581_pinctrl_match_data },
+       { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match);
diff --git a/target/linux/airoha/patches-6.12/120-03-pinctrl-airoha-convert-PHY-LED-GPIO-to-macro.patch b/target/linux/airoha/patches-6.12/120-03-pinctrl-airoha-convert-PHY-LED-GPIO-to-macro.patch
new file mode 100644 (file)
index 0000000..df1d966
--- /dev/null
@@ -0,0 +1,616 @@
+From ee980d96b6ecd385691f101e641f3e15513ce8c3 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sun, 25 May 2025 20:28:34 +0200
+Subject: [PATCH 3/5] pinctrl: airoha: convert PHY LED GPIO to macro
+
+PHY LED GPIO pinctrl struct definition is very similar across the
+different 4 PHY and 2 LED and it can be generelized to a macro.
+
+To reduce code size, convert them to a common macro.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-airoha.c | 570 ++++------------------
+ 1 file changed, 82 insertions(+), 488 deletions(-)
+
+--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c
++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
+@@ -1478,516 +1478,110 @@ static const struct airoha_pinctrl_func_
+       },
+ };
++#define AIROHA_PINCTRL_PHY_LED(gpio, mux_val, map_mask, map_val)      \
++      {                                                               \
++              .name = (gpio),                                         \
++              .regmap[0] = {                                          \
++                      AIROHA_FUNC_MUX,                                \
++                      REG_GPIO_2ND_I2C_MODE,                          \
++                      (mux_val),                                      \
++                      (mux_val),                                      \
++              },                                                      \
++              .regmap[1] = {                                          \
++                      AIROHA_FUNC_MUX,                                \
++                      REG_LAN_LED0_MAPPING,                           \
++                      (map_mask),                                     \
++                      (map_val),                                      \
++              },                                                      \
++              .regmap_size = 2,                                       \
++      }
++
+ static const struct airoha_pinctrl_func_group phy1_led0_func_group[] = {
+-      {
+-              .name = "gpio33",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED0_MODE_MASK,
+-                      GPIO_LAN0_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio34",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED0_MODE_MASK,
+-                      GPIO_LAN1_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio35",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED0_MODE_MASK,
+-                      GPIO_LAN2_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio42",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED0_MODE_MASK,
+-                      GPIO_LAN3_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)),
+ };
+ static const struct airoha_pinctrl_func_group phy2_led0_func_group[] = {
+-      {
+-              .name = "gpio33",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED0_MODE_MASK,
+-                      GPIO_LAN0_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio34",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED0_MODE_MASK,
+-                      GPIO_LAN1_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio35",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED0_MODE_MASK,
+-                      GPIO_LAN2_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio42",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED0_MODE_MASK,
+-                      GPIO_LAN3_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)),
+ };
+ static const struct airoha_pinctrl_func_group phy3_led0_func_group[] = {
+-      {
+-              .name = "gpio33",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED0_MODE_MASK,
+-                      GPIO_LAN0_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio34",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED0_MODE_MASK,
+-                      GPIO_LAN1_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio35",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED0_MODE_MASK,
+-                      GPIO_LAN2_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio42",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED0_MODE_MASK,
+-                      GPIO_LAN3_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
+ };
+ static const struct airoha_pinctrl_func_group phy4_led0_func_group[] = {
+-      {
+-              .name = "gpio33",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED0_MODE_MASK,
+-                      GPIO_LAN0_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio34",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED0_MODE_MASK,
+-                      GPIO_LAN1_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio35",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED0_MODE_MASK,
+-                      GPIO_LAN2_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio42",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED0_MODE_MASK,
+-                      GPIO_LAN3_LED0_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED0_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(3)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(3)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(3)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(3)),
+ };
+ static const struct airoha_pinctrl_func_group phy1_led1_func_group[] = {
+-      {
+-              .name = "gpio43",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED1_MODE_MASK,
+-                      GPIO_LAN0_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio44",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED1_MODE_MASK,
+-                      GPIO_LAN1_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio45",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED1_MODE_MASK,
+-                      GPIO_LAN2_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio46",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED1_MODE_MASK,
+-                      GPIO_LAN3_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(0)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)),
+ };
+ static const struct airoha_pinctrl_func_group phy2_led1_func_group[] = {
+-      {
+-              .name = "gpio43",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED1_MODE_MASK,
+-                      GPIO_LAN0_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio44",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED1_MODE_MASK,
+-                      GPIO_LAN1_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio45",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED1_MODE_MASK,
+-                      GPIO_LAN2_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio46",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED1_MODE_MASK,
+-                      GPIO_LAN3_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(1)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)),
+ };
+ static const struct airoha_pinctrl_func_group phy3_led1_func_group[] = {
+-      {
+-              .name = "gpio43",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED1_MODE_MASK,
+-                      GPIO_LAN0_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio44",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED1_MODE_MASK,
+-                      GPIO_LAN1_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio45",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED1_MODE_MASK,
+-                      GPIO_LAN2_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio46",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED1_MODE_MASK,
+-                      GPIO_LAN3_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(2)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
+ };
+ static const struct airoha_pinctrl_func_group phy4_led1_func_group[] = {
+-      {
+-              .name = "gpio43",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN0_LED1_MODE_MASK,
+-                      GPIO_LAN0_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN0_LED_MAPPING_MASK,
+-                      LAN0_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio44",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN1_LED1_MODE_MASK,
+-                      GPIO_LAN1_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN1_LED_MAPPING_MASK,
+-                      LAN1_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio45",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN2_LED1_MODE_MASK,
+-                      GPIO_LAN2_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN2_LED_MAPPING_MASK,
+-                      LAN2_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      }, {
+-              .name = "gpio46",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_GPIO_2ND_I2C_MODE,
+-                      GPIO_LAN3_LED1_MODE_MASK,
+-                      GPIO_LAN3_LED1_MODE_MASK
+-              },
+-              .regmap[1] = {
+-                      AIROHA_FUNC_MUX,
+-                      REG_LAN_LED1_MAPPING,
+-                      LAN3_LED_MAPPING_MASK,
+-                      LAN3_PHY_LED_MAP(3)
+-              },
+-              .regmap_size = 2,
+-      },
++      AIROHA_PINCTRL_PHY_LED("gpio33", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio34", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio35", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio42", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
+ };
+ static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = {
diff --git a/target/linux/airoha/patches-6.12/120-04-pinctrl-airoha-convert-PWM-GPIO-to-macro.patch b/target/linux/airoha/patches-6.12/120-04-pinctrl-airoha-convert-PWM-GPIO-to-macro.patch
new file mode 100644 (file)
index 0000000..e541cdd
--- /dev/null
@@ -0,0 +1,491 @@
+From 83c79d127c610063e1b86c3f7f8d5e0145ffe9c6 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sun, 25 May 2025 20:43:47 +0200
+Subject: [PATCH 4/5] pinctrl: airoha: convert PWM GPIO to macro
+
+The PWM GPIO struct definition follow the same pattern for every GPIO
+pin hence it can be converted to a macro.
+
+Create 2 macro one for normal mux and one for ext mux and convert all
+the entry to these new macro to reduce code size.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-airoha.c | 465 ++++------------------
+ 1 file changed, 68 insertions(+), 397 deletions(-)
+
+--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c
++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
+@@ -1078,404 +1078,75 @@ static const struct airoha_pinctrl_func_
+ };
+ /* PWM */
++#define AIROHA_PINCTRL_PWM(gpio, mux_val)             \
++      {                                               \
++              .name = (gpio),                         \
++              .regmap[0] = {                          \
++                      AIROHA_FUNC_PWM_MUX,            \
++                      REG_GPIO_FLASH_MODE_CFG,        \
++                      (mux_val),                      \
++                      (mux_val)                       \
++              },                                      \
++              .regmap_size = 1,                       \
++      }                                               \
++
++#define AIROHA_PINCTRL_PWM_EXT(gpio, mux_val)         \
++      {                                               \
++              .name = (gpio),                         \
++              .regmap[0] = {                          \
++                      AIROHA_FUNC_PWM_EXT_MUX,        \
++                      REG_GPIO_FLASH_MODE_CFG_EXT,    \
++                      (mux_val),                      \
++                      (mux_val)                       \
++              },                                      \
++              .regmap_size = 1,                       \
++      }                                               \
++
+ static const struct airoha_pinctrl_func_group pwm_func_group[] = {
+-      {
+-              .name = "gpio0",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO0_FLASH_MODE_CFG,
+-                      GPIO0_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio1",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO1_FLASH_MODE_CFG,
+-                      GPIO1_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio2",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO2_FLASH_MODE_CFG,
+-                      GPIO2_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio3",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO3_FLASH_MODE_CFG,
+-                      GPIO3_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio4",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO4_FLASH_MODE_CFG,
+-                      GPIO4_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio5",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO5_FLASH_MODE_CFG,
+-                      GPIO5_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio6",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO6_FLASH_MODE_CFG,
+-                      GPIO6_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio7",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO7_FLASH_MODE_CFG,
+-                      GPIO7_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio8",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO8_FLASH_MODE_CFG,
+-                      GPIO8_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio9",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO9_FLASH_MODE_CFG,
+-                      GPIO9_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio10",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO10_FLASH_MODE_CFG,
+-                      GPIO10_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio11",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO11_FLASH_MODE_CFG,
+-                      GPIO11_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio12",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO12_FLASH_MODE_CFG,
+-                      GPIO12_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio13",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO13_FLASH_MODE_CFG,
+-                      GPIO13_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio14",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO14_FLASH_MODE_CFG,
+-                      GPIO14_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio15",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG,
+-                      GPIO15_FLASH_MODE_CFG,
+-                      GPIO15_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio16",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO16_FLASH_MODE_CFG,
+-                      GPIO16_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio17",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO17_FLASH_MODE_CFG,
+-                      GPIO17_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio18",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO18_FLASH_MODE_CFG,
+-                      GPIO18_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio19",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO19_FLASH_MODE_CFG,
+-                      GPIO19_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio20",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO20_FLASH_MODE_CFG,
+-                      GPIO20_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio21",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO21_FLASH_MODE_CFG,
+-                      GPIO21_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio22",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO22_FLASH_MODE_CFG,
+-                      GPIO22_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio23",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO23_FLASH_MODE_CFG,
+-                      GPIO23_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio24",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO24_FLASH_MODE_CFG,
+-                      GPIO24_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio25",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO25_FLASH_MODE_CFG,
+-                      GPIO25_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio26",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO26_FLASH_MODE_CFG,
+-                      GPIO26_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio27",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO27_FLASH_MODE_CFG,
+-                      GPIO27_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio28",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO28_FLASH_MODE_CFG,
+-                      GPIO28_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio29",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO29_FLASH_MODE_CFG,
+-                      GPIO29_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio30",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO30_FLASH_MODE_CFG,
+-                      GPIO30_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio31",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO31_FLASH_MODE_CFG,
+-                      GPIO31_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio36",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO36_FLASH_MODE_CFG,
+-                      GPIO36_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio37",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO37_FLASH_MODE_CFG,
+-                      GPIO37_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio38",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO38_FLASH_MODE_CFG,
+-                      GPIO38_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio39",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO39_FLASH_MODE_CFG,
+-                      GPIO39_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio40",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO40_FLASH_MODE_CFG,
+-                      GPIO40_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio41",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO41_FLASH_MODE_CFG,
+-                      GPIO41_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio42",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO42_FLASH_MODE_CFG,
+-                      GPIO42_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio43",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO43_FLASH_MODE_CFG,
+-                      GPIO43_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio44",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO44_FLASH_MODE_CFG,
+-                      GPIO44_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio45",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO45_FLASH_MODE_CFG,
+-                      GPIO45_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio46",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO46_FLASH_MODE_CFG,
+-                      GPIO46_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      }, {
+-              .name = "gpio47",
+-              .regmap[0] = {
+-                      AIROHA_FUNC_PWM_EXT_MUX,
+-                      REG_GPIO_FLASH_MODE_CFG_EXT,
+-                      GPIO47_FLASH_MODE_CFG,
+-                      GPIO47_FLASH_MODE_CFG
+-              },
+-              .regmap_size = 1,
+-      },
++      AIROHA_PINCTRL_PWM("gpio0", GPIO0_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio1", GPIO1_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio2", GPIO2_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio3", GPIO3_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio4", GPIO4_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio5", GPIO5_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio6", GPIO6_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio7", GPIO7_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio8", GPIO8_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio9", GPIO9_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio10", GPIO10_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio11", GPIO11_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio12", GPIO12_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio13", GPIO13_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio14", GPIO14_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM("gpio15", GPIO15_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio16", GPIO16_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio17", GPIO17_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio18", GPIO18_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio19", GPIO19_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio20", GPIO20_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio21", GPIO21_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio22", GPIO22_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio23", GPIO23_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio24", GPIO24_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio25", GPIO25_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio26", GPIO26_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio27", GPIO27_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio28", GPIO28_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio29", GPIO29_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio30", GPIO30_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio31", GPIO31_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio36", GPIO36_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio37", GPIO37_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio38", GPIO38_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio39", GPIO39_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio40", GPIO40_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio41", GPIO41_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio42", GPIO42_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio43", GPIO43_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio44", GPIO44_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio45", GPIO45_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio46", GPIO46_FLASH_MODE_CFG),
++      AIROHA_PINCTRL_PWM_EXT("gpio47", GPIO47_FLASH_MODE_CFG),
+ };
+ #define AIROHA_PINCTRL_PHY_LED(gpio, mux_val, map_mask, map_val)      \
diff --git a/target/linux/airoha/patches-6.12/120-05-pinctrl-airoha-add-support-for-Airoha-AN7583-PINs.patch b/target/linux/airoha/patches-6.12/120-05-pinctrl-airoha-add-support-for-Airoha-AN7583-PINs.patch
new file mode 100644 (file)
index 0000000..37d3b29
--- /dev/null
@@ -0,0 +1,919 @@
+From cc92581b44cc3a6821c540ddbe27d4c009a7d312 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sun, 25 May 2025 21:32:25 +0200
+Subject: [PATCH 5/5] pinctrl: airoha: add support for Airoha AN7583 PINs
+
+Add all the required entry to add suppot for Airoha AN7583 PINs.
+
+Where possible the same function group are used from Airoha EN7581 to
+reduce code duplication.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/pinctrl/mediatek/pinctrl-airoha.c | 733 ++++++++++++++++++++++
+ 1 file changed, 733 insertions(+)
+
+--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c
++++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
+@@ -75,6 +75,7 @@
+ #define GPIO_PCM_SPI_CS3_MODE_MASK            BIT(20)
+ #define GPIO_PCM_SPI_CS2_MODE_P156_MASK               BIT(19)
+ #define GPIO_PCM_SPI_CS2_MODE_P128_MASK               BIT(18)
++#define AN7583_GPIO_PCM_SPI_CS2_MODE_MASK     BIT(18)
+ #define GPIO_PCM_SPI_CS1_MODE_MASK            BIT(17)
+ #define GPIO_PCM_SPI_MODE_MASK                        BIT(16)
+ #define GPIO_PCM2_MODE_MASK                   BIT(13)
+@@ -132,6 +133,8 @@
+ /* CONF */
+ #define REG_I2C_SDA_E2                                0x001c
++#define AN7583_I2C1_SCL_E2_MASK                       BIT(16)
++#define AN7583_I2C1_SDA_E2_MASK                       BIT(15)
+ #define SPI_MISO_E2_MASK                      BIT(14)
+ #define SPI_MOSI_E2_MASK                      BIT(13)
+ #define SPI_CLK_E2_MASK                               BIT(12)
+@@ -139,12 +142,16 @@
+ #define PCIE2_RESET_E2_MASK                   BIT(10)
+ #define PCIE1_RESET_E2_MASK                   BIT(9)
+ #define PCIE0_RESET_E2_MASK                   BIT(8)
++#define AN7583_MDIO_0_E2_MASK                 BIT(5)
++#define AN7583_MDC_0_E2_MASK                  BIT(4)
+ #define UART1_RXD_E2_MASK                     BIT(3)
+ #define UART1_TXD_E2_MASK                     BIT(2)
+ #define I2C_SCL_E2_MASK                               BIT(1)
+ #define I2C_SDA_E2_MASK                               BIT(0)
+ #define REG_I2C_SDA_E4                                0x0020
++#define AN7583_I2C1_SCL_E4_MASK                       BIT(16)
++#define AN7583_I2C1_SDA_E4_MASK                       BIT(15)
+ #define SPI_MISO_E4_MASK                      BIT(14)
+ #define SPI_MOSI_E4_MASK                      BIT(13)
+ #define SPI_CLK_E4_MASK                               BIT(12)
+@@ -152,6 +159,8 @@
+ #define PCIE2_RESET_E4_MASK                   BIT(10)
+ #define PCIE1_RESET_E4_MASK                   BIT(9)
+ #define PCIE0_RESET_E4_MASK                   BIT(8)
++#define AN7583_MDIO_0_E4_MASK                 BIT(5)
++#define AN7583_MDC_0_E4_MASK                  BIT(4)
+ #define UART1_RXD_E4_MASK                     BIT(3)
+ #define UART1_TXD_E4_MASK                     BIT(2)
+ #define I2C_SCL_E4_MASK                               BIT(1)
+@@ -163,6 +172,8 @@
+ #define REG_GPIO_H_E4                         0x0030
+ #define REG_I2C_SDA_PU                                0x0044
++#define AN7583_I2C1_SCL_PU_MASK                       BIT(16)
++#define AN7583_I2C1_SDA_PU_MASK                       BIT(15)
+ #define SPI_MISO_PU_MASK                      BIT(14)
+ #define SPI_MOSI_PU_MASK                      BIT(13)
+ #define SPI_CLK_PU_MASK                               BIT(12)
+@@ -170,12 +181,16 @@
+ #define PCIE2_RESET_PU_MASK                   BIT(10)
+ #define PCIE1_RESET_PU_MASK                   BIT(9)
+ #define PCIE0_RESET_PU_MASK                   BIT(8)
++#define AN7583_MDIO_0_PU_MASK                 BIT(5)
++#define AN7583_MDC_0_PU_MASK                  BIT(4)
+ #define UART1_RXD_PU_MASK                     BIT(3)
+ #define UART1_TXD_PU_MASK                     BIT(2)
+ #define I2C_SCL_PU_MASK                               BIT(1)
+ #define I2C_SDA_PU_MASK                               BIT(0)
+ #define REG_I2C_SDA_PD                                0x0048
++#define AN7583_I2C1_SDA_PD_MASK                       BIT(16)
++#define AN7583_I2C1_SCL_PD_MASK                       BIT(15)
+ #define SPI_MISO_PD_MASK                      BIT(14)
+ #define SPI_MOSI_PD_MASK                      BIT(13)
+ #define SPI_CLK_PD_MASK                               BIT(12)
+@@ -183,6 +198,8 @@
+ #define PCIE2_RESET_PD_MASK                   BIT(10)
+ #define PCIE1_RESET_PD_MASK                   BIT(9)
+ #define PCIE0_RESET_PD_MASK                   BIT(8)
++#define AN7583_MDIO_0_PD_MASK                 BIT(5)
++#define AN7583_MDC_0_PD_MASK                  BIT(4)
+ #define UART1_RXD_PD_MASK                     BIT(3)
+ #define UART1_TXD_PD_MASK                     BIT(2)
+ #define I2C_SCL_PD_MASK                               BIT(1)
+@@ -630,10 +647,223 @@ static const struct pingroup en7581_pinc
+       PINCTRL_PIN_GROUP("pcie_reset2", en7581_pcie_reset2),
+ };
++static struct pinctrl_pin_desc an7583_pinctrl_pins[] = {
++      PINCTRL_PIN(2, "gpio0"),
++      PINCTRL_PIN(3, "gpio1"),
++      PINCTRL_PIN(4, "gpio2"),
++      PINCTRL_PIN(5, "gpio3"),
++      PINCTRL_PIN(6, "gpio4"),
++      PINCTRL_PIN(7, "gpio5"),
++      PINCTRL_PIN(8, "gpio6"),
++      PINCTRL_PIN(9, "gpio7"),
++      PINCTRL_PIN(10, "gpio8"),
++      PINCTRL_PIN(11, "gpio9"),
++      PINCTRL_PIN(12, "gpio10"),
++      PINCTRL_PIN(13, "gpio11"),
++      PINCTRL_PIN(14, "gpio12"),
++      PINCTRL_PIN(15, "gpio13"),
++      PINCTRL_PIN(16, "gpio14"),
++      PINCTRL_PIN(17, "gpio15"),
++      PINCTRL_PIN(18, "gpio16"),
++      PINCTRL_PIN(19, "gpio17"),
++      PINCTRL_PIN(20, "gpio18"),
++      PINCTRL_PIN(21, "gpio19"),
++      PINCTRL_PIN(22, "gpio20"),
++      PINCTRL_PIN(23, "gpio21"),
++      PINCTRL_PIN(24, "gpio22"),
++      PINCTRL_PIN(25, "gpio23"),
++      PINCTRL_PIN(26, "gpio24"),
++      PINCTRL_PIN(27, "gpio25"),
++      PINCTRL_PIN(28, "gpio26"),
++      PINCTRL_PIN(29, "gpio27"),
++      PINCTRL_PIN(30, "gpio28"),
++      PINCTRL_PIN(31, "gpio29"),
++      PINCTRL_PIN(32, "gpio30"),
++      PINCTRL_PIN(33, "gpio31"),
++      PINCTRL_PIN(34, "gpio32"),
++      PINCTRL_PIN(35, "gpio33"),
++      PINCTRL_PIN(36, "gpio34"),
++      PINCTRL_PIN(37, "gpio35"),
++      PINCTRL_PIN(38, "gpio36"),
++      PINCTRL_PIN(39, "gpio37"),
++      PINCTRL_PIN(40, "gpio38"),
++      PINCTRL_PIN(41, "i2c0_scl"),
++      PINCTRL_PIN(42, "i2c0_sda"),
++      PINCTRL_PIN(43, "i2c1_scl"),
++      PINCTRL_PIN(44, "i2c1_sda"),
++      PINCTRL_PIN(45, "spi_clk"),
++      PINCTRL_PIN(46, "spi_cs"),
++      PINCTRL_PIN(47, "spi_mosi"),
++      PINCTRL_PIN(48, "spi_miso"),
++      PINCTRL_PIN(49, "uart_txd"),
++      PINCTRL_PIN(50, "uart_rxd"),
++      PINCTRL_PIN(51, "pcie_reset0"),
++      PINCTRL_PIN(52, "pcie_reset1"),
++      PINCTRL_PIN(53, "mdc_0"),
++      PINCTRL_PIN(54, "mdio_0"),
++};
++
++static const int an7583_pon_pins[] = { 15, 16, 17, 18, 19, 20 };
++static const int an7583_pon_tod_1pps_pins[] = { 32 };
++static const int an7583_gsw_tod_1pps_pins[] = { 32 };
++static const int an7583_sipo_pins[] = { 34, 35 };
++static const int an7583_sipo_rclk_pins[] = { 34, 35, 33 };
++static const int an7583_mdio_pins[] = { 43, 44 };
++static const int an7583_uart2_pins[] = { 34, 35 };
++static const int an7583_uart2_cts_rts_pins[] = { 32, 33 };
++static const int an7583_hsuart_pins[] = { 30, 31 };
++static const int an7583_hsuart_cts_rts_pins[] = { 28, 29 };
++static const int an7583_npu_uart_pins[] = { 7, 8 };
++static const int an7583_uart4_pins[] = { 7, 8 };
++static const int an7583_uart5_pins[] = { 23, 24 };
++static const int an7583_i2c0_pins[] = { 41, 42 };
++static const int an7583_i2c1_pins[] = { 43, 44 };
++static const int an7583_jtag_udi_pins[] = { 23, 24, 22, 25, 26 };
++static const int an7583_jtag_dfd_pins[] = { 23, 24, 22, 25, 26 };
++static const int an7583_pcm1_pins[] = { 10, 11, 12, 13, 14 };
++static const int an7583_pcm2_pins[] = { 28, 29, 30, 31, 24 };
++static const int an7583_spi_pins[] = { 28, 29, 30, 31 };
++static const int an7583_spi_quad_pins[] = { 25, 26 };
++static const int an7583_spi_cs1_pins[] = { 27 };
++static const int an7583_pcm_spi_pins[] = { 28, 29, 30, 31, 10, 11, 12, 13 };
++static const int an7583_pcm_spi_rst_pins[] = { 14 };
++static const int an7583_pcm_spi_cs1_pins[] = { 24 };
++static const int an7583_emmc_pins[] = { 7, 8, 9, 22, 23, 24, 25, 26, 45, 46, 47 };
++static const int an7583_pnand_pins[] = { 7, 8, 9, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 45, 46, 47, 48 };
++static const int an7583_gpio0_pins[] = { 2 };
++static const int an7583_gpio1_pins[] = { 3 };
++static const int an7583_gpio2_pins[] = { 4 };
++static const int an7583_gpio3_pins[] = { 5 };
++static const int an7583_gpio4_pins[] = { 6 };
++static const int an7583_gpio5_pins[] = { 7 };
++static const int an7583_gpio6_pins[] = { 8 };
++static const int an7583_gpio7_pins[] = { 9 };
++static const int an7583_gpio8_pins[] = { 10 };
++static const int an7583_gpio9_pins[] = { 11 };
++static const int an7583_gpio10_pins[] = { 12 };
++static const int an7583_gpio11_pins[] = { 13 };
++static const int an7583_gpio12_pins[] = { 14 };
++static const int an7583_gpio13_pins[] = { 15 };
++static const int an7583_gpio14_pins[] = { 16 };
++static const int an7583_gpio15_pins[] = { 17 };
++static const int an7583_gpio16_pins[] = { 18 };
++static const int an7583_gpio17_pins[] = { 19 };
++static const int an7583_gpio18_pins[] = { 20 };
++static const int an7583_gpio19_pins[] = { 21 };
++static const int an7583_gpio20_pins[] = { 22 };
++static const int an7583_gpio21_pins[] = { 24 };
++static const int an7583_gpio23_pins[] = { 25 };
++static const int an7583_gpio24_pins[] = { 26 };
++static const int an7583_gpio25_pins[] = { 27 };
++static const int an7583_gpio26_pins[] = { 28 };
++static const int an7583_gpio27_pins[] = { 29 };
++static const int an7583_gpio28_pins[] = { 30 };
++static const int an7583_gpio29_pins[] = { 31 };
++static const int an7583_gpio30_pins[] = { 32 };
++static const int an7583_gpio31_pins[] = { 33 };
++static const int an7583_gpio33_pins[] = { 35 };
++static const int an7583_gpio34_pins[] = { 36 };
++static const int an7583_gpio35_pins[] = { 37 };
++static const int an7583_gpio36_pins[] = { 38 };
++static const int an7583_gpio37_pins[] = { 39 };
++static const int an7583_gpio38_pins[] = { 40 };
++static const int an7583_gpio39_pins[] = { 41 };
++static const int an7583_gpio40_pins[] = { 42 };
++static const int an7583_gpio41_pins[] = { 43 };
++static const int an7583_gpio42_pins[] = { 44 };
++static const int an7583_gpio43_pins[] = { 45 };
++static const int an7583_gpio44_pins[] = { 46 };
++static const int an7583_gpio45_pins[] = { 47 };
++static const int an7583_gpio46_pins[] = { 48 };
++static const int an7583_gpio47_pins[] = { 49 };
++static const int an7583_gpio48_pins[] = { 50 };
++static const int an7583_pcie_reset0_pins[] = { 51 };
++static const int an7583_pcie_reset1_pins[] = { 52 };
++
++static const struct pingroup an7583_pinctrl_groups[] = {
++      PINCTRL_PIN_GROUP("pon", an7583_pon),
++      PINCTRL_PIN_GROUP("pon_tod_1pps", an7583_pon_tod_1pps),
++      PINCTRL_PIN_GROUP("gsw_tod_1pps", an7583_gsw_tod_1pps),
++      PINCTRL_PIN_GROUP("sipo", an7583_sipo),
++      PINCTRL_PIN_GROUP("sipo_rclk", an7583_sipo_rclk),
++      PINCTRL_PIN_GROUP("mdio", an7583_mdio),
++      PINCTRL_PIN_GROUP("uart2", an7583_uart2),
++      PINCTRL_PIN_GROUP("uart2_cts_rts", an7583_uart2_cts_rts),
++      PINCTRL_PIN_GROUP("hsuart", an7583_hsuart),
++      PINCTRL_PIN_GROUP("hsuart_cts_rts", an7583_hsuart_cts_rts),
++      PINCTRL_PIN_GROUP("npu_uart", an7583_npu_uart),
++      PINCTRL_PIN_GROUP("uart4", an7583_uart4),
++      PINCTRL_PIN_GROUP("uart5", an7583_uart5),
++      PINCTRL_PIN_GROUP("i2c0", an7583_i2c0),
++      PINCTRL_PIN_GROUP("i2c1", an7583_i2c1),
++      PINCTRL_PIN_GROUP("jtag_udi", an7583_jtag_udi),
++      PINCTRL_PIN_GROUP("jtag_dfd", an7583_jtag_dfd),
++      PINCTRL_PIN_GROUP("pcm1", an7583_pcm1),
++      PINCTRL_PIN_GROUP("pcm2", an7583_pcm2),
++      PINCTRL_PIN_GROUP("spi", an7583_spi),
++      PINCTRL_PIN_GROUP("spi_quad", an7583_spi_quad),
++      PINCTRL_PIN_GROUP("spi_cs1", an7583_spi_cs1),
++      PINCTRL_PIN_GROUP("pcm_spi", an7583_pcm_spi),
++      PINCTRL_PIN_GROUP("pcm_spi_rst", an7583_pcm_spi_rst),
++      PINCTRL_PIN_GROUP("pcm_spi_cs1", an7583_pcm_spi_cs1),
++      PINCTRL_PIN_GROUP("emmc", an7583_emmc),
++      PINCTRL_PIN_GROUP("pnand", an7583_pnand),
++      PINCTRL_PIN_GROUP("gpio0", an7583_gpio0),
++      PINCTRL_PIN_GROUP("gpio1", an7583_gpio1),
++      PINCTRL_PIN_GROUP("gpio2", an7583_gpio2),
++      PINCTRL_PIN_GROUP("gpio3", an7583_gpio3),
++      PINCTRL_PIN_GROUP("gpio4", an7583_gpio4),
++      PINCTRL_PIN_GROUP("gpio5", an7583_gpio5),
++      PINCTRL_PIN_GROUP("gpio6", an7583_gpio6),
++      PINCTRL_PIN_GROUP("gpio7", an7583_gpio7),
++      PINCTRL_PIN_GROUP("gpio8", an7583_gpio8),
++      PINCTRL_PIN_GROUP("gpio9", an7583_gpio9),
++      PINCTRL_PIN_GROUP("gpio10", an7583_gpio10),
++      PINCTRL_PIN_GROUP("gpio11", an7583_gpio11),
++      PINCTRL_PIN_GROUP("gpio12", an7583_gpio12),
++      PINCTRL_PIN_GROUP("gpio13", an7583_gpio13),
++      PINCTRL_PIN_GROUP("gpio14", an7583_gpio14),
++      PINCTRL_PIN_GROUP("gpio15", an7583_gpio15),
++      PINCTRL_PIN_GROUP("gpio16", an7583_gpio16),
++      PINCTRL_PIN_GROUP("gpio17", an7583_gpio17),
++      PINCTRL_PIN_GROUP("gpio18", an7583_gpio18),
++      PINCTRL_PIN_GROUP("gpio19", an7583_gpio19),
++      PINCTRL_PIN_GROUP("gpio20", an7583_gpio20),
++      PINCTRL_PIN_GROUP("gpio21", an7583_gpio21),
++      PINCTRL_PIN_GROUP("gpio23", an7583_gpio23),
++      PINCTRL_PIN_GROUP("gpio24", an7583_gpio24),
++      PINCTRL_PIN_GROUP("gpio25", an7583_gpio25),
++      PINCTRL_PIN_GROUP("gpio26", an7583_gpio26),
++      PINCTRL_PIN_GROUP("gpio27", an7583_gpio27),
++      PINCTRL_PIN_GROUP("gpio28", an7583_gpio28),
++      PINCTRL_PIN_GROUP("gpio29", an7583_gpio29),
++      PINCTRL_PIN_GROUP("gpio30", an7583_gpio30),
++      PINCTRL_PIN_GROUP("gpio31", an7583_gpio31),
++      PINCTRL_PIN_GROUP("gpio33", an7583_gpio33),
++      PINCTRL_PIN_GROUP("gpio34", an7583_gpio34),
++      PINCTRL_PIN_GROUP("gpio35", an7583_gpio35),
++      PINCTRL_PIN_GROUP("gpio36", an7583_gpio36),
++      PINCTRL_PIN_GROUP("gpio37", an7583_gpio37),
++      PINCTRL_PIN_GROUP("gpio38", an7583_gpio38),
++      PINCTRL_PIN_GROUP("gpio39", an7583_gpio39),
++      PINCTRL_PIN_GROUP("gpio40", an7583_gpio40),
++      PINCTRL_PIN_GROUP("gpio41", an7583_gpio41),
++      PINCTRL_PIN_GROUP("gpio42", an7583_gpio42),
++      PINCTRL_PIN_GROUP("gpio43", an7583_gpio43),
++      PINCTRL_PIN_GROUP("gpio44", an7583_gpio44),
++      PINCTRL_PIN_GROUP("gpio45", an7583_gpio45),
++      PINCTRL_PIN_GROUP("gpio46", an7583_gpio46),
++      PINCTRL_PIN_GROUP("gpio47", an7583_gpio47),
++      PINCTRL_PIN_GROUP("gpio48", an7583_gpio48),
++      PINCTRL_PIN_GROUP("pcie_reset0", an7583_pcie_reset0),
++      PINCTRL_PIN_GROUP("pcie_reset1", an7583_pcie_reset1),
++};
++
+ static const char *const pon_groups[] = { "pon" };
+ static const char *const tod_1pps_groups[] = { "pon_tod_1pps", "gsw_tod_1pps" };
+ static const char *const sipo_groups[] = { "sipo", "sipo_rclk" };
+ static const char *const mdio_groups[] = { "mdio" };
++static const char *const an7583_mdio_groups[] = { "mdio" };
+ static const char *const uart_groups[] = { "uart2", "uart2_cts_rts", "hsuart",
+                                          "hsuart_cts_rts", "uart4",
+                                          "uart5" };
+@@ -646,11 +876,16 @@ static const char *const pcm_spi_groups[
+                                             "pcm_spi_cs2_p156",
+                                             "pcm_spi_cs2_p128",
+                                             "pcm_spi_cs3", "pcm_spi_cs4" };
++static const char *const an7583_pcm_spi_groups[] = { "pcm_spi", "pcm_spi_int",
++                                                   "pcm_spi_rst", "pcm_spi_cs1",
++                                                   "pcm_spi_cs2", "pcm_spi_cs3",
++                                                   "pcm_spi_cs4" };
+ static const char *const i2s_groups[] = { "i2s" };
+ static const char *const emmc_groups[] = { "emmc" };
+ static const char *const pnand_groups[] = { "pnand" };
+ static const char *const pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1",
+                                                "pcie_reset2" };
++static const char *const an7583_pcie_reset_groups[] = { "pcie_reset0", "pcie_reset1" };
+ static const char *const pwm_groups[] = { "gpio0", "gpio1",
+                                         "gpio2", "gpio3",
+                                         "gpio4", "gpio5",
+@@ -689,6 +924,22 @@ static const char *const phy3_led1_group
+                                               "gpio45", "gpio46" };
+ static const char *const phy4_led1_groups[] = { "gpio43", "gpio44",
+                                               "gpio45", "gpio46" };
++static const char *const an7583_phy1_led0_groups[] = { "gpio1", "gpio2",
++                                                     "gpio3", "gpio4" };
++static const char *const an7583_phy2_led0_groups[] = { "gpio1", "gpio2",
++                                                     "gpio3", "gpio4" };
++static const char *const an7583_phy3_led0_groups[] = { "gpio1", "gpio2",
++                                                     "gpio3", "gpio4" };
++static const char *const an7583_phy4_led0_groups[] = { "gpio1", "gpio2",
++                                                     "gpio3", "gpio4" };
++static const char *const an7583_phy1_led1_groups[] = { "gpio8", "gpio9",
++                                                     "gpio10", "gpio11" };
++static const char *const an7583_phy2_led1_groups[] = { "gpio8", "gpio9",
++                                                     "gpio10", "gpio11" };
++static const char *const an7583_phy3_led1_groups[] = { "gpio8", "gpio9",
++                                                     "gpio10", "gpio11" };
++static const char *const an7583_phy4_led1_groups[] = { "gpio8", "gpio9",
++                                                     "gpio10", "gpio11" };
+ static const struct airoha_pinctrl_func_group pon_func_group[] = {
+       {
+@@ -766,6 +1017,25 @@ static const struct airoha_pinctrl_func_
+       },
+ };
++static const struct airoha_pinctrl_func_group an7583_mdio_func_group[] = {
++      {
++              .name = "mdio",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_PON_MODE,
++                      GPIO_SGMII_MDIO_MODE_MASK,
++                      GPIO_SGMII_MDIO_MODE_MASK
++              },
++              .regmap[1] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_MDC_IO_MASTER_MODE_MODE,
++                      GPIO_MDC_IO_MASTER_MODE_MODE
++              },
++              .regmap_size = 2,
++      },
++};
++
+ static const struct airoha_pinctrl_func_group uart_func_group[] = {
+       {
+               .name = "uart2",
+@@ -1007,6 +1277,73 @@ static const struct airoha_pinctrl_func_
+       },
+ };
++static const struct airoha_pinctrl_func_group an7583_pcm_spi_func_group[] = {
++      {
++              .name = "pcm_spi",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_PCM_SPI_MODE_MASK,
++                      GPIO_PCM_SPI_MODE_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcm_spi_int",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_PCM_INT_MODE_MASK,
++                      GPIO_PCM_INT_MODE_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcm_spi_rst",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_PCM_RESET_MODE_MASK,
++                      GPIO_PCM_RESET_MODE_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcm_spi_cs1",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_PCM_SPI_CS1_MODE_MASK,
++                      GPIO_PCM_SPI_CS1_MODE_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcm_spi_cs2",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      AN7583_GPIO_PCM_SPI_CS2_MODE_MASK,
++                      AN7583_GPIO_PCM_SPI_CS2_MODE_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcm_spi_cs3",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_PCM_SPI_CS3_MODE_MASK,
++                      GPIO_PCM_SPI_CS3_MODE_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcm_spi_cs4",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_SPI_CS1_MODE,
++                      GPIO_PCM_SPI_CS4_MODE_MASK,
++                      GPIO_PCM_SPI_CS4_MODE_MASK
++              },
++              .regmap_size = 1,
++      },
++};
++
+ static const struct airoha_pinctrl_func_group i2s_func_group[] = {
+       {
+               .name = "i2s",
+@@ -1077,6 +1414,28 @@ static const struct airoha_pinctrl_func_
+       },
+ };
++static const struct airoha_pinctrl_func_group an7583_pcie_reset_func_group[] = {
++      {
++              .name = "pcie_reset0",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_PON_MODE,
++                      GPIO_PCIE_RESET0_MASK,
++                      GPIO_PCIE_RESET0_MASK
++              },
++              .regmap_size = 1,
++      }, {
++              .name = "pcie_reset1",
++              .regmap[0] = {
++                      AIROHA_FUNC_MUX,
++                      REG_GPIO_PON_MODE,
++                      GPIO_PCIE_RESET1_MASK,
++                      GPIO_PCIE_RESET1_MASK
++              },
++              .regmap_size = 1,
++      },
++};
++
+ /* PWM */
+ #define AIROHA_PINCTRL_PWM(gpio, mux_val)             \
+       {                                               \
+@@ -1255,6 +1614,94 @@ static const struct airoha_pinctrl_func_
+                              LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
+ };
++static const struct airoha_pinctrl_func_group an7583_phy1_led0_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio1", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio2", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio3", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio4", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy2_led0_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio1", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio2", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio3", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio4", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy3_led0_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio1", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio2", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio3", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio4", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy4_led0_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio1", GPIO_LAN0_LED0_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(3)),
++      AIROHA_PINCTRL_PHY_LED("gpio2", GPIO_LAN1_LED0_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(3)),
++      AIROHA_PINCTRL_PHY_LED("gpio3", GPIO_LAN2_LED0_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(3)),
++      AIROHA_PINCTRL_PHY_LED("gpio4", GPIO_LAN3_LED0_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(3)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy1_led1_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio8", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio9", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio10", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(0)),
++      AIROHA_PINCTRL_PHY_LED("gpio1", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(0)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy2_led1_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio8", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio9", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio10", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(1)),
++      AIROHA_PINCTRL_PHY_LED("gpio11", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(1)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy3_led1_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio8", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio9", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio10", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio11", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
++};
++
++static const struct airoha_pinctrl_func_group an7583_phy4_led1_func_group[] = {
++      AIROHA_PINCTRL_PHY_LED("gpio8", GPIO_LAN0_LED1_MODE_MASK,
++                             LAN0_LED_MAPPING_MASK, LAN0_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio9", GPIO_LAN1_LED1_MODE_MASK,
++                             LAN1_LED_MAPPING_MASK, LAN1_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio10", GPIO_LAN2_LED1_MODE_MASK,
++                             LAN2_LED_MAPPING_MASK, LAN2_PHY_LED_MAP(2)),
++      AIROHA_PINCTRL_PHY_LED("gpio11", GPIO_LAN3_LED1_MODE_MASK,
++                             LAN3_LED_MAPPING_MASK, LAN3_PHY_LED_MAP(2)),
++};
++
+ static const struct airoha_pinctrl_func en7581_pinctrl_funcs[] = {
+       PINCTRL_FUNC_DESC("pon", pon),
+       PINCTRL_FUNC_DESC("tod_1pps", tod_1pps),
+@@ -1281,6 +1728,31 @@ static const struct airoha_pinctrl_func
+       PINCTRL_FUNC_DESC("phy4_led1", phy4_led1),
+ };
++static const struct airoha_pinctrl_func an7583_pinctrl_funcs[] = {
++      PINCTRL_FUNC_DESC("pon", pon),
++      PINCTRL_FUNC_DESC("tod_1pps", tod_1pps),
++      PINCTRL_FUNC_DESC("sipo", sipo),
++      PINCTRL_FUNC_DESC("mdio", an7583_mdio),
++      PINCTRL_FUNC_DESC("uart", uart),
++      PINCTRL_FUNC_DESC("i2c", i2c),
++      PINCTRL_FUNC_DESC("jtag", jtag),
++      PINCTRL_FUNC_DESC("pcm", pcm),
++      PINCTRL_FUNC_DESC("spi", spi),
++      PINCTRL_FUNC_DESC("pcm_spi", an7583_pcm_spi),
++      PINCTRL_FUNC_DESC("emmc", emmc),
++      PINCTRL_FUNC_DESC("pnand", pnand),
++      PINCTRL_FUNC_DESC("pcie_reset", an7583_pcie_reset),
++      PINCTRL_FUNC_DESC("pwm", pwm),
++      PINCTRL_FUNC_DESC("phy1_led0", an7583_phy1_led0),
++      PINCTRL_FUNC_DESC("phy2_led0", an7583_phy2_led0),
++      PINCTRL_FUNC_DESC("phy3_led0", an7583_phy3_led0),
++      PINCTRL_FUNC_DESC("phy4_led0", an7583_phy4_led0),
++      PINCTRL_FUNC_DESC("phy1_led1", an7583_phy1_led1),
++      PINCTRL_FUNC_DESC("phy2_led1", an7583_phy2_led1),
++      PINCTRL_FUNC_DESC("phy3_led1", an7583_phy3_led1),
++      PINCTRL_FUNC_DESC("phy4_led1", an7583_phy4_led1),
++};
++
+ static const struct airoha_pinctrl_conf en7581_pinctrl_pullup_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_PU, UART1_TXD_PU_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_PU, UART1_RXD_PU_MASK),
+@@ -1342,6 +1814,62 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_PU, PCIE2_RESET_PU_MASK),
+ };
++static const struct airoha_pinctrl_conf an7583_pinctrl_pullup_conf[] = {
++      PINCTRL_CONF_DESC(2, REG_GPIO_L_PU, BIT(0)),
++      PINCTRL_CONF_DESC(3, REG_GPIO_L_PU, BIT(1)),
++      PINCTRL_CONF_DESC(4, REG_GPIO_L_PU, BIT(2)),
++      PINCTRL_CONF_DESC(5, REG_GPIO_L_PU, BIT(3)),
++      PINCTRL_CONF_DESC(6, REG_GPIO_L_PU, BIT(4)),
++      PINCTRL_CONF_DESC(7, REG_GPIO_L_PU, BIT(5)),
++      PINCTRL_CONF_DESC(8, REG_GPIO_L_PU, BIT(6)),
++      PINCTRL_CONF_DESC(9, REG_GPIO_L_PU, BIT(7)),
++      PINCTRL_CONF_DESC(10, REG_GPIO_L_PU, BIT(8)),
++      PINCTRL_CONF_DESC(11, REG_GPIO_L_PU, BIT(9)),
++      PINCTRL_CONF_DESC(12, REG_GPIO_L_PU, BIT(10)),
++      PINCTRL_CONF_DESC(13, REG_GPIO_L_PU, BIT(11)),
++      PINCTRL_CONF_DESC(14, REG_GPIO_L_PU, BIT(12)),
++      PINCTRL_CONF_DESC(15, REG_GPIO_L_PU, BIT(13)),
++      PINCTRL_CONF_DESC(16, REG_GPIO_L_PU, BIT(14)),
++      PINCTRL_CONF_DESC(17, REG_GPIO_L_PU, BIT(15)),
++      PINCTRL_CONF_DESC(18, REG_GPIO_L_PU, BIT(16)),
++      PINCTRL_CONF_DESC(19, REG_GPIO_L_PU, BIT(17)),
++      PINCTRL_CONF_DESC(20, REG_GPIO_L_PU, BIT(18)),
++      PINCTRL_CONF_DESC(21, REG_GPIO_L_PU, BIT(18)),
++      PINCTRL_CONF_DESC(22, REG_GPIO_L_PU, BIT(20)),
++      PINCTRL_CONF_DESC(23, REG_GPIO_L_PU, BIT(21)),
++      PINCTRL_CONF_DESC(24, REG_GPIO_L_PU, BIT(22)),
++      PINCTRL_CONF_DESC(25, REG_GPIO_L_PU, BIT(23)),
++      PINCTRL_CONF_DESC(26, REG_GPIO_L_PU, BIT(24)),
++      PINCTRL_CONF_DESC(27, REG_GPIO_L_PU, BIT(25)),
++      PINCTRL_CONF_DESC(28, REG_GPIO_L_PU, BIT(26)),
++      PINCTRL_CONF_DESC(29, REG_GPIO_L_PU, BIT(27)),
++      PINCTRL_CONF_DESC(30, REG_GPIO_L_PU, BIT(28)),
++      PINCTRL_CONF_DESC(31, REG_GPIO_L_PU, BIT(29)),
++      PINCTRL_CONF_DESC(32, REG_GPIO_L_PU, BIT(30)),
++      PINCTRL_CONF_DESC(33, REG_GPIO_L_PU, BIT(31)),
++      PINCTRL_CONF_DESC(34, REG_GPIO_H_PU, BIT(0)),
++      PINCTRL_CONF_DESC(35, REG_GPIO_H_PU, BIT(1)),
++      PINCTRL_CONF_DESC(36, REG_GPIO_H_PU, BIT(2)),
++      PINCTRL_CONF_DESC(37, REG_GPIO_H_PU, BIT(3)),
++      PINCTRL_CONF_DESC(38, REG_GPIO_H_PU, BIT(4)),
++      PINCTRL_CONF_DESC(39, REG_GPIO_H_PU, BIT(5)),
++      PINCTRL_CONF_DESC(40, REG_GPIO_H_PU, BIT(6)),
++      PINCTRL_CONF_DESC(41, REG_I2C_SDA_PU, I2C_SCL_PU_MASK),
++      PINCTRL_CONF_DESC(42, REG_I2C_SDA_PU, I2C_SDA_PU_MASK),
++      PINCTRL_CONF_DESC(43, REG_I2C_SDA_PU, AN7583_I2C1_SCL_PU_MASK),
++      PINCTRL_CONF_DESC(44, REG_I2C_SDA_PU, AN7583_I2C1_SDA_PU_MASK),
++      PINCTRL_CONF_DESC(45, REG_I2C_SDA_PU, SPI_CLK_PU_MASK),
++      PINCTRL_CONF_DESC(46, REG_I2C_SDA_PU, SPI_CS0_PU_MASK),
++      PINCTRL_CONF_DESC(47, REG_I2C_SDA_PU, SPI_MOSI_PU_MASK),
++      PINCTRL_CONF_DESC(48, REG_I2C_SDA_PU, SPI_MISO_PU_MASK),
++      PINCTRL_CONF_DESC(49, REG_I2C_SDA_PU, UART1_TXD_PU_MASK),
++      PINCTRL_CONF_DESC(50, REG_I2C_SDA_PU, UART1_RXD_PU_MASK),
++      PINCTRL_CONF_DESC(51, REG_I2C_SDA_PU, PCIE0_RESET_PU_MASK),
++      PINCTRL_CONF_DESC(52, REG_I2C_SDA_PU, PCIE1_RESET_PU_MASK),
++      PINCTRL_CONF_DESC(53, REG_I2C_SDA_PU, AN7583_MDC_0_PU_MASK),
++      PINCTRL_CONF_DESC(54, REG_I2C_SDA_PU, AN7583_MDIO_0_PU_MASK),
++};
++
+ static const struct airoha_pinctrl_conf en7581_pinctrl_pulldown_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_PD, UART1_TXD_PD_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_PD, UART1_RXD_PD_MASK),
+@@ -1403,6 +1931,62 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_PD, PCIE2_RESET_PD_MASK),
+ };
++static const struct airoha_pinctrl_conf an7583_pinctrl_pulldown_conf[] = {
++      PINCTRL_CONF_DESC(2, REG_GPIO_L_PD, BIT(0)),
++      PINCTRL_CONF_DESC(3, REG_GPIO_L_PD, BIT(1)),
++      PINCTRL_CONF_DESC(4, REG_GPIO_L_PD, BIT(2)),
++      PINCTRL_CONF_DESC(5, REG_GPIO_L_PD, BIT(3)),
++      PINCTRL_CONF_DESC(6, REG_GPIO_L_PD, BIT(4)),
++      PINCTRL_CONF_DESC(7, REG_GPIO_L_PD, BIT(5)),
++      PINCTRL_CONF_DESC(8, REG_GPIO_L_PD, BIT(6)),
++      PINCTRL_CONF_DESC(9, REG_GPIO_L_PD, BIT(7)),
++      PINCTRL_CONF_DESC(10, REG_GPIO_L_PD, BIT(8)),
++      PINCTRL_CONF_DESC(11, REG_GPIO_L_PD, BIT(9)),
++      PINCTRL_CONF_DESC(12, REG_GPIO_L_PD, BIT(10)),
++      PINCTRL_CONF_DESC(13, REG_GPIO_L_PD, BIT(11)),
++      PINCTRL_CONF_DESC(14, REG_GPIO_L_PD, BIT(12)),
++      PINCTRL_CONF_DESC(15, REG_GPIO_L_PD, BIT(13)),
++      PINCTRL_CONF_DESC(16, REG_GPIO_L_PD, BIT(14)),
++      PINCTRL_CONF_DESC(17, REG_GPIO_L_PD, BIT(15)),
++      PINCTRL_CONF_DESC(18, REG_GPIO_L_PD, BIT(16)),
++      PINCTRL_CONF_DESC(19, REG_GPIO_L_PD, BIT(17)),
++      PINCTRL_CONF_DESC(20, REG_GPIO_L_PD, BIT(18)),
++      PINCTRL_CONF_DESC(21, REG_GPIO_L_PD, BIT(18)),
++      PINCTRL_CONF_DESC(22, REG_GPIO_L_PD, BIT(20)),
++      PINCTRL_CONF_DESC(23, REG_GPIO_L_PD, BIT(21)),
++      PINCTRL_CONF_DESC(24, REG_GPIO_L_PD, BIT(22)),
++      PINCTRL_CONF_DESC(25, REG_GPIO_L_PD, BIT(23)),
++      PINCTRL_CONF_DESC(26, REG_GPIO_L_PD, BIT(24)),
++      PINCTRL_CONF_DESC(27, REG_GPIO_L_PD, BIT(25)),
++      PINCTRL_CONF_DESC(28, REG_GPIO_L_PD, BIT(26)),
++      PINCTRL_CONF_DESC(29, REG_GPIO_L_PD, BIT(27)),
++      PINCTRL_CONF_DESC(30, REG_GPIO_L_PD, BIT(28)),
++      PINCTRL_CONF_DESC(31, REG_GPIO_L_PD, BIT(29)),
++      PINCTRL_CONF_DESC(32, REG_GPIO_L_PD, BIT(30)),
++      PINCTRL_CONF_DESC(33, REG_GPIO_L_PD, BIT(31)),
++      PINCTRL_CONF_DESC(34, REG_GPIO_H_PD, BIT(0)),
++      PINCTRL_CONF_DESC(35, REG_GPIO_H_PD, BIT(1)),
++      PINCTRL_CONF_DESC(36, REG_GPIO_H_PD, BIT(2)),
++      PINCTRL_CONF_DESC(37, REG_GPIO_H_PD, BIT(3)),
++      PINCTRL_CONF_DESC(38, REG_GPIO_H_PD, BIT(4)),
++      PINCTRL_CONF_DESC(39, REG_GPIO_H_PD, BIT(5)),
++      PINCTRL_CONF_DESC(40, REG_GPIO_H_PD, BIT(6)),
++      PINCTRL_CONF_DESC(41, REG_I2C_SDA_PD, I2C_SCL_PD_MASK),
++      PINCTRL_CONF_DESC(42, REG_I2C_SDA_PD, I2C_SDA_PD_MASK),
++      PINCTRL_CONF_DESC(43, REG_I2C_SDA_PD, AN7583_I2C1_SCL_PD_MASK),
++      PINCTRL_CONF_DESC(44, REG_I2C_SDA_PD, AN7583_I2C1_SDA_PD_MASK),
++      PINCTRL_CONF_DESC(45, REG_I2C_SDA_PD, SPI_CLK_PD_MASK),
++      PINCTRL_CONF_DESC(46, REG_I2C_SDA_PD, SPI_CS0_PD_MASK),
++      PINCTRL_CONF_DESC(47, REG_I2C_SDA_PD, SPI_MOSI_PD_MASK),
++      PINCTRL_CONF_DESC(48, REG_I2C_SDA_PD, SPI_MISO_PD_MASK),
++      PINCTRL_CONF_DESC(49, REG_I2C_SDA_PD, UART1_TXD_PD_MASK),
++      PINCTRL_CONF_DESC(50, REG_I2C_SDA_PD, UART1_RXD_PD_MASK),
++      PINCTRL_CONF_DESC(51, REG_I2C_SDA_PD, PCIE0_RESET_PD_MASK),
++      PINCTRL_CONF_DESC(52, REG_I2C_SDA_PD, PCIE1_RESET_PD_MASK),
++      PINCTRL_CONF_DESC(53, REG_I2C_SDA_PD, AN7583_MDC_0_PD_MASK),
++      PINCTRL_CONF_DESC(54, REG_I2C_SDA_PD, AN7583_MDIO_0_PD_MASK),
++};
++
+ static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e2_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_E2, UART1_TXD_E2_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_E2, UART1_RXD_E2_MASK),
+@@ -1464,6 +2048,62 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_E2, PCIE2_RESET_E2_MASK),
+ };
++static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e2_conf[] = {
++      PINCTRL_CONF_DESC(2, REG_GPIO_L_E2, BIT(0)),
++      PINCTRL_CONF_DESC(3, REG_GPIO_L_E2, BIT(1)),
++      PINCTRL_CONF_DESC(4, REG_GPIO_L_E2, BIT(2)),
++      PINCTRL_CONF_DESC(5, REG_GPIO_L_E2, BIT(3)),
++      PINCTRL_CONF_DESC(6, REG_GPIO_L_E2, BIT(4)),
++      PINCTRL_CONF_DESC(7, REG_GPIO_L_E2, BIT(5)),
++      PINCTRL_CONF_DESC(8, REG_GPIO_L_E2, BIT(6)),
++      PINCTRL_CONF_DESC(9, REG_GPIO_L_E2, BIT(7)),
++      PINCTRL_CONF_DESC(10, REG_GPIO_L_E2, BIT(8)),
++      PINCTRL_CONF_DESC(11, REG_GPIO_L_E2, BIT(9)),
++      PINCTRL_CONF_DESC(12, REG_GPIO_L_E2, BIT(10)),
++      PINCTRL_CONF_DESC(13, REG_GPIO_L_E2, BIT(11)),
++      PINCTRL_CONF_DESC(14, REG_GPIO_L_E2, BIT(12)),
++      PINCTRL_CONF_DESC(15, REG_GPIO_L_E2, BIT(13)),
++      PINCTRL_CONF_DESC(16, REG_GPIO_L_E2, BIT(14)),
++      PINCTRL_CONF_DESC(17, REG_GPIO_L_E2, BIT(15)),
++      PINCTRL_CONF_DESC(18, REG_GPIO_L_E2, BIT(16)),
++      PINCTRL_CONF_DESC(19, REG_GPIO_L_E2, BIT(17)),
++      PINCTRL_CONF_DESC(20, REG_GPIO_L_E2, BIT(18)),
++      PINCTRL_CONF_DESC(21, REG_GPIO_L_E2, BIT(18)),
++      PINCTRL_CONF_DESC(22, REG_GPIO_L_E2, BIT(20)),
++      PINCTRL_CONF_DESC(23, REG_GPIO_L_E2, BIT(21)),
++      PINCTRL_CONF_DESC(24, REG_GPIO_L_E2, BIT(22)),
++      PINCTRL_CONF_DESC(25, REG_GPIO_L_E2, BIT(23)),
++      PINCTRL_CONF_DESC(26, REG_GPIO_L_E2, BIT(24)),
++      PINCTRL_CONF_DESC(27, REG_GPIO_L_E2, BIT(25)),
++      PINCTRL_CONF_DESC(28, REG_GPIO_L_E2, BIT(26)),
++      PINCTRL_CONF_DESC(29, REG_GPIO_L_E2, BIT(27)),
++      PINCTRL_CONF_DESC(30, REG_GPIO_L_E2, BIT(28)),
++      PINCTRL_CONF_DESC(31, REG_GPIO_L_E2, BIT(29)),
++      PINCTRL_CONF_DESC(32, REG_GPIO_L_E2, BIT(30)),
++      PINCTRL_CONF_DESC(33, REG_GPIO_L_E2, BIT(31)),
++      PINCTRL_CONF_DESC(34, REG_GPIO_H_E2, BIT(0)),
++      PINCTRL_CONF_DESC(35, REG_GPIO_H_E2, BIT(1)),
++      PINCTRL_CONF_DESC(36, REG_GPIO_H_E2, BIT(2)),
++      PINCTRL_CONF_DESC(37, REG_GPIO_H_E2, BIT(3)),
++      PINCTRL_CONF_DESC(38, REG_GPIO_H_E2, BIT(4)),
++      PINCTRL_CONF_DESC(39, REG_GPIO_H_E2, BIT(5)),
++      PINCTRL_CONF_DESC(40, REG_GPIO_H_E2, BIT(6)),
++      PINCTRL_CONF_DESC(41, REG_I2C_SDA_E2, I2C_SCL_E2_MASK),
++      PINCTRL_CONF_DESC(42, REG_I2C_SDA_E2, I2C_SDA_E2_MASK),
++      PINCTRL_CONF_DESC(43, REG_I2C_SDA_E2, AN7583_I2C1_SCL_E2_MASK),
++      PINCTRL_CONF_DESC(44, REG_I2C_SDA_E2, AN7583_I2C1_SDA_E2_MASK),
++      PINCTRL_CONF_DESC(45, REG_I2C_SDA_E2, SPI_CLK_E2_MASK),
++      PINCTRL_CONF_DESC(46, REG_I2C_SDA_E2, SPI_CS0_E2_MASK),
++      PINCTRL_CONF_DESC(47, REG_I2C_SDA_E2, SPI_MOSI_E2_MASK),
++      PINCTRL_CONF_DESC(48, REG_I2C_SDA_E2, SPI_MISO_E2_MASK),
++      PINCTRL_CONF_DESC(49, REG_I2C_SDA_E2, UART1_TXD_E2_MASK),
++      PINCTRL_CONF_DESC(50, REG_I2C_SDA_E2, UART1_RXD_E2_MASK),
++      PINCTRL_CONF_DESC(51, REG_I2C_SDA_E2, PCIE0_RESET_E2_MASK),
++      PINCTRL_CONF_DESC(52, REG_I2C_SDA_E2, PCIE1_RESET_E2_MASK),
++      PINCTRL_CONF_DESC(53, REG_I2C_SDA_E2, AN7583_MDC_0_E2_MASK),
++      PINCTRL_CONF_DESC(54, REG_I2C_SDA_E2, AN7583_MDIO_0_E2_MASK),
++};
++
+ static const struct airoha_pinctrl_conf en7581_pinctrl_drive_e4_conf[] = {
+       PINCTRL_CONF_DESC(0, REG_I2C_SDA_E4, UART1_TXD_E4_MASK),
+       PINCTRL_CONF_DESC(1, REG_I2C_SDA_E4, UART1_RXD_E4_MASK),
+@@ -1525,12 +2165,73 @@ static const struct airoha_pinctrl_conf
+       PINCTRL_CONF_DESC(63, REG_I2C_SDA_E4, PCIE2_RESET_E4_MASK),
+ };
++static const struct airoha_pinctrl_conf an7583_pinctrl_drive_e4_conf[] = {
++      PINCTRL_CONF_DESC(2, REG_GPIO_L_E4, BIT(0)),
++      PINCTRL_CONF_DESC(3, REG_GPIO_L_E4, BIT(1)),
++      PINCTRL_CONF_DESC(4, REG_GPIO_L_E4, BIT(2)),
++      PINCTRL_CONF_DESC(5, REG_GPIO_L_E4, BIT(3)),
++      PINCTRL_CONF_DESC(6, REG_GPIO_L_E4, BIT(4)),
++      PINCTRL_CONF_DESC(7, REG_GPIO_L_E4, BIT(5)),
++      PINCTRL_CONF_DESC(8, REG_GPIO_L_E4, BIT(6)),
++      PINCTRL_CONF_DESC(9, REG_GPIO_L_E4, BIT(7)),
++      PINCTRL_CONF_DESC(10, REG_GPIO_L_E4, BIT(8)),
++      PINCTRL_CONF_DESC(11, REG_GPIO_L_E4, BIT(9)),
++      PINCTRL_CONF_DESC(12, REG_GPIO_L_E4, BIT(10)),
++      PINCTRL_CONF_DESC(13, REG_GPIO_L_E4, BIT(11)),
++      PINCTRL_CONF_DESC(14, REG_GPIO_L_E4, BIT(12)),
++      PINCTRL_CONF_DESC(15, REG_GPIO_L_E4, BIT(13)),
++      PINCTRL_CONF_DESC(16, REG_GPIO_L_E4, BIT(14)),
++      PINCTRL_CONF_DESC(17, REG_GPIO_L_E4, BIT(15)),
++      PINCTRL_CONF_DESC(18, REG_GPIO_L_E4, BIT(16)),
++      PINCTRL_CONF_DESC(19, REG_GPIO_L_E4, BIT(17)),
++      PINCTRL_CONF_DESC(20, REG_GPIO_L_E4, BIT(18)),
++      PINCTRL_CONF_DESC(21, REG_GPIO_L_E4, BIT(18)),
++      PINCTRL_CONF_DESC(22, REG_GPIO_L_E4, BIT(20)),
++      PINCTRL_CONF_DESC(23, REG_GPIO_L_E4, BIT(21)),
++      PINCTRL_CONF_DESC(24, REG_GPIO_L_E4, BIT(22)),
++      PINCTRL_CONF_DESC(25, REG_GPIO_L_E4, BIT(23)),
++      PINCTRL_CONF_DESC(26, REG_GPIO_L_E4, BIT(24)),
++      PINCTRL_CONF_DESC(27, REG_GPIO_L_E4, BIT(25)),
++      PINCTRL_CONF_DESC(28, REG_GPIO_L_E4, BIT(26)),
++      PINCTRL_CONF_DESC(29, REG_GPIO_L_E4, BIT(27)),
++      PINCTRL_CONF_DESC(30, REG_GPIO_L_E4, BIT(28)),
++      PINCTRL_CONF_DESC(31, REG_GPIO_L_E4, BIT(29)),
++      PINCTRL_CONF_DESC(32, REG_GPIO_L_E4, BIT(30)),
++      PINCTRL_CONF_DESC(33, REG_GPIO_L_E4, BIT(31)),
++      PINCTRL_CONF_DESC(34, REG_GPIO_H_E4, BIT(0)),
++      PINCTRL_CONF_DESC(35, REG_GPIO_H_E4, BIT(1)),
++      PINCTRL_CONF_DESC(36, REG_GPIO_H_E4, BIT(2)),
++      PINCTRL_CONF_DESC(37, REG_GPIO_H_E4, BIT(3)),
++      PINCTRL_CONF_DESC(38, REG_GPIO_H_E4, BIT(4)),
++      PINCTRL_CONF_DESC(39, REG_GPIO_H_E4, BIT(5)),
++      PINCTRL_CONF_DESC(40, REG_GPIO_H_E4, BIT(6)),
++      PINCTRL_CONF_DESC(41, REG_I2C_SDA_E4, I2C_SCL_E4_MASK),
++      PINCTRL_CONF_DESC(42, REG_I2C_SDA_E4, I2C_SDA_E4_MASK),
++      PINCTRL_CONF_DESC(43, REG_I2C_SDA_E4, AN7583_I2C1_SCL_E4_MASK),
++      PINCTRL_CONF_DESC(44, REG_I2C_SDA_E4, AN7583_I2C1_SDA_E4_MASK),
++      PINCTRL_CONF_DESC(45, REG_I2C_SDA_E4, SPI_CLK_E4_MASK),
++      PINCTRL_CONF_DESC(46, REG_I2C_SDA_E4, SPI_CS0_E4_MASK),
++      PINCTRL_CONF_DESC(47, REG_I2C_SDA_E4, SPI_MOSI_E4_MASK),
++      PINCTRL_CONF_DESC(48, REG_I2C_SDA_E4, SPI_MISO_E4_MASK),
++      PINCTRL_CONF_DESC(49, REG_I2C_SDA_E4, UART1_TXD_E4_MASK),
++      PINCTRL_CONF_DESC(50, REG_I2C_SDA_E4, UART1_RXD_E4_MASK),
++      PINCTRL_CONF_DESC(51, REG_I2C_SDA_E4, PCIE0_RESET_E4_MASK),
++      PINCTRL_CONF_DESC(52, REG_I2C_SDA_E4, PCIE1_RESET_E4_MASK),
++      PINCTRL_CONF_DESC(53, REG_I2C_SDA_E4, AN7583_MDC_0_E4_MASK),
++      PINCTRL_CONF_DESC(54, REG_I2C_SDA_E4, AN7583_MDIO_0_E4_MASK),
++};
++
+ static const struct airoha_pinctrl_conf en7581_pinctrl_pcie_rst_od_conf[] = {
+       PINCTRL_CONF_DESC(61, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK),
+       PINCTRL_CONF_DESC(62, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK),
+       PINCTRL_CONF_DESC(63, REG_PCIE_RESET_OD, PCIE2_RESET_OD_MASK),
+ };
++static const struct airoha_pinctrl_conf an7583_pinctrl_pcie_rst_od_conf[] = {
++      PINCTRL_CONF_DESC(51, REG_PCIE_RESET_OD, PCIE0_RESET_OD_MASK),
++      PINCTRL_CONF_DESC(52, REG_PCIE_RESET_OD, PCIE1_RESET_OD_MASK),
++};
++
+ static int airoha_convert_pin_to_reg_offset(struct pinctrl_dev *pctrl_dev,
+                                           struct pinctrl_gpio_range *range,
+                                           int pin)
+@@ -2267,8 +2968,40 @@ static const struct airoha_pinctrl_match
+       },
+ };
++static const struct airoha_pinctrl_match_data an7583_pinctrl_match_data = {
++      .pins = an7583_pinctrl_pins,
++      .num_pins = ARRAY_SIZE(an7583_pinctrl_pins),
++      .grps = an7583_pinctrl_groups,
++      .num_grps = ARRAY_SIZE(an7583_pinctrl_groups),
++      .funcs = an7583_pinctrl_funcs,
++      .num_funcs = ARRAY_SIZE(an7583_pinctrl_funcs),
++      .confs_info = {
++              [AIROHA_PINCTRL_CONFS_PULLUP] = {
++                      .confs = an7583_pinctrl_pullup_conf,
++                      .num_confs = ARRAY_SIZE(an7583_pinctrl_pullup_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_PULLDOWN] = {
++                      .confs = an7583_pinctrl_pulldown_conf,
++                      .num_confs = ARRAY_SIZE(an7583_pinctrl_pulldown_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_DRIVE_E2] = {
++                      .confs = en7581_pinctrl_drive_e2_conf,
++                      .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e2_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_DRIVE_E4] = {
++                      .confs = an7583_pinctrl_drive_e4_conf,
++                      .num_confs = ARRAY_SIZE(an7583_pinctrl_drive_e4_conf),
++              },
++              [AIROHA_PINCTRL_CONFS_PCIE_RST_OD] = {
++                      .confs = an7583_pinctrl_pcie_rst_od_conf,
++                      .num_confs = ARRAY_SIZE(an7583_pinctrl_pcie_rst_od_conf),
++              },
++      },
++};
++
+ static const struct of_device_id airoha_pinctrl_of_match[] = {
+       { .compatible = "airoha,en7581-pinctrl", .data = &en7581_pinctrl_match_data },
++      { .compatible = "airoha,an7583-pinctrl", .data = &an7583_pinctrl_match_data },
+       { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, airoha_pinctrl_of_match);
diff --git a/target/linux/airoha/patches-6.12/401-02-net-dsa-mt7530-Add-AN7583-support.patch b/target/linux/airoha/patches-6.12/401-02-net-dsa-mt7530-Add-AN7583-support.patch
new file mode 100644 (file)
index 0000000..0d72a59
--- /dev/null
@@ -0,0 +1,140 @@
+From 7e112e51d48db09739dd73c90411fc8a5635747f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Thu, 22 May 2025 15:13:10 +0200
+Subject: [PATCH 2/3] net: dsa: mt7530: Add AN7583 support
+
+Add Airoha AN7583 Switch support. This is based on Airoha EN7581 that is
+based on Mediatek MT7988 Switch.
+
+Airoha AN7583 require additional tweak to the GEPHY_CONN_CFG register to
+make the internal PHY work.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/net/dsa/mt7530-mmio.c |  1 +
+ drivers/net/dsa/mt7530.c      | 24 ++++++++++++++++++++++--
+ drivers/net/dsa/mt7530.h      | 18 ++++++++++++++----
+ 3 files changed, 37 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/dsa/mt7530-mmio.c
++++ b/drivers/net/dsa/mt7530-mmio.c
+@@ -11,6 +11,7 @@
+ #include "mt7530.h"
+ static const struct of_device_id mt7988_of_match[] = {
++      { .compatible = "airoha,an7583-switch", .data = &mt753x_table[ID_AN7583], },
+       { .compatible = "airoha,en7581-switch", .data = &mt753x_table[ID_EN7581], },
+       { .compatible = "mediatek,mt7988-switch", .data = &mt753x_table[ID_MT7988], },
+       { /* sentinel */ },
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1153,7 +1153,7 @@ mt753x_cpu_port_enable(struct dsa_switch
+        * is affine to the inbound user port.
+        */
+       if (priv->id == ID_MT7531 || priv->id == ID_MT7988 ||
+-          priv->id == ID_EN7581)
++          priv->id == ID_EN7581 || priv->id == ID_AN7583)
+               mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port)));
+       /* CPU port gets connected to all user ports of
+@@ -2589,7 +2589,7 @@ mt7531_setup_common(struct dsa_switch *d
+       mt7530_set(priv, MT753X_AGC, LOCAL_EN);
+       /* Enable Special Tag for rx frames */
+-      if (priv->id == ID_EN7581)
++      if (priv->id == ID_EN7581 || priv->id == ID_AN7583)
+               mt7530_write(priv, MT753X_CPORT_SPTAG_CFG,
+                            CPORT_SW2FE_STAG_EN | CPORT_FE2SW_STAG_EN);
+@@ -3157,6 +3157,16 @@ static int mt7988_setup(struct dsa_switc
+       reset_control_deassert(priv->rstc);
+       usleep_range(20, 50);
++      /* AN7583 require additional tweak to CONN_CFG */
++      if (priv->id == ID_AN7583)
++              mt7530_rmw(priv, AN7583_GEPHY_CONN_CFG,
++                         AN7583_CSR_DPHY_CKIN_SEL |
++                         AN7583_CSR_PHY_CORE_REG_CLK_SEL |
++                         AN7583_CSR_ETHER_AFE_PWD,
++                         AN7583_CSR_DPHY_CKIN_SEL |
++                         AN7583_CSR_PHY_CORE_REG_CLK_SEL |
++                         FIELD_PREP(AN7583_CSR_ETHER_AFE_PWD, 0));
++
+       /* Reset the switch PHYs */
+       mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_PHY_RST);
+@@ -3253,6 +3263,16 @@ const struct mt753x_info mt753x_table[]
+               .pcs_ops = &mt7530_pcs_ops,
+               .sw_setup = mt7988_setup,
+               .phy_read_c22 = mt7531_ind_c22_phy_read,
++              .phy_write_c22 = mt7531_ind_c22_phy_write,
++              .phy_read_c45 = mt7531_ind_c45_phy_read,
++              .phy_write_c45 = mt7531_ind_c45_phy_write,
++              .mac_port_get_caps = en7581_mac_port_get_caps,
++      },
++      [ID_AN7583] = {
++              .id = ID_AN7583,
++              .pcs_ops = &mt7530_pcs_ops,
++              .sw_setup = mt7988_setup,
++              .phy_read_c22 = mt7531_ind_c22_phy_read,
+               .phy_write_c22 = mt7531_ind_c22_phy_write,
+               .phy_read_c45 = mt7531_ind_c45_phy_read,
+               .phy_write_c45 = mt7531_ind_c45_phy_write,
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -20,6 +20,7 @@ enum mt753x_id {
+       ID_MT7531 = 2,
+       ID_MT7988 = 3,
+       ID_EN7581 = 4,
++      ID_AN7583 = 5,
+ };
+ #define       NUM_TRGMII_CTRL                 5
+@@ -66,7 +67,8 @@ enum mt753x_id {
+ #define MT753X_MIRROR_REG(id)         ((id == ID_MT7531 || \
+                                         id == ID_MT7988 || \
+-                                        id == ID_EN7581) ? \
++                                        id == ID_EN7581 || \
++                                        id == ID_AN7583) ? \
+                                        MT7531_CFC : MT753X_MFC)
+ #define MT753X_MIRROR_EN(id)          ((id == ID_MT7531 || \
+@@ -76,19 +78,22 @@ enum mt753x_id {
+ #define MT753X_MIRROR_PORT_MASK(id)   ((id == ID_MT7531 || \
+                                         id == ID_MT7988 || \
+-                                        id == ID_EN7581) ? \
++                                        id == ID_EN7581 || \
++                                        id == ID_AN7583) ? \
+                                        MT7531_MIRROR_PORT_MASK : \
+                                        MT7530_MIRROR_PORT_MASK)
+ #define MT753X_MIRROR_PORT_GET(id, val)       ((id == ID_MT7531 || \
+                                         id == ID_MT7988 || \
+-                                        id == ID_EN7581) ? \
++                                        id == ID_EN7581 || \
++                                        id == ID_AN7583) ? \
+                                        MT7531_MIRROR_PORT_GET(val) : \
+                                        MT7530_MIRROR_PORT_GET(val))
+ #define MT753X_MIRROR_PORT_SET(id, val)       ((id == ID_MT7531 || \
+                                         id == ID_MT7988 || \
+-                                        id == ID_EN7581) ? \
++                                        id == ID_EN7581 || \
++                                        id == ID_AN7583) ? \
+                                        MT7531_MIRROR_PORT_SET(val) : \
+                                        MT7530_MIRROR_PORT_SET(val))
+@@ -619,6 +624,11 @@ enum mt7531_xtal_fsel {
+ #define  CPORT_SW2FE_STAG_EN          BIT(1)
+ #define  CPORT_FE2SW_STAG_EN          BIT(0)
++#define AN7583_GEPHY_CONN_CFG         0x7c14
++#define  AN7583_CSR_DPHY_CKIN_SEL     BIT(31)
++#define  AN7583_CSR_PHY_CORE_REG_CLK_SEL BIT(30)
++#define  AN7583_CSR_ETHER_AFE_PWD     GENMASK(28, 24)
++
+ /* Registers for LED GPIO control (MT7530 only)
+  * All registers follow this pattern:
+  * [ 2: 0]  port 0
diff --git a/target/linux/airoha/patches-6.12/402-01-thermal-airoha-convert-to-regmap-API.patch b/target/linux/airoha/patches-6.12/402-01-thermal-airoha-convert-to-regmap-API.patch
new file mode 100644 (file)
index 0000000..9414bef
--- /dev/null
@@ -0,0 +1,194 @@
+From 7d55e75edc87022a4c1820588f70a80cebb13c5f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 23 May 2025 19:34:54 +0200
+Subject: [PATCH 1/5] thermal: airoha: convert to regmap API
+
+In preparation for support of Airoha AN7583, convert the driver to
+regmap API. This is needed as Airoha AN7583 will be based on syscon
+regmap.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/thermal/airoha_thermal.c | 72 +++++++++++++++++++-------------
+ 1 file changed, 42 insertions(+), 30 deletions(-)
+
+--- a/drivers/thermal/airoha_thermal.c
++++ b/drivers/thermal/airoha_thermal.c
+@@ -194,7 +194,7 @@
+ #define AIROHA_MAX_SAMPLES                    6
+ struct airoha_thermal_priv {
+-      void __iomem *base;
++      struct regmap *map;
+       struct regmap *chip_scu;
+       struct resource scu_adc_res;
+@@ -265,8 +265,8 @@ static int airoha_thermal_set_trips(stru
+                              RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK)));
+               /* We offset the high temp of 1°C to trigger correct event */
+-              writel(TEMP_TO_RAW(priv, high) >> 4,
+-                     priv->base + EN7581_TEMPOFFSETH);
++              regmap_write(priv->map, EN7581_TEMPOFFSETH,
++                           TEMP_TO_RAW(priv, high) >> 4);
+               enable_monitor = true;
+       }
+@@ -277,15 +277,15 @@ static int airoha_thermal_set_trips(stru
+                             RAW_TO_TEMP(priv, FIELD_MAX(EN7581_DOUT_TADC_MASK)));
+               /* We offset the low temp of 1°C to trigger correct event */
+-              writel(TEMP_TO_RAW(priv, low) >> 4,
+-                     priv->base + EN7581_TEMPOFFSETL);
++              regmap_write(priv->map, EN7581_TEMPOFFSETL,
++                           TEMP_TO_RAW(priv, high) >> 4);
+               enable_monitor = true;
+       }
+       /* Enable sensor 0 monitor after trip are set */
+       if (enable_monitor)
+-              writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0);
++              regmap_write(priv->map, EN7581_TEMPMONCTL0, EN7581_SENSE0_EN);
+       return 0;
+ }
+@@ -302,7 +302,7 @@ static irqreturn_t airoha_thermal_irq(in
+       bool update = false;
+       u32 status;
+-      status = readl(priv->base + EN7581_TEMPMONINTSTS);
++      regmap_read(priv->map, EN7581_TEMPMONINTSTS, &status);
+       switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) {
+       case EN7581_HOFSINTSTS0:
+               event = THERMAL_TRIP_VIOLATED;
+@@ -318,7 +318,7 @@ static irqreturn_t airoha_thermal_irq(in
+       }
+       /* Reset Interrupt */
+-      writel(status, priv->base + EN7581_TEMPMONINTSTS);
++      regmap_write(priv->map, EN7581_TEMPMONINTSTS, status);
+       if (update)
+               thermal_zone_device_update(priv->tz, event);
+@@ -336,11 +336,11 @@ static void airoha_thermal_setup_adc_val
+       /* sleep 10 ms for ADC to enable */
+       usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
+-      efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG);
++      regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info);
+       if (efuse_calib_info) {
+               priv->default_offset = FIELD_GET(EN7581_EFUSE_TEMP_OFFSET, efuse_calib_info);
+               /* Different slope are applied if the sensor is used for CPU or for package */
+-              cpu_sensor = readl(priv->base + EN7581_EFUSE_TEMP_CPU_SENSOR_REG);
++              regmap_read(priv->map, EN7581_EFUSE_TEMP_CPU_SENSOR_REG, &cpu_sensor);
+               if (cpu_sensor) {
+                       priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT;
+                       priv->init_temp = EN7581_INIT_TEMP_FTK_X10;
+@@ -359,8 +359,8 @@ static void airoha_thermal_setup_adc_val
+ static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv)
+ {
+       /* Set measure mode */
+-      writel(FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4),
+-             priv->base + EN7581_TEMPMSRCTL0);
++      regmap_write(priv->map, EN7581_TEMPMSRCTL0,
++                   FIELD_PREP(EN7581_MSRCTL0, EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4));
+       /*
+        * Configure ADC valid reading addr
+@@ -375,15 +375,15 @@ static void airoha_thermal_setup_monitor
+        * We set valid instead of volt as we don't enable valid/volt
+        * split reading and AHB read valid addr in such case.
+        */
+-      writel(priv->scu_adc_res.start + EN7581_DOUT_TADC,
+-             priv->base + EN7581_TEMPADCVALIDADDR);
++      regmap_write(priv->map, EN7581_TEMPADCVALIDADDR,
++                   priv->scu_adc_res.start + EN7581_DOUT_TADC);
+       /*
+        * Configure valid bit on a fake value of bit 16. The ADC outputs
+        * max of 2 bytes for voltage.
+        */
+-      writel(FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16),
+-             priv->base + EN7581_TEMPADCVALIDMASK);
++      regmap_write(priv->map, EN7581_TEMPADCVALIDMASK,
++                   FIELD_PREP(EN7581_ADV_RD_VALID_POS, 16));
+       /*
+        * AHB supports max 12 bytes for ADC voltage. Shift the read
+@@ -391,40 +391,52 @@ static void airoha_thermal_setup_monitor
+        * in the order of half a Â°C and is acceptable in the context
+        * of triggering interrupt in critical condition.
+        */
+-      writel(FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4),
+-             priv->base + EN7581_TEMPADCVOLTAGESHIFT);
++      regmap_write(priv->map, EN7581_TEMPADCVOLTAGESHIFT,
++                   FIELD_PREP(EN7581_ADC_VOLTAGE_SHIFT, 4));
+       /* BUS clock is 300MHz counting unit is 3 * 68.64 * 256 = 52.715us */
+-      writel(FIELD_PREP(EN7581_PERIOD_UNIT, 3),
+-             priv->base + EN7581_TEMPMONCTL1);
++      regmap_write(priv->map, EN7581_TEMPMONCTL1,
++                   FIELD_PREP(EN7581_PERIOD_UNIT, 3));
+       /*
+        * filt interval is 1 * 52.715us = 52.715us,
+        * sen interval is 379 * 52.715us = 19.97ms
+        */
+-      writel(FIELD_PREP(EN7581_FILT_INTERVAL, 1) |
+-             FIELD_PREP(EN7581_FILT_INTERVAL, 379),
+-             priv->base + EN7581_TEMPMONCTL2);
++      regmap_write(priv->map, EN7581_TEMPMONCTL2,
++                   FIELD_PREP(EN7581_FILT_INTERVAL, 1) |
++                   FIELD_PREP(EN7581_FILT_INTERVAL, 379));
+       /* AHB poll is set to 146 * 68.64 = 10.02us */
+-      writel(FIELD_PREP(EN7581_ADC_POLL_INTVL, 146),
+-             priv->base + EN7581_TEMPAHBPOLL);
++      regmap_write(priv->map, EN7581_TEMPAHBPOLL,
++                   FIELD_PREP(EN7581_ADC_POLL_INTVL, 146));
+ }
++static const struct regmap_config airoha_thermal_regmap_config = {
++      .reg_bits               = 32,
++      .reg_stride             = 4,
++      .val_bits               = 32,
++};
++
+ static int airoha_thermal_probe(struct platform_device *pdev)
+ {
+       struct airoha_thermal_priv *priv;
+       struct device_node *chip_scu_np;
+       struct device *dev = &pdev->dev;
++      void __iomem *base;
+       int irq, ret;
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+-      priv->base = devm_platform_ioremap_resource(pdev, 0);
+-      if (IS_ERR(priv->base))
+-              return PTR_ERR(priv->base);
++      base = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      priv->map = devm_regmap_init_mmio(dev, base,
++                                        &airoha_thermal_regmap_config);
++      if (IS_ERR(priv->map))
++              return PTR_ERR(priv->map);
+       chip_scu_np = of_parse_phandle(dev->of_node, "airoha,chip-scu", 0);
+       if (!chip_scu_np)
+@@ -462,8 +474,8 @@ static int airoha_thermal_probe(struct p
+       platform_set_drvdata(pdev, priv);
+       /* Enable LOW and HIGH interrupt */
+-      writel(EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0,
+-             priv->base + EN7581_TEMPMONINT);
++      regmap_write(priv->map, EN7581_TEMPMONINT,
++                   EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0);
+       return 0;
+ }
diff --git a/target/linux/airoha/patches-6.12/402-02-thermal-drivers-airoha-Generalize-probe-function.patch b/target/linux/airoha/patches-6.12/402-02-thermal-drivers-airoha-Generalize-probe-function.patch
new file mode 100644 (file)
index 0000000..b306b23
--- /dev/null
@@ -0,0 +1,226 @@
+From 6c0f01b16687dc582f0470a5d5b20084fb3a290f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 23 May 2025 19:48:32 +0200
+Subject: [PATCH 2/5] thermal/drivers: airoha: Generalize probe function
+
+In preparation for support of Airoha AN7583, generalize the probe
+function to address for the 2 SoC differece.
+
+Implement a match_data struct where it's possible to define a more
+specific probe and post_probe function and specific thermal ops and
+pllrg protect value.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/thermal/airoha_thermal.c | 102 +++++++++++++++++++++++--------
+ 1 file changed, 75 insertions(+), 27 deletions(-)
+
+--- a/drivers/thermal/airoha_thermal.c
++++ b/drivers/thermal/airoha_thermal.c
+@@ -198,12 +198,23 @@ struct airoha_thermal_priv {
+       struct regmap *chip_scu;
+       struct resource scu_adc_res;
++      u32 pllrg_protect;
++
+       struct thermal_zone_device *tz;
+       int init_temp;
+       int default_slope;
+       int default_offset;
+ };
++struct airoha_thermal_soc_data {
++      u32 pllrg_protect;
++
++      const struct thermal_zone_device_ops *thdev_ops;
++      int (*probe)(struct platform_device *pdev,
++                   struct airoha_thermal_priv *priv);
++      int (*post_probe)(struct platform_device *pdev);
++};
++
+ static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv)
+ {
+       u32 val;
+@@ -220,7 +231,8 @@ static void airoha_init_thermal_ADC_mode
+       regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg);
+       /* Give access to thermal regs */
+-      regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, EN7581_SCU_THERMAL_PROTECT_KEY);
++      regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT,
++                   priv->pllrg_protect);
+       adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1);
+       regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux);
+@@ -228,7 +240,7 @@ static void airoha_init_thermal_ADC_mode
+       regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg);
+ }
+-static int airoha_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
++static int en7581_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
+ {
+       struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
+       int min_value, max_value, avg_value, value;
+@@ -253,7 +265,7 @@ static int airoha_thermal_get_temp(struc
+       return 0;
+ }
+-static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low,
++static int en7581_thermal_set_trips(struct thermal_zone_device *tz, int low,
+                                   int high)
+ {
+       struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
+@@ -290,12 +302,12 @@ static int airoha_thermal_set_trips(stru
+       return 0;
+ }
+-static const struct thermal_zone_device_ops thdev_ops = {
+-      .get_temp = airoha_thermal_get_temp,
+-      .set_trips = airoha_thermal_set_trips,
++static const struct thermal_zone_device_ops en7581_thdev_ops = {
++      .get_temp = en7581_thermal_get_temp,
++      .set_trips = en7581_thermal_set_trips,
+ };
+-static irqreturn_t airoha_thermal_irq(int irq, void *data)
++static irqreturn_t en7581_thermal_irq(int irq, void *data)
+ {
+       struct airoha_thermal_priv *priv = data;
+       enum thermal_notify_event event;
+@@ -326,7 +338,7 @@ static irqreturn_t airoha_thermal_irq(in
+       return IRQ_HANDLED;
+ }
+-static void airoha_thermal_setup_adc_val(struct device *dev,
++static void en7581_thermal_setup_adc_val(struct device *dev,
+                                        struct airoha_thermal_priv *priv)
+ {
+       u32 efuse_calib_info, cpu_sensor;
+@@ -356,7 +368,7 @@ static void airoha_thermal_setup_adc_val
+       }
+ }
+-static void airoha_thermal_setup_monitor(struct airoha_thermal_priv *priv)
++static void en7581_thermal_setup_monitor(struct airoha_thermal_priv *priv)
+ {
+       /* Set measure mode */
+       regmap_write(priv->map, EN7581_TEMPMSRCTL0,
+@@ -411,30 +423,26 @@ static void airoha_thermal_setup_monitor
+                    FIELD_PREP(EN7581_ADC_POLL_INTVL, 146));
+ }
+-static const struct regmap_config airoha_thermal_regmap_config = {
++static const struct regmap_config en7581_thermal_regmap_config = {
+       .reg_bits               = 32,
+       .reg_stride             = 4,
+       .val_bits               = 32,
+ };
+-static int airoha_thermal_probe(struct platform_device *pdev)
++static int en7581_thermal_probe(struct platform_device *pdev,
++                              struct airoha_thermal_priv *priv)
+ {
+-      struct airoha_thermal_priv *priv;
+       struct device_node *chip_scu_np;
+       struct device *dev = &pdev->dev;
+       void __iomem *base;
+       int irq, ret;
+-      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+-      if (!priv)
+-              return -ENOMEM;
+-
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+       priv->map = devm_regmap_init_mmio(dev, base,
+-                                        &airoha_thermal_regmap_config);
++                                        &en7581_thermal_regmap_config);
+       if (IS_ERR(priv->map))
+               return PTR_ERR(priv->map);
+@@ -454,18 +462,55 @@ static int airoha_thermal_probe(struct p
+               return irq;
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+-                                      airoha_thermal_irq, IRQF_ONESHOT,
++                                      en7581_thermal_irq, IRQF_ONESHOT,
+                                       pdev->name, priv);
+       if (ret) {
+               dev_err(dev, "Can't get interrupt working.\n");
+               return ret;
+       }
+-      airoha_thermal_setup_monitor(priv);
+-      airoha_thermal_setup_adc_val(dev, priv);
++      en7581_thermal_setup_monitor(priv);
++      en7581_thermal_setup_adc_val(dev, priv);
++
++      return 0;
++}
++
++static int en7581_thermal_post_probe(struct platform_device *pdev)
++{
++      struct airoha_thermal_priv *priv = platform_get_drvdata(pdev);
++
++      /* Enable LOW and HIGH interrupt (if supported) */
++      regmap_write(priv->map, EN7581_TEMPMONINT,
++                   EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0);
++
++      return 0;
++}
++
++static int airoha_thermal_probe(struct platform_device *pdev)
++{
++      const struct airoha_thermal_soc_data *soc_data;
++      struct airoha_thermal_priv *priv;
++      struct device *dev = &pdev->dev;
++      int ret;
++
++      soc_data = device_get_match_data(dev);
++
++      priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
++      if (!priv)
++              return -ENOMEM;
++
++      priv->pllrg_protect = soc_data->pllrg_protect;
++
++      if (!soc_data->probe)
++              return -EINVAL;
++
++      ret = soc_data->probe(pdev, priv);
++      if (ret)
++              return ret;
+       /* register of thermal sensor and get info from DT */
+-      priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &thdev_ops);
++      priv->tz = devm_thermal_of_zone_register(dev, 0, priv,
++                                               soc_data->thdev_ops);
+       if (IS_ERR(priv->tz)) {
+               dev_err(dev, "register thermal zone sensor failed\n");
+               return PTR_ERR(priv->tz);
+@@ -473,15 +518,18 @@ static int airoha_thermal_probe(struct p
+       platform_set_drvdata(pdev, priv);
+-      /* Enable LOW and HIGH interrupt */
+-      regmap_write(priv->map, EN7581_TEMPMONINT,
+-                   EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0);
+-
+-      return 0;
++      return soc_data->post_probe ? soc_data->post_probe(pdev) : 0;
+ }
++static const struct airoha_thermal_soc_data en7581_data = {
++      .pllrg_protect = EN7581_SCU_THERMAL_PROTECT_KEY,
++      .thdev_ops = &en7581_thdev_ops,
++      .probe = &en7581_thermal_probe,
++      .post_probe = &en7581_thermal_post_probe,
++};
++
+ static const struct of_device_id airoha_thermal_match[] = {
+-      { .compatible = "airoha,en7581-thermal" },
++      { .compatible = "airoha,en7581-thermal", .data = &en7581_data },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, airoha_thermal_match);
diff --git a/target/linux/airoha/patches-6.12/402-03-thermal-drivers-airoha-generalize-get_thermal_ADC-an.patch b/target/linux/airoha/patches-6.12/402-03-thermal-drivers-airoha-generalize-get_thermal_ADC-an.patch
new file mode 100644 (file)
index 0000000..5f6ae2c
--- /dev/null
@@ -0,0 +1,129 @@
+From 1e623852d07759c3c076505193bd7f0bd3486774 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 23 May 2025 19:54:53 +0200
+Subject: [PATCH 3/5] thermal/drivers: airoha: generalize get_thermal_ADC and
+ set_mux function
+
+In preparation for support of Airoha AN7583, generalize
+get_thermal_ADC() and set_thermal_mux() with the use of reg_field API.
+
+This is to account the same logic between the current supported SoC and
+the new one but with different register address.
+
+While at it also further improve some comments and move sleep inside the
+set_thermal_mux function.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/thermal/airoha_thermal.c | 54 +++++++++++++++++++++++++-------
+ 1 file changed, 42 insertions(+), 12 deletions(-)
+
+--- a/drivers/thermal/airoha_thermal.c
++++ b/drivers/thermal/airoha_thermal.c
+@@ -193,9 +193,18 @@
+ #define AIROHA_MAX_SAMPLES                    6
++enum airoha_thermal_chip_scu_field {
++      AIROHA_THERMAL_DOUT_TADC,
++      AIROHA_THERMAL_MUX_TADC,
++
++      /* keep last */
++      AIROHA_THERMAL_FIELD_MAX,
++};
++
+ struct airoha_thermal_priv {
+       struct regmap *map;
+       struct regmap *chip_scu;
++      struct regmap_field *chip_scu_fields[AIROHA_THERMAL_FIELD_MAX];
+       struct resource scu_adc_res;
+       u32 pllrg_protect;
+@@ -219,22 +228,29 @@ static int airoha_get_thermal_ADC(struct
+ {
+       u32 val;
+-      regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val);
+-      return FIELD_GET(EN7581_DOUT_TADC_MASK, val);
++      regmap_field_read(priv->chip_scu_fields[AIROHA_THERMAL_DOUT_TADC],
++                        &val);
++      return val;
+ }
+-static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv)
++static void airoha_set_thermal_mux(struct airoha_thermal_priv *priv,
++                                 int tdac_idx)
+ {
+-      u32 adc_mux, pllrg;
++      u32 pllrg;
+       /* Save PLLRG current value */
+       regmap_read(priv->chip_scu, EN7581_PLLRG_PROTECT, &pllrg);
+-      /* Give access to thermal regs */
++      /* Give access to Thermal regs */
+       regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT,
+                    priv->pllrg_protect);
+-      adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1);
+-      regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux);
++
++      /* Configure Thermal ADC mux to tdac_idx */
++      regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC],
++                         tdac_idx);
++
++      /* Sleep 10 ms for Thermal ADC to enable */
++      usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
+       /* Restore PLLRG value on exit */
+       regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg);
+@@ -343,10 +359,8 @@ static void en7581_thermal_setup_adc_val
+ {
+       u32 efuse_calib_info, cpu_sensor;
+-      /* Setup thermal sensor to ADC mode and setup the mux to DIODE1 */
+-      airoha_init_thermal_ADC_mode(priv);
+-      /* sleep 10 ms for ADC to enable */
+-      usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
++      /* Setup Thermal Sensor to ADC mode and setup the mux to DIODE1 */
++      airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1);
+       regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info);
+       if (efuse_calib_info) {
+@@ -429,13 +443,18 @@ static const struct regmap_config en7581
+       .val_bits               = 32,
+ };
++static const struct reg_field en7581_chip_scu_fields[AIROHA_THERMAL_FIELD_MAX] = {
++      [AIROHA_THERMAL_DOUT_TADC] = REG_FIELD(EN7581_DOUT_TADC, 0, 15),
++      [AIROHA_THERMAL_MUX_TADC] = REG_FIELD(EN7581_PWD_TADC, 1, 3),
++};
++
+ static int en7581_thermal_probe(struct platform_device *pdev,
+                               struct airoha_thermal_priv *priv)
+ {
+       struct device_node *chip_scu_np;
+       struct device *dev = &pdev->dev;
+       void __iomem *base;
+-      int irq, ret;
++      int i, irq, ret;
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+@@ -454,6 +473,17 @@ static int en7581_thermal_probe(struct p
+       if (IS_ERR(priv->chip_scu))
+               return PTR_ERR(priv->chip_scu);
++      for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) {
++              struct regmap_field *field;
++
++              field = devm_regmap_field_alloc(dev, priv->chip_scu,
++                                              en7581_chip_scu_fields[i]);
++              if (IS_ERR(field))
++                      return PTR_ERR(field);
++
++              priv->chip_scu_fields[i] = field;
++      }
++
+       of_address_to_resource(chip_scu_np, 0, &priv->scu_adc_res);
+       of_node_put(chip_scu_np);
diff --git a/target/linux/airoha/patches-6.12/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch b/target/linux/airoha/patches-6.12/402-05-thermal-drivers-airoha-Add-support-for-AN7583.patch
new file mode 100644 (file)
index 0000000..5133235
--- /dev/null
@@ -0,0 +1,277 @@
+From 5891a9e5fbdf9a305b5f81e2625455efb2a886f0 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 23 May 2025 19:59:20 +0200
+Subject: [PATCH 5/5] thermal/drivers: airoha: Add support for AN7583
+
+Add support for Airoha AN7583 Thermal driver. This apply similar logic
+on how to read the temperature but totally drop support for the
+PTP_THERMAL subsystem. PTP_THERMAL subsystem was a way to trigger trip
+point from hardware by configuring how to read the temperature
+internally.
+
+This subsystem has been totally removed from Airoha AN7583 permitting
+only to read the temperature.
+
+The SoC support up to 3 sensor but the original driver always read the
+BGA sensor hence it's currently implemented reading only this specific
+sensor. Reference and values for the other 2 sensor are defined for
+further implementation if confirmed working.
+
+set_thermal_mux() is extended to also address muxing the sensor as
+AN7583 use a different way to read the temperature from 3 different
+diode. The EN7581 code is updated to account for these changes.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/thermal/airoha_thermal.c | 158 ++++++++++++++++++++++++++++++-
+ 1 file changed, 154 insertions(+), 4 deletions(-)
+
+--- a/drivers/thermal/airoha_thermal.c
++++ b/drivers/thermal/airoha_thermal.c
+@@ -18,6 +18,12 @@
+ #define EN7581_DOUT_TADC                      0x2f8
+ #define   EN7581_DOUT_TADC_MASK                       GENMASK(15, 0)
++#define AN7583_MUX_SENSOR                     0x2a0
++#define   AN7583_LOAD_ADJ                     GENMASK(3, 2)
++#define AN7583_MUX_TADC                               0x2e4
++#define   AN7583_MUX_TADC_MASK                        GENMASK(3, 1)
++#define AN7583_DOUT_TADC                      0x2f0
++
+ /* PTP_THERMAL regs */
+ #define EN7581_TEMPMONCTL0                    0x800
+ #define   EN7581_SENSE3_EN                    BIT(3)
+@@ -181,6 +187,11 @@
+ #define EN7581_SCU_THERMAL_PROTECT_KEY                0x12
+ #define EN7581_SCU_THERMAL_MUX_DIODE1         0x7
++#define AN7583_SCU_THERMAL_PROTECT_KEY                0x80
++#define AN7583_NUM_SENSOR                     3
++
++#define AIROHA_THERMAL_NO_MUX_SENSOR          -1
++
+ /* Convert temp to raw value as read from ADC ((((temp / 100) - init) * slope) / 1000) + offset */
+ #define TEMP_TO_RAW(priv, temp)                       ((((((temp) / 100) - (priv)->init_temp) * \
+                                                 (priv)->default_slope) / 1000) + \
+@@ -193,8 +204,39 @@
+ #define AIROHA_MAX_SAMPLES                    6
++/*
++ * AN7583 supports all these ADC mux but the original driver
++ * always checked temp with the AN7583_BGP_TEMP_SENSOR.
++ * Assume using the other sensor temperature is invalid and
++ * always read from AN7583_BGP_TEMP_SENSOR.
++ *
++ * On top of this it's defined that AN7583 supports 3
++ * sensor: AN7583_BGP_TEMP_SENSOR, AN7583_GBE_TEMP_SENSOR,
++ * AN7583_CPU_TEMP_SENSOR.
++ *
++ * Provide the ADC mux for reference.
++ */
++enum an7583_thermal_adc_mux {
++      AN7583_BGP_TEMP_SENSOR,
++      AN7583_PAD_AVS,
++      AN7583_CORE_POWER,
++      AN7583_AVSDAC_OUT,
++      AN7583_VCM,
++      AN7583_GBE_TEMP_SENSOR,
++      AN7583_CPU_TEMP_SENSOR,
++
++      AN7583_ADC_MUX_MAX,
++};
++
++enum an7583_thermal_diode_mux {
++      AN7583_D0_TADC,
++      AN7583_ZERO_TADC,
++      AN7583_D1_TADC,
++};
++
+ enum airoha_thermal_chip_scu_field {
+       AIROHA_THERMAL_DOUT_TADC,
++      AIROHA_THERMAL_MUX_SENSOR,
+       AIROHA_THERMAL_MUX_TADC,
+       /* keep last */
+@@ -208,6 +250,7 @@ struct airoha_thermal_priv {
+       struct resource scu_adc_res;
+       u32 pllrg_protect;
++      int current_adc;
+       struct thermal_zone_device *tz;
+       int init_temp;
+@@ -224,6 +267,24 @@ struct airoha_thermal_soc_data {
+       int (*post_probe)(struct platform_device *pdev);
+ };
++static const unsigned int an7583_thermal_coeff[AN7583_ADC_MUX_MAX] = {
++      [AN7583_BGP_TEMP_SENSOR] = 973,
++      [AN7583_GBE_TEMP_SENSOR] = 995,
++      [AN7583_CPU_TEMP_SENSOR] = 1035,
++};
++
++static const unsigned int an7583_thermal_slope[AN7583_ADC_MUX_MAX] = {
++      [AN7583_BGP_TEMP_SENSOR] = 7440,
++      [AN7583_GBE_TEMP_SENSOR] = 7620,
++      [AN7583_CPU_TEMP_SENSOR] = 8390,
++};
++
++static const unsigned int an7583_thermal_offset[AN7583_ADC_MUX_MAX] = {
++      [AN7583_BGP_TEMP_SENSOR] = 294,
++      [AN7583_GBE_TEMP_SENSOR] = 298,
++      [AN7583_CPU_TEMP_SENSOR] = 344,
++};
++
+ static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv)
+ {
+       u32 val;
+@@ -234,7 +295,7 @@ static int airoha_get_thermal_ADC(struct
+ }
+ static void airoha_set_thermal_mux(struct airoha_thermal_priv *priv,
+-                                 int tdac_idx)
++                                 int tdac_idx, int sensor_idx)
+ {
+       u32 pllrg;
+@@ -245,9 +306,20 @@ static void airoha_set_thermal_mux(struc
+       regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT,
+                    priv->pllrg_protect);
++      /*
++       * Configure Thermal Sensor mux to sensor_idx.
++       * (if not supported, sensor_idx is AIROHA_THERMAL_NO_MUX_SENSOR)
++       */
++      if (sensor_idx != AIROHA_THERMAL_NO_MUX_SENSOR)
++              regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_SENSOR],
++                                 sensor_idx);
++
+       /* Configure Thermal ADC mux to tdac_idx */
+-      regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC],
+-                         tdac_idx);
++      if (priv->current_adc != tdac_idx) {
++              regmap_field_write(priv->chip_scu_fields[AIROHA_THERMAL_MUX_TADC],
++                                 tdac_idx);
++              priv->current_adc = tdac_idx;
++      }
+       /* Sleep 10 ms for Thermal ADC to enable */
+       usleep_range(10 * USEC_PER_MSEC, 11 * USEC_PER_MSEC);
+@@ -360,7 +432,8 @@ static void en7581_thermal_setup_adc_val
+       u32 efuse_calib_info, cpu_sensor;
+       /* Setup Thermal Sensor to ADC mode and setup the mux to DIODE1 */
+-      airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1);
++      airoha_set_thermal_mux(priv, EN7581_SCU_THERMAL_MUX_DIODE1,
++                             AIROHA_THERMAL_NO_MUX_SENSOR);
+       regmap_read(priv->map, EN7581_EFUSE_TEMP_OFFSET_REG, &efuse_calib_info);
+       if (efuse_calib_info) {
+@@ -476,6 +549,10 @@ static int en7581_thermal_probe(struct p
+       for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) {
+               struct regmap_field *field;
++              /* Skip registering MUX_SENSOR field as not supported */
++              if (i == AIROHA_THERMAL_MUX_SENSOR)
++                      continue;
++
+               field = devm_regmap_field_alloc(dev, priv->chip_scu,
+                                               en7581_chip_scu_fields[i]);
+               if (IS_ERR(field))
+@@ -516,6 +593,71 @@ static int en7581_thermal_post_probe(str
+       return 0;
+ }
++static int an7583_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
++{
++      struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
++      int sensor_idx;
++      int delta_diode, delta_gain;
++      int coeff, slope, offset;
++
++      int diode_zero, diode_d0, diode_d1;
++
++      /* Always read sensor AN7583_BGP_TEMP_SENSOR */
++      sensor_idx = AN7583_BGP_TEMP_SENSOR;
++
++      coeff = an7583_thermal_coeff[sensor_idx];
++      slope = an7583_thermal_slope[sensor_idx];
++      offset = an7583_thermal_offset[sensor_idx];
++
++      airoha_set_thermal_mux(priv, sensor_idx, AN7583_ZERO_TADC);
++      diode_zero = airoha_get_thermal_ADC(priv);
++      airoha_set_thermal_mux(priv, sensor_idx, AN7583_D0_TADC);
++      diode_d0 = airoha_get_thermal_ADC(priv);
++      airoha_set_thermal_mux(priv, sensor_idx, AN7583_D1_TADC);
++      diode_d1 = airoha_get_thermal_ADC(priv);
++
++      delta_diode = diode_d1 - diode_d0;
++      delta_gain = (delta_diode * coeff) / 100 + (diode_zero - diode_d1);
++      *temp = (slope * delta_diode * 10) / delta_gain - offset * 10;
++      *temp *= 100;
++
++      return 0;
++}
++
++static const struct thermal_zone_device_ops an7583_tz_ops = {
++      .get_temp = an7583_thermal_get_temp,
++};
++
++static const struct reg_field an7583_chip_scu_fields[AIROHA_THERMAL_FIELD_MAX] = {
++      [AIROHA_THERMAL_DOUT_TADC] = REG_FIELD(AN7583_DOUT_TADC, 0, 31),
++      [AIROHA_THERMAL_MUX_TADC] = REG_FIELD(AN7583_MUX_TADC, 1, 3),
++      [AIROHA_THERMAL_MUX_SENSOR] = REG_FIELD(AN7583_MUX_SENSOR, 2, 3),
++};
++
++static int an7583_thermal_probe(struct platform_device *pdev,
++                              struct airoha_thermal_priv *priv)
++{
++      struct device *dev = &pdev->dev;
++      int i;
++
++      priv->chip_scu = device_node_to_regmap(dev->parent->of_node);
++      if (IS_ERR(priv->map))
++              return PTR_ERR(priv->map);
++
++      for (i = 0; i < AIROHA_THERMAL_FIELD_MAX; i++) {
++              struct regmap_field *field;
++
++              field = devm_regmap_field_alloc(dev, priv->chip_scu,
++                                              an7583_chip_scu_fields[i]);
++              if (IS_ERR(field))
++                      return PTR_ERR(field);
++
++              priv->chip_scu_fields[i] = field;
++      }
++
++      return 0;
++}
++
+ static int airoha_thermal_probe(struct platform_device *pdev)
+ {
+       const struct airoha_thermal_soc_data *soc_data;
+@@ -530,6 +672,7 @@ static int airoha_thermal_probe(struct p
+               return -ENOMEM;
+       priv->pllrg_protect = soc_data->pllrg_protect;
++      priv->current_adc = -1;
+       if (!soc_data->probe)
+               return -EINVAL;
+@@ -558,8 +701,15 @@ static const struct airoha_thermal_soc_d
+       .post_probe = &en7581_thermal_post_probe,
+ };
++static const struct airoha_thermal_soc_data an7583_data = {
++      .pllrg_protect = AN7583_SCU_THERMAL_PROTECT_KEY,
++      .thdev_ops = &an7583_tz_ops,
++      .probe = &an7583_thermal_probe,
++};
++
+ static const struct of_device_id airoha_thermal_match[] = {
+       { .compatible = "airoha,en7581-thermal", .data = &en7581_data },
++      { .compatible = "airoha,an7583-thermal", .data = &an7583_data },
+       {},
+ };
+ MODULE_DEVICE_TABLE(of, airoha_thermal_match);
diff --git a/target/linux/airoha/patches-6.12/403-cpufreq-airoha-Add-support-for-AN7583-SoC.patch b/target/linux/airoha/patches-6.12/403-cpufreq-airoha-Add-support-for-AN7583-SoC.patch
new file mode 100644 (file)
index 0000000..3c076b4
--- /dev/null
@@ -0,0 +1,35 @@
+From 8a38220c6bf6d79ecb1c95b083e062bd7221dea9 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sat, 9 Aug 2025 13:24:57 +0200
+Subject: [PATCH] cpufreq: airoha: Add support for AN7583 SoC
+
+New Airoha AN7583 SoC use the same exact logic to control the CPU
+frequency. Add the Device compatible to the block list for
+cpufreq-dt-plat and to the Airoha CPUFreq driver compatible list.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/cpufreq/airoha-cpufreq.c     | 1 +
+ drivers/cpufreq/cpufreq-dt-platdev.c | 1 +
+ 2 files changed, 2 insertions(+)
+
+--- a/drivers/cpufreq/airoha-cpufreq.c
++++ b/drivers/cpufreq/airoha-cpufreq.c
+@@ -121,6 +121,7 @@ static struct platform_driver airoha_cpu
+ };
+ static const struct of_device_id airoha_cpufreq_match_list[] __initconst = {
++      { .compatible = "airoha,an7583" },
+       { .compatible = "airoha,en7581" },
+       {},
+ };
+--- a/drivers/cpufreq/cpufreq-dt-platdev.c
++++ b/drivers/cpufreq/cpufreq-dt-platdev.c
+@@ -103,6 +103,7 @@ static const struct of_device_id allowli
+  * platforms using "operating-points-v2" property.
+  */
+ static const struct of_device_id blocklist[] __initconst = {
++      { .compatible = "airoha,an7583", },
+       { .compatible = "airoha,en7581", },
+       { .compatible = "allwinner,sun50i-h6", },
diff --git a/target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch b/target/linux/airoha/patches-6.12/600-01-clk-en7523-convert-driver-to-regmap-API.patch
new file mode 100644 (file)
index 0000000..85bd2c2
--- /dev/null
@@ -0,0 +1,351 @@
+From 8d5a00b3b83f76d255bcffc91d5263f72b27547a Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Fri, 7 Feb 2025 23:51:23 +0100
+Subject: [PATCH 01/10] clk: en7523: convert driver to regmap API
+
+Convert driver to regmap API, in preparation for support of Airoha
+AN7523 as the SCU will be an MFD and the regmap will be provided in the
+parent node.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 137 ++++++++++++++++++++++-----------------
+ 1 file changed, 76 insertions(+), 61 deletions(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0-only
++#include <linux/bitfield.h>
+ #include <linux/delay.h>
+ #include <linux/clk-provider.h>
+ #include <linux/io.h>
+@@ -34,6 +35,7 @@
+ #define   REG_RESET_CONTROL_PCIE2     BIT(26)
+ /* EN7581 */
+ #define REG_NP_SCU_PCIC                       0x88
++#define REG_PCIE_CTRL                 GENMASK(7, 0)
+ #define REG_NP_SCU_SSTR                       0x9c
+ #define REG_PCIE_XSI0_SEL_MASK                GENMASK(14, 13)
+ #define REG_PCIE_XSI1_SEL_MASK                GENMASK(12, 11)
+@@ -63,14 +65,14 @@ struct en_clk_desc {
+ };
+ struct en_clk_gate {
+-      void __iomem *base;
++      struct regmap *map;
+       struct clk_hw hw;
+ };
+ struct en_rst_data {
+       const u16 *bank_ofs;
+       const u16 *idx_map;
+-      void __iomem *base;
++      struct regmap *map;
+       struct reset_controller_dev rcdev;
+ };
+@@ -388,44 +390,44 @@ static u32 en7523_get_div(const struct e
+ static int en7523_pci_is_enabled(struct clk_hw *hw)
+ {
+       struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
++      u32 val;
+-      return !!(readl(cg->base + REG_PCI_CONTROL) & REG_PCI_CONTROL_REFCLK_EN1);
++      regmap_read(cg->map, REG_PCI_CONTROL, &val);
++      return !!(val & REG_PCI_CONTROL_REFCLK_EN1);
+ }
+ static int en7523_pci_prepare(struct clk_hw *hw)
+ {
+       struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+-      void __iomem *np_base = cg->base;
+-      u32 val, mask;
++      struct regmap *map = cg->map;
++      u32 mask;
+       /* Need to pull device low before reset */
+-      val = readl(np_base + REG_PCI_CONTROL);
+-      val &= ~(REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT);
+-      writel(val, np_base + REG_PCI_CONTROL);
++      regmap_clear_bits(map, REG_PCI_CONTROL,
++                        REG_PCI_CONTROL_PERSTOUT1 |
++                        REG_PCI_CONTROL_PERSTOUT);
+       usleep_range(1000, 2000);
+       /* Enable PCIe port 1 */
+-      val |= REG_PCI_CONTROL_REFCLK_EN1;
+-      writel(val, np_base + REG_PCI_CONTROL);
++      regmap_set_bits(map, REG_PCI_CONTROL,
++                      REG_PCI_CONTROL_REFCLK_EN1);
+       usleep_range(1000, 2000);
+       /* Reset to default */
+-      val = readl(np_base + REG_RESET_CONTROL1);
+       mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
+              REG_RESET_CONTROL_PCIEHB;
+-      writel(val & ~mask, np_base + REG_RESET_CONTROL1);
++      regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
+       usleep_range(1000, 2000);
+-      writel(val | mask, np_base + REG_RESET_CONTROL1);
++      regmap_set_bits(map, REG_RESET_CONTROL1, mask);
+       msleep(100);
+-      writel(val & ~mask, np_base + REG_RESET_CONTROL1);
++      regmap_clear_bits(map, REG_RESET_CONTROL1, mask);
+       usleep_range(5000, 10000);
+       /* Release device */
+       mask = REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT;
+-      val = readl(np_base + REG_PCI_CONTROL);
+-      writel(val & ~mask, np_base + REG_PCI_CONTROL);
++      regmap_clear_bits(map, REG_PCI_CONTROL, mask);
+       usleep_range(1000, 2000);
+-      writel(val | mask, np_base + REG_PCI_CONTROL);
++      regmap_set_bits(map, REG_PCI_CONTROL, mask);
+       msleep(250);
+       return 0;
+@@ -434,16 +436,13 @@ static int en7523_pci_prepare(struct clk
+ static void en7523_pci_unprepare(struct clk_hw *hw)
+ {
+       struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+-      void __iomem *np_base = cg->base;
+-      u32 val;
++      struct regmap *map = cg->map;
+-      val = readl(np_base + REG_PCI_CONTROL);
+-      val &= ~REG_PCI_CONTROL_REFCLK_EN1;
+-      writel(val, np_base + REG_PCI_CONTROL);
++      regmap_clear_bits(map, REG_PCI_CONTROL, REG_PCI_CONTROL_REFCLK_EN1);
+ }
+ static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
+-                                             void __iomem *np_base)
++                                             struct regmap *clk_map)
+ {
+       const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
+       struct clk_init_data init = {
+@@ -456,7 +455,7 @@ static struct clk_hw *en7523_register_pc
+       if (!cg)
+               return NULL;
+-      cg->base = np_base;
++      cg->map = clk_map;
+       cg->hw.init = &init;
+       if (init.ops->unprepare)
+@@ -474,21 +473,20 @@ static int en7581_pci_is_enabled(struct
+       u32 val, mask;
+       mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
+-      val = readl(cg->base + REG_PCI_CONTROL);
++      regmap_read(cg->map, REG_PCI_CONTROL, &val);
+       return (val & mask) == mask;
+ }
+ static int en7581_pci_enable(struct clk_hw *hw)
+ {
+       struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+-      void __iomem *np_base = cg->base;
+-      u32 val, mask;
++      struct regmap *map = cg->map;
++      u32 mask;
+       mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
+              REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
+              REG_PCI_CONTROL_PERSTOUT;
+-      val = readl(np_base + REG_PCI_CONTROL);
+-      writel(val | mask, np_base + REG_PCI_CONTROL);
++      regmap_set_bits(map, REG_PCI_CONTROL, mask);
+       return 0;
+ }
+@@ -496,19 +494,18 @@ static int en7581_pci_enable(struct clk_
+ static void en7581_pci_disable(struct clk_hw *hw)
+ {
+       struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+-      void __iomem *np_base = cg->base;
+-      u32 val, mask;
++      struct regmap *map = cg->map;
++      u32 mask;
+       mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1 |
+              REG_PCI_CONTROL_PERSTOUT1 | REG_PCI_CONTROL_PERSTOUT2 |
+              REG_PCI_CONTROL_PERSTOUT;
+-      val = readl(np_base + REG_PCI_CONTROL);
+-      writel(val & ~mask, np_base + REG_PCI_CONTROL);
++      regmap_clear_bits(map, REG_PCI_CONTROL, mask);
+       usleep_range(1000, 2000);
+ }
+ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+-                                 void __iomem *base, void __iomem *np_base)
++                                 struct regmap *map, struct regmap *clk_map)
+ {
+       struct clk_hw *hw;
+       u32 rate;
+@@ -517,10 +514,12 @@ static void en7523_register_clocks(struc
+       for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
+               const struct en_clk_desc *desc = &en7523_base_clks[i];
+               u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+-              u32 val = readl(base + desc->base_reg);
++              u32 val;
++
++              regmap_read(map, desc->base_reg, &val);
+               rate = en7523_get_base_rate(desc, val);
+-              val = readl(base + reg);
++              regmap_read(map, reg, &val);
+               rate /= en7523_get_div(desc, val);
+               hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+@@ -533,30 +532,47 @@ static void en7523_register_clocks(struc
+               clk_data->hws[desc->id] = hw;
+       }
+-      hw = en7523_register_pcie_clk(dev, np_base);
++      hw = en7523_register_pcie_clk(dev, clk_map);
+       clk_data->hws[EN7523_CLK_PCIE] = hw;
+ }
++static const struct regmap_config en7523_clk_regmap_config = {
++      .reg_bits = 32,
++      .val_bits = 32,
++      .reg_stride = 4,
++};
++
+ static int en7523_clk_hw_init(struct platform_device *pdev,
+                             struct clk_hw_onecell_data *clk_data)
+ {
+       void __iomem *base, *np_base;
++      struct regmap *map, *clk_map;
+       base = devm_platform_ioremap_resource(pdev, 0);
+       if (IS_ERR(base))
+               return PTR_ERR(base);
++      map = devm_regmap_init_mmio(&pdev->dev, base,
++                                  &en7523_clk_regmap_config);
++      if (IS_ERR(map))
++              return PTR_ERR(map);
++
+       np_base = devm_platform_ioremap_resource(pdev, 1);
+       if (IS_ERR(np_base))
+               return PTR_ERR(np_base);
+-      en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
++      clk_map = devm_regmap_init_mmio(&pdev->dev, np_base,
++                                      &en7523_clk_regmap_config);
++      if (IS_ERR(clk_map))
++              return PTR_ERR(clk_map);
++
++      en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
+       return 0;
+ }
+ static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+-                                 struct regmap *map, void __iomem *base)
++                                 struct regmap *map, struct regmap *clk_map)
+ {
+       struct clk_hw *hw;
+       u32 rate;
+@@ -593,7 +609,7 @@ static void en7581_register_clocks(struc
+               clk_data->hws[desc->id] = hw;
+       }
+-      hw = en7523_register_pcie_clk(dev, base);
++      hw = en7523_register_pcie_clk(dev, clk_map);
+       clk_data->hws[EN7523_CLK_PCIE] = hw;
+ }
+@@ -601,15 +617,10 @@ static int en7523_reset_update(struct re
+                              unsigned long id, bool assert)
+ {
+       struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
+-      void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
+-      u32 val;
++      u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
+-      val = readl(addr);
+-      if (assert)
+-              val |= BIT(id % RST_NR_PER_BANK);
+-      else
+-              val &= ~BIT(id % RST_NR_PER_BANK);
+-      writel(val, addr);
++      regmap_update_bits(rst_data->map, addr, BIT(id % RST_NR_PER_BANK),
++                         assert ? BIT(id % RST_NR_PER_BANK) : 0);
+       return 0;
+ }
+@@ -630,9 +641,11 @@ static int en7523_reset_status(struct re
+                              unsigned long id)
+ {
+       struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
+-      void __iomem *addr = rst_data->base + rst_data->bank_ofs[id / RST_NR_PER_BANK];
++      u32 addr = rst_data->bank_ofs[id / RST_NR_PER_BANK];
++      u32 val;
+-      return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
++      regmap_read(rst_data->map, addr, &val);
++      return !!(val & BIT(id % RST_NR_PER_BANK));
+ }
+ static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
+@@ -652,7 +665,7 @@ static const struct reset_control_ops en
+       .status = en7523_reset_status,
+ };
+-static int en7581_reset_register(struct device *dev, void __iomem *base)
++static int en7581_reset_register(struct device *dev, struct regmap *map)
+ {
+       struct en_rst_data *rst_data;
+@@ -662,7 +675,7 @@ static int en7581_reset_register(struct
+       rst_data->bank_ofs = en7581_rst_ofs;
+       rst_data->idx_map = en7581_rst_map;
+-      rst_data->base = base;
++      rst_data->map = map;
+       rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
+       rst_data->rcdev.of_xlate = en7523_reset_xlate;
+@@ -678,9 +691,8 @@ static int en7581_reset_register(struct
+ static int en7581_clk_hw_init(struct platform_device *pdev,
+                             struct clk_hw_onecell_data *clk_data)
+ {
+-      struct regmap *map;
++      struct regmap *map, *clk_map;
+       void __iomem *base;
+-      u32 val;
+       map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+       if (IS_ERR(map))
+@@ -690,15 +702,18 @@ static int en7581_clk_hw_init(struct pla
+       if (IS_ERR(base))
+               return PTR_ERR(base);
+-      en7581_register_clocks(&pdev->dev, clk_data, map, base);
+-
+-      val = readl(base + REG_NP_SCU_SSTR);
+-      val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+-      writel(val, base + REG_NP_SCU_SSTR);
+-      val = readl(base + REG_NP_SCU_PCIC);
+-      writel(val | 3, base + REG_NP_SCU_PCIC);
++      clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config);
++      if (IS_ERR(clk_map))
++              return PTR_ERR(clk_map);
++
++      en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
++
++      regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
++                        REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
++      regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
++                         FIELD_PREP(REG_PCIE_CTRL, 3));
+-      return en7581_reset_register(&pdev->dev, base);
++      return en7581_reset_register(&pdev->dev, clk_map);
+ }
+ static int en7523_clk_probe(struct platform_device *pdev)
diff --git a/target/linux/airoha/patches-6.12/600-02-clk-en7523-generalize-register-clocks-function.patch b/target/linux/airoha/patches-6.12/600-02-clk-en7523-generalize-register-clocks-function.patch
new file mode 100644 (file)
index 0000000..b8d892f
--- /dev/null
@@ -0,0 +1,258 @@
+From 36a3a919391dea2000f355125f0a161c453fcf78 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sat, 8 Feb 2025 00:08:08 +0100
+Subject: [PATCH 02/10] clk: en7523: generalize register clocks function
+
+Generalize register clocks function for Airoha EN7523 and EN7581 clocks
+driver. The same logic is applied for both clock hence code can be
+reduced and simplified by putting the base_clocks struct in the soc_data
+and passing that to a generic register clocks function.
+
+While at it rework some function to return error and use devm variant
+for clk_hw_regiser.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 148 +++++++++++++++++----------------------
+ 1 file changed, 66 insertions(+), 82 deletions(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -78,8 +78,10 @@ struct en_rst_data {
+ struct en_clk_soc_data {
+       u32 num_clocks;
++      const struct en_clk_desc *base_clks;
+       const struct clk_ops pcie_ops;
+       int (*hw_init)(struct platform_device *pdev,
++                     const struct en_clk_soc_data *soc_data,
+                      struct clk_hw_onecell_data *clk_data);
+ };
+@@ -450,10 +452,11 @@ static struct clk_hw *en7523_register_pc
+               .ops = &soc_data->pcie_ops,
+       };
+       struct en_clk_gate *cg;
++      int err;
+       cg = devm_kzalloc(dev, sizeof(*cg), GFP_KERNEL);
+       if (!cg)
+-              return NULL;
++              return ERR_PTR(-ENOMEM);
+       cg->map = clk_map;
+       cg->hw.init = &init;
+@@ -461,12 +464,62 @@ static struct clk_hw *en7523_register_pc
+       if (init.ops->unprepare)
+               init.ops->unprepare(&cg->hw);
+-      if (clk_hw_register(dev, &cg->hw))
+-              return NULL;
++      err = devm_clk_hw_register(dev, &cg->hw);
++      if (err)
++              return ERR_PTR(err);
+       return &cg->hw;
+ }
++static int en75xx_register_clocks(struct device *dev,
++                                const struct en_clk_soc_data *soc_data,
++                                struct clk_hw_onecell_data *clk_data,
++                                struct regmap *map, struct regmap *clk_map)
++{
++      struct clk_hw *hw;
++      u32 rate;
++      int i;
++
++      for (i = 0; i < soc_data->num_clocks - 1; i++) {
++              const struct en_clk_desc *desc = &soc_data->base_clks[i];
++              u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
++              int err;
++
++              err = regmap_read(map, desc->base_reg, &val);
++              if (err) {
++                      pr_err("Failed reading fixed clk rate %s: %d\n",
++                             desc->name, err);
++                      return err;
++              }
++              rate = en7523_get_base_rate(desc, val);
++
++              err = regmap_read(map, reg, &val);
++              if (err) {
++                      pr_err("Failed reading fixed clk div %s: %d\n",
++                             desc->name, err);
++                      return err;
++              }
++              rate /= en7523_get_div(desc, val);
++
++              hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
++              if (IS_ERR(hw)) {
++                      pr_err("Failed to register clk %s: %ld\n",
++                             desc->name, PTR_ERR(hw));
++                      return PTR_ERR(hw);
++              }
++
++              clk_data->hws[desc->id] = hw;
++      }
++
++      hw = en7523_register_pcie_clk(dev, clk_map);
++      if (IS_ERR(hw))
++              return PTR_ERR(hw);
++
++      clk_data->hws[EN7523_CLK_PCIE] = hw;
++
++      return 0;
++}
++
+ static int en7581_pci_is_enabled(struct clk_hw *hw)
+ {
+       struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
+@@ -504,38 +557,6 @@ static void en7581_pci_disable(struct cl
+       usleep_range(1000, 2000);
+ }
+-static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+-                                 struct regmap *map, struct regmap *clk_map)
+-{
+-      struct clk_hw *hw;
+-      u32 rate;
+-      int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
+-              const struct en_clk_desc *desc = &en7523_base_clks[i];
+-              u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+-              u32 val;
+-
+-              regmap_read(map, desc->base_reg, &val);
+-
+-              rate = en7523_get_base_rate(desc, val);
+-              regmap_read(map, reg, &val);
+-              rate /= en7523_get_div(desc, val);
+-
+-              hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+-              if (IS_ERR(hw)) {
+-                      pr_err("Failed to register clk %s: %ld\n",
+-                             desc->name, PTR_ERR(hw));
+-                      continue;
+-              }
+-
+-              clk_data->hws[desc->id] = hw;
+-      }
+-
+-      hw = en7523_register_pcie_clk(dev, clk_map);
+-      clk_data->hws[EN7523_CLK_PCIE] = hw;
+-}
+-
+ static const struct regmap_config en7523_clk_regmap_config = {
+       .reg_bits = 32,
+       .val_bits = 32,
+@@ -543,6 +564,7 @@ static const struct regmap_config en7523
+ };
+ static int en7523_clk_hw_init(struct platform_device *pdev,
++                            const struct en_clk_soc_data *soc_data,
+                             struct clk_hw_onecell_data *clk_data)
+ {
+       void __iomem *base, *np_base;
+@@ -566,51 +588,7 @@ static int en7523_clk_hw_init(struct pla
+       if (IS_ERR(clk_map))
+               return PTR_ERR(clk_map);
+-      en7523_register_clocks(&pdev->dev, clk_data, map, clk_map);
+-
+-      return 0;
+-}
+-
+-static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
+-                                 struct regmap *map, struct regmap *clk_map)
+-{
+-      struct clk_hw *hw;
+-      u32 rate;
+-      int i;
+-
+-      for (i = 0; i < ARRAY_SIZE(en7581_base_clks); i++) {
+-              const struct en_clk_desc *desc = &en7581_base_clks[i];
+-              u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
+-              int err;
+-
+-              err = regmap_read(map, desc->base_reg, &val);
+-              if (err) {
+-                      pr_err("Failed reading fixed clk rate %s: %d\n",
+-                             desc->name, err);
+-                      continue;
+-              }
+-              rate = en7523_get_base_rate(desc, val);
+-
+-              err = regmap_read(map, reg, &val);
+-              if (err) {
+-                      pr_err("Failed reading fixed clk div %s: %d\n",
+-                             desc->name, err);
+-                      continue;
+-              }
+-              rate /= en7523_get_div(desc, val);
+-
+-              hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+-              if (IS_ERR(hw)) {
+-                      pr_err("Failed to register clk %s: %ld\n",
+-                             desc->name, PTR_ERR(hw));
+-                      continue;
+-              }
+-
+-              clk_data->hws[desc->id] = hw;
+-      }
+-
+-      hw = en7523_register_pcie_clk(dev, clk_map);
+-      clk_data->hws[EN7523_CLK_PCIE] = hw;
++      return en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
+ }
+ static int en7523_reset_update(struct reset_controller_dev *rcdev,
+@@ -689,10 +667,12 @@ static int en7581_reset_register(struct
+ }
+ static int en7581_clk_hw_init(struct platform_device *pdev,
++                            const struct en_clk_soc_data *soc_data,
+                             struct clk_hw_onecell_data *clk_data)
+ {
+       struct regmap *map, *clk_map;
+       void __iomem *base;
++      int ret;
+       map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+       if (IS_ERR(map))
+@@ -706,7 +686,9 @@ static int en7581_clk_hw_init(struct pla
+       if (IS_ERR(clk_map))
+               return PTR_ERR(clk_map);
+-      en7581_register_clocks(&pdev->dev, clk_data, map, clk_map);
++      ret = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
++      if (ret)
++              return ret;
+       regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
+                         REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
+@@ -732,7 +714,7 @@ static int en7523_clk_probe(struct platf
+               return -ENOMEM;
+       clk_data->num = soc_data->num_clocks;
+-      r = soc_data->hw_init(pdev, clk_data);
++      r = soc_data->hw_init(pdev, soc_data, clk_data);
+       if (r)
+               return r;
+@@ -740,6 +722,7 @@ static int en7523_clk_probe(struct platf
+ }
+ static const struct en_clk_soc_data en7523_data = {
++      .base_clks = en7523_base_clks,
+       .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1,
+       .pcie_ops = {
+               .is_enabled = en7523_pci_is_enabled,
+@@ -750,6 +733,7 @@ static const struct en_clk_soc_data en75
+ };
+ static const struct en_clk_soc_data en7581_data = {
++      .base_clks = en7581_base_clks,
+       /* We increment num_clocks by 1 to account for additional PCIe clock */
+       .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
+       .pcie_ops = {
diff --git a/target/linux/airoha/patches-6.12/600-03-clk-en7523-convert-to-full-clk_hw-implementation.patch b/target/linux/airoha/patches-6.12/600-03-clk-en7523-convert-to-full-clk_hw-implementation.patch
new file mode 100644 (file)
index 0000000..31b5bce
--- /dev/null
@@ -0,0 +1,147 @@
+From 933030fd268ac111eb9db13b5a90b7c66cd9df41 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 17 Jun 2025 11:38:21 +0200
+Subject: [PATCH 03/10] clk: en7523: convert to full clk_hw implementation
+
+In preparation for support of .set_rate, convert the clock register
+logic from fixed clock implementation to full clk_hw implementation with
+dedicated OPs.
+
+This is just a rework and no behaviour change is expected.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 83 ++++++++++++++++++++++++++++------------
+ 1 file changed, 59 insertions(+), 24 deletions(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -69,6 +69,12 @@ struct en_clk_gate {
+       struct clk_hw hw;
+ };
++struct en_clk {
++      struct regmap *map;
++      const struct en_clk_desc *desc;
++      struct clk_hw hw;
++};
++
+ struct en_rst_data {
+       const u16 *bank_ofs;
+       const u16 *idx_map;
+@@ -471,44 +477,73 @@ static struct clk_hw *en7523_register_pc
+       return &cg->hw;
+ }
++static unsigned long en75xx_recalc_rate(struct clk_hw *hw,
++                                      unsigned long parent_rate)
++{
++      struct en_clk *c = container_of(hw, struct en_clk, hw);
++      const struct en_clk_desc *desc = c->desc;
++      struct regmap *map = c->map;
++      u32 val, reg;
++      u32 rate;
++      int err;
++
++      err = regmap_read(map, desc->base_reg, &val);
++      if (err) {
++              pr_err("Failed reading fixed clk rate %s: %d\n",
++                     desc->name, err);
++              return err;
++      }
++      rate = en7523_get_base_rate(desc, val);
++
++      reg = desc->div_reg ? desc->div_reg : desc->base_reg;
++      err = regmap_read(map, reg, &val);
++      if (err) {
++              pr_err("Failed reading fixed clk div %s: %d\n",
++                     desc->name, err);
++              return err;
++      }
++
++      return rate / en7523_get_div(desc, val);
++}
++
++static const struct clk_ops en75xx_clk_ops = {
++      .recalc_rate = en75xx_recalc_rate,
++};
++
+ static int en75xx_register_clocks(struct device *dev,
+                                 const struct en_clk_soc_data *soc_data,
+                                 struct clk_hw_onecell_data *clk_data,
+                                 struct regmap *map, struct regmap *clk_map)
+ {
+       struct clk_hw *hw;
+-      u32 rate;
+       int i;
+       for (i = 0; i < soc_data->num_clocks - 1; i++) {
+               const struct en_clk_desc *desc = &soc_data->base_clks[i];
+-              u32 val, reg = desc->div_reg ? desc->div_reg : desc->base_reg;
++              struct clk_init_data init = {
++                      .ops = &en75xx_clk_ops,
++              };
++              struct en_clk *en_clk;
+               int err;
+-              err = regmap_read(map, desc->base_reg, &val);
+-              if (err) {
+-                      pr_err("Failed reading fixed clk rate %s: %d\n",
+-                             desc->name, err);
+-                      return err;
+-              }
+-              rate = en7523_get_base_rate(desc, val);
++              en_clk = devm_kzalloc(dev, sizeof(*en_clk), GFP_KERNEL);
++              if (!en_clk)
++                      return -ENOMEM;
+-              err = regmap_read(map, reg, &val);
++              init.name = desc->name;
++
++              en_clk->map = map;
++              en_clk->desc = desc;
++              en_clk->hw.init = &init;
++
++              err = devm_clk_hw_register(dev, &en_clk->hw);
+               if (err) {
+-                      pr_err("Failed reading fixed clk div %s: %d\n",
++                      pr_err("Failed to register clk %s: %d\n",
+                              desc->name, err);
+                       return err;
+               }
+-              rate /= en7523_get_div(desc, val);
+-
+-              hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
+-              if (IS_ERR(hw)) {
+-                      pr_err("Failed to register clk %s: %ld\n",
+-                             desc->name, PTR_ERR(hw));
+-                      return PTR_ERR(hw);
+-              }
+-              clk_data->hws[desc->id] = hw;
++              clk_data->hws[desc->id] = &en_clk->hw;
+       }
+       hw = en7523_register_pcie_clk(dev, clk_map);
+@@ -672,7 +707,7 @@ static int en7581_clk_hw_init(struct pla
+ {
+       struct regmap *map, *clk_map;
+       void __iomem *base;
+-      int ret;
++      int err;
+       map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+       if (IS_ERR(map))
+@@ -686,9 +721,9 @@ static int en7581_clk_hw_init(struct pla
+       if (IS_ERR(clk_map))
+               return PTR_ERR(clk_map);
+-      ret = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
+-      if (ret)
+-              return ret;
++      err = en75xx_register_clocks(&pdev->dev, soc_data, clk_data, map, clk_map);
++      if (err)
++              return err;
+       regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
+                         REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
diff --git a/target/linux/airoha/patches-6.12/600-04-clk-en7523-add-support-for-.set_rate.patch b/target/linux/airoha/patches-6.12/600-04-clk-en7523-add-support-for-.set_rate.patch
new file mode 100644 (file)
index 0000000..fc2656a
--- /dev/null
@@ -0,0 +1,173 @@
+From fe71e8f734a5c9b808a68b8abaa0156de605df4f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 17 Jun 2025 12:28:41 +0200
+Subject: [PATCH 04/10] clk: en7523: add support for .set_rate
+
+Add support for EN7523 driver to configure rate. The SoC expose both
+base clock selector and clock divisor hence it's possible to change the
+rate.
+
+This will be especially needed for new SoC AN7583 that require changes
+for the MDIO and the eMMC.
+
+The clock were assumed correctly configured by the bootloader but this
+goes against the rule of "kernel should not depend on external
+configuration".
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 141 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 141 insertions(+)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -506,8 +506,149 @@ static unsigned long en75xx_recalc_rate(
+       return rate / en7523_get_div(desc, val);
+ }
++static int en75xx_get_base_val_for_rate(const struct en_clk_desc *desc,
++                                      int div, unsigned long rate)
++{
++      int i;
++
++      /* Single base rate */
++      if (!desc->base_bits) {
++              if (rate != desc->base_value / div)
++                      goto err;
++
++              return 0;
++      }
++
++      /* Check every base rate with provided divisor */
++      for (i = 0; i < desc->n_base_values; i++)
++              if (rate == desc->base_values[i] / div)
++                      return i;
++
++err:
++      return -EINVAL;
++}
++
++static int en75xx_get_vals_for_rate(const struct en_clk_desc *desc,
++                                  unsigned long rate,
++                                  u32 *base_val, u32 *div_val)
++{
++      int tmp_base_val = 0;
++      int tmp_div_val = 0;
++
++      if (!desc->base_bits && !desc->div_bits)
++              return -EINVAL;
++
++      /* Divisor not supported, just search in base rate */
++      if (!desc->div_bits) {
++              tmp_base_val = en75xx_get_base_val_for_rate(desc, 1, rate);
++              if (tmp_base_val < 0) {
++                      pr_err("Invalid rate for clock %s\n",
++                             desc->name);
++                      return -EINVAL;
++              }
++
++              goto exit;
++      }
++
++      /* Check if div0 satisfy the request */
++      if (desc->div_val0) {
++              tmp_base_val = en75xx_get_base_val_for_rate(desc,
++                                                          desc->div_val0,
++                                                          rate);
++              if (tmp_base_val >= 0)
++                      goto exit;
++
++              /* Skip checking first divisor val */
++              tmp_div_val = 1;
++      }
++
++      /* Simulate rate with every divisor supported */
++      for (; tmp_div_val < BIT(desc->div_bits); tmp_div_val++) {
++              int div = (tmp_div_val + desc->div_offset) * desc->div_step;
++
++              tmp_base_val = en75xx_get_base_val_for_rate(desc, div,
++                                                          rate);
++              if (tmp_base_val >= 0)
++                      goto exit;
++      }
++
++      if (tmp_div_val == BIT(desc->div_bits)) {
++              pr_err("Invalid rate for clock %s\n",
++                     desc->name);
++              return -EINVAL;
++      }
++
++exit:
++      *base_val = tmp_base_val;
++      *div_val = tmp_div_val;
++
++      return 0;
++}
++
++static long en75xx_round_rate(struct clk_hw *hw, unsigned long rate,
++                            unsigned long *parent_rate)
++{
++      struct en_clk *en_clk = container_of(hw, struct en_clk, hw);
++      u32 div_val, base_val;
++      int err;
++
++      /* Just check if the rate is possible */
++      err = en75xx_get_vals_for_rate(en_clk->desc, rate,
++                                     &base_val, &div_val);
++      if (err)
++              return err;
++
++      return rate;
++}
++
++static int en75xx_set_rate(struct clk_hw *hw, unsigned long rate,
++                         unsigned long parent_rate)
++{
++      struct en_clk *en_clk = container_of(hw, struct en_clk, hw);
++      const struct en_clk_desc *desc = en_clk->desc;
++      struct regmap *map = en_clk->map;
++      u32 base_val, div_val;
++      u32 reg, val, mask;
++      int err;
++
++      err = en75xx_get_vals_for_rate(en_clk->desc, rate,
++                                     &base_val, &div_val);
++      if (err)
++              return err;
++
++      if (desc->div_bits) {
++              reg = desc->div_reg ? desc->div_reg : desc->base_reg;
++
++              mask = (BIT(desc->div_bits) - 1) << desc->div_shift;
++              val = div_val << desc->div_shift;
++
++              err = regmap_update_bits(map, reg, mask, val);
++              if (err) {
++                      pr_err("Failed to update div reg for clock %s\n",
++                             desc->name);
++                      return -EINVAL;
++              }
++      }
++
++      if (desc->base_bits) {
++              mask = (BIT(desc->base_bits) - 1) << desc->base_shift;
++              val = base_val << desc->base_shift;
++
++              err = regmap_update_bits(map, desc->base_reg, mask, val);
++              if (err) {
++                      pr_err("Failed to update reg for clock %s\n",
++                             desc->name);
++                      return -EINVAL;
++              }
++      }
++
++      return 0;
++}
++
+ static const struct clk_ops en75xx_clk_ops = {
+       .recalc_rate = en75xx_recalc_rate,
++      .round_rate = en75xx_round_rate,
++      .set_rate = en75xx_set_rate,
+ };
+ static int en75xx_register_clocks(struct device *dev,
diff --git a/target/linux/airoha/patches-6.12/600-05-clk-en7523-permit-to-reference-Chip-SCU-from-phandle.patch b/target/linux/airoha/patches-6.12/600-05-clk-en7523-permit-to-reference-Chip-SCU-from-phandle.patch
new file mode 100644 (file)
index 0000000..059d808
--- /dev/null
@@ -0,0 +1,37 @@
+From 397a132fb8173a9d728bc7c7a31ff5c0590d076f Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 17 Jun 2025 12:48:35 +0200
+Subject: [PATCH 05/10] clk: en7523: permit to reference Chip SCU from phandle
+
+In preparation for support of AN7583 and to make Chip SCU reference more
+robust, permit to reference the Chip SCU syscon regmap also with the
+"airoha,chip-scu" property in DT.
+
+Legacy implementation is kept by fallbacking in the absence of
+"airoha,chip-scu" property.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -846,11 +846,16 @@ static int en7581_clk_hw_init(struct pla
+                             const struct en_clk_soc_data *soc_data,
+                             struct clk_hw_onecell_data *clk_data)
+ {
++      struct device *dev = &pdev->dev;
+       struct regmap *map, *clk_map;
+       void __iomem *base;
+       int err;
+-      map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
++      if (of_property_present(dev->of_node, "airoha,chip-scu"))
++              map = syscon_regmap_lookup_by_phandle(dev->of_node,
++                                                    "airoha,chip-scu");
++      else
++              map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
+       if (IS_ERR(map))
+               return PTR_ERR(map);
diff --git a/target/linux/airoha/patches-6.12/600-07-clk-en7523-reword-and-clean-clk_probe-variables.patch b/target/linux/airoha/patches-6.12/600-07-clk-en7523-reword-and-clean-clk_probe-variables.patch
new file mode 100644 (file)
index 0000000..5de1768
--- /dev/null
@@ -0,0 +1,53 @@
+From d05fc5c8a9ab7bbda80e4fc728902f8d48d3e8aa Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 17 Jun 2025 14:53:56 +0200
+Subject: [PATCH 07/10] clk: en7523: reword and clean clk_probe variables
+
+Rework and clean en7523_clk_probe variables to make them consistent with
+the rest of the source. Also apply some minor cleanup for pdev
+variables.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -881,25 +881,27 @@ static int en7581_clk_hw_init(struct pla
+ static int en7523_clk_probe(struct platform_device *pdev)
+ {
+-      struct device_node *node = pdev->dev.of_node;
+       const struct en_clk_soc_data *soc_data;
+       struct clk_hw_onecell_data *clk_data;
+-      int r;
++      struct device *dev = &pdev->dev;
++      int err;
+-      soc_data = device_get_match_data(&pdev->dev);
++      soc_data = device_get_match_data(dev);
+-      clk_data = devm_kzalloc(&pdev->dev,
+-                              struct_size(clk_data, hws, soc_data->num_clocks),
++      clk_data = devm_kzalloc(dev,
++                              struct_size(clk_data, hws,
++                                          soc_data->num_clocks),
+                               GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
+       clk_data->num = soc_data->num_clocks;
+-      r = soc_data->hw_init(pdev, soc_data, clk_data);
+-      if (r)
+-              return r;
++      err = soc_data->hw_init(pdev, soc_data, clk_data);
++      if (err)
++              return err;
+-      return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
++      return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
++                                    clk_data);
+ }
+ static const struct en_clk_soc_data en7523_data = {
diff --git a/target/linux/airoha/patches-6.12/600-08-clk-en7523-add-support-for-probing-SCU-child.patch b/target/linux/airoha/patches-6.12/600-08-clk-en7523-add-support-for-probing-SCU-child.patch
new file mode 100644 (file)
index 0000000..4d57996
--- /dev/null
@@ -0,0 +1,57 @@
+From 8f1aea6f4aa61e09eb29b41ff9fffeedd5b2fc0d Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Tue, 17 Jun 2025 13:15:19 +0200
+Subject: [PATCH 08/10] clk: en7523: add support for probing SCU child
+
+On new Airoha SoC in the SCU register space additional pheriperal might
+be present aside from the clock/reset. The Airoha AN7583 SoC is an
+example of this where 2 MDIO controller are present.
+
+Introduce a bool "probe_child" to trigger probe of child node of the SCU
+node.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 17 +++++++++++++++--
+ 1 file changed, 15 insertions(+), 2 deletions(-)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -5,6 +5,7 @@
+ #include <linux/clk-provider.h>
+ #include <linux/io.h>
+ #include <linux/mfd/syscon.h>
++#include <linux/of_platform.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
+ #include <linux/regmap.h>
+@@ -83,6 +84,7 @@ struct en_rst_data {
+ };
+ struct en_clk_soc_data {
++      bool probe_child;
+       u32 num_clocks;
+       const struct en_clk_desc *base_clks;
+       const struct clk_ops pcie_ops;
+@@ -900,8 +902,19 @@ static int en7523_clk_probe(struct platf
+       if (err)
+               return err;
+-      return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
+-                                    clk_data);
++      err = of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
++                                   clk_data);
++      if (err)
++              return err;
++
++      if (soc_data->probe_child) {
++              err = of_platform_populate(dev->of_node, NULL, NULL,
++                                         dev);
++              if (err)
++                      return err;
++      }
++
++      return 0;
+ }
+ static const struct en_clk_soc_data en7523_data = {
diff --git a/target/linux/airoha/patches-6.12/600-09-dt-bindings-clock-airoha-Document-support-for-AN7583.patch b/target/linux/airoha/patches-6.12/600-09-dt-bindings-clock-airoha-Document-support-for-AN7583.patch
new file mode 100644 (file)
index 0000000..7c3430b
--- /dev/null
@@ -0,0 +1,122 @@
+From 12838dd20851a6eae67061c5f195f31981a4d8c1 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Wed, 28 May 2025 02:39:35 +0200
+Subject: [PATCH 09/10] dt-bindings: clock: airoha: Document support for AN7583
+ clock
+
+Document support for Airoha AN7583 clock. This is based on the EN7523
+clock schema with the new requirement of the "airoha,chip-scu"
+(previously optional for EN7581).
+
+Add additional binding for additional clock and reset lines.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ .../bindings/clock/airoha,en7523-scu.yaml     |  9 +++
+ include/dt-bindings/clock/en7523-clk.h        |  3 +
+ .../dt-bindings/reset/airoha,an7583-reset.h   | 61 +++++++++++++++++++
+ 3 files changed, 73 insertions(+)
+ create mode 100644 include/dt-bindings/reset/airoha,an7583-reset.h
+
+# diff --git a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+# index bce77a14c938..be9759b86fdc 100644
+# --- a/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+# +++ b/Documentation/devicetree/bindings/clock/airoha,en7523-scu.yaml
+# @@ -32,6 +32,7 @@ properties:
+#        - enum:
+#            - airoha,en7523-scu
+#            - airoha,en7581-scu
+# +          - airoha,an7583-scu
+#    reg:
+#      items:
+# @@ -82,6 +83,14 @@ allOf:
+#          reg:
+#            maxItems: 1
+# +  - if:
+# +      properties:
+# +        compatible:
+# +          const: airoha,an7583-scu
+# +    then:
+# +      required:
+# +        - airoha,chip-scu
+# +
+#  additionalProperties: false
+#  examples:
+--- a/include/dt-bindings/clock/en7523-clk.h
++++ b/include/dt-bindings/clock/en7523-clk.h
+@@ -14,4 +14,7 @@
+ #define EN7581_CLK_EMMC               8
++#define AN7583_CLK_MDIO0      9
++#define AN7583_CLK_MDIO1      10
++
+ #endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */
+--- /dev/null
++++ b/include/dt-bindings/reset/airoha,an7583-reset.h
+@@ -0,0 +1,62 @@
++/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
++/*
++ * Copyright (c) 2024 AIROHA Inc
++ * Author: Christian Marangi <ansuelsmth@gmail.com>
++ */
++
++#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_AN7583_H_
++#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_AN7583_H_
++
++/* RST_CTRL2 */
++#define AN7583_XPON_PHY_RST            0
++#define AN7583_GPON_OLT_RST            1
++#define AN7583_CPU_TIMER2_RST          2
++#define AN7583_HSUART_RST              3
++#define AN7583_UART4_RST               4
++#define AN7583_UART5_RST               5
++#define AN7583_I2C2_RST                        6
++#define AN7583_XSI_MAC_RST             7
++#define AN7583_XSI_PHY_RST             8
++#define AN7583_NPU_RST                         9
++#define AN7583_TRNG_MSTART_RST                10
++#define AN7583_DUAL_HSI0_RST          11
++#define AN7583_DUAL_HSI1_RST          12
++#define AN7583_DUAL_HSI0_MAC_RST      13
++#define AN7583_DUAL_HSI1_MAC_RST      14
++#define AN7583_XPON_XFI_RST           15
++#define AN7583_WDMA_RST                       16
++#define AN7583_WOE0_RST                       17
++#define AN7583_HSDMA_RST              18
++#define AN7583_TDMA_RST                       19
++#define AN7583_EMMC_RST                       20
++#define AN7583_SOE_RST                        21
++#define AN7583_XFP_MAC_RST            22
++#define AN7583_MDIO0                    23
++#define AN7583_MDIO1                    24
++/* RST_CTRL1 */
++#define AN7583_PCM1_ZSI_ISI_RST               25
++#define AN7583_FE_PDMA_RST            26
++#define AN7583_FE_QDMA_RST            27
++#define AN7583_PCM_SPIWP_RST          28
++#define AN7583_CRYPTO_RST             29
++#define AN7583_TIMER_RST              30
++#define AN7583_PCM1_RST                       31
++#define AN7583_UART_RST                       32
++#define AN7583_GPIO_RST                       33
++#define AN7583_GDMA_RST                       34
++#define AN7583_I2C_MASTER_RST         35
++#define AN7583_PCM2_ZSI_ISI_RST               36
++#define AN7583_SFC_RST                        37
++#define AN7583_UART2_RST              38
++#define AN7583_GDMP_RST                       39
++#define AN7583_FE_RST                 40
++#define AN7583_USB_HOST_P0_RST                41
++#define AN7583_GSW_RST                        42
++#define AN7583_SFC2_PCM_RST           43
++#define AN7583_PCIE0_RST              44
++#define AN7583_PCIE1_RST              45
++#define AN7583_CPU_TIMER_RST          46
++#define AN7583_PCIE_HB_RST            47
++#define AN7583_XPON_MAC_RST           48
++
++#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_AN7583_H_ */
diff --git a/target/linux/airoha/patches-6.12/600-10-clk-en7523-add-support-for-Airoha-AN7583-clock.patch b/target/linux/airoha/patches-6.12/600-10-clk-en7523-add-support-for-Airoha-AN7583-clock.patch
new file mode 100644 (file)
index 0000000..0a57e8a
--- /dev/null
@@ -0,0 +1,328 @@
+From 3c5cd99f894c23650accf19fef18b5b9bbe83941 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sat, 8 Feb 2025 00:43:27 +0100
+Subject: [PATCH 10/10] clk: en7523: add support for Airoha AN7583 clock
+
+Add support for Airoha AN7583 clock and reset.
+
+Airoha AN7583 SoC have the same register address of EN7581 but implement
+different bits and additional base clocks. Also reset are different with
+the introduction of 2 dedicated MDIO line and drop of some reset lines.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/clk/clk-en7523.c | 264 +++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 264 insertions(+)
+
+--- a/drivers/clk/clk-en7523.c
++++ b/drivers/clk/clk-en7523.c
+@@ -12,6 +12,7 @@
+ #include <linux/reset-controller.h>
+ #include <dt-bindings/clock/en7523-clk.h>
+ #include <dt-bindings/reset/airoha,en7581-reset.h>
++#include <dt-bindings/reset/airoha,an7583-reset.h>
+ #define RST_NR_PER_BANK                       32
+@@ -104,6 +105,14 @@ static const u32 bus7581_base[] = { 6000
+ static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
+ static const u32 crypto_base[] = { 540000000, 480000000 };
+ static const u32 emmc7581_base[] = { 200000000, 150000000 };
++/* AN7583 */
++static const u32 gsw7583_base[] = { 540672000, 270336000, 400000000, 200000000 };
++static const u32 emi7583_base[] = { 540672000, 480000000, 400000000, 300000000 };
++static const u32 bus7583_base[] = { 600000000, 540672000, 480000000, 400000000 };
++static const u32 spi7583_base[] = { 100000000, 12500000 };
++static const u32 npu7583_base[] = { 666000000, 800000000, 720000000, 600000000 };
++static const u32 crypto7583_base[] = { 540672000, 400000000 };
++static const u32 emmc7583_base[] = { 150000000, 200000000 };
+ static const struct en_clk_desc en7523_base_clks[] = {
+       {
+@@ -306,6 +315,138 @@ static const struct en_clk_desc en7581_b
+       }
+ };
++static const struct en_clk_desc an7583_base_clks[] = {
++      {
++              .id = EN7523_CLK_GSW,
++              .name = "gsw",
++
++              .base_reg = REG_GSW_CLK_DIV_SEL,
++              .base_bits = 2,
++              .base_shift = 8,
++              .base_values = gsw7583_base,
++              .n_base_values = ARRAY_SIZE(gsw7583_base),
++
++              .div_bits = 3,
++              .div_shift = 0,
++              .div_step = 1,
++              .div_offset = 1,
++      }, {
++              .id = EN7523_CLK_EMI,
++              .name = "emi",
++
++              .base_reg = REG_EMI_CLK_DIV_SEL,
++              .base_bits = 2,
++              .base_shift = 8,
++              .base_values = emi7583_base,
++              .n_base_values = ARRAY_SIZE(emi7583_base),
++
++              .div_bits = 3,
++              .div_shift = 0,
++              .div_step = 1,
++              .div_offset = 1,
++      }, {
++              .id = EN7523_CLK_BUS,
++              .name = "bus",
++
++              .base_reg = REG_BUS_CLK_DIV_SEL,
++              .base_bits = 2,
++              .base_shift = 8,
++              .base_values = bus7583_base,
++              .n_base_values = ARRAY_SIZE(bus7583_base),
++
++              .div_bits = 3,
++              .div_shift = 0,
++              .div_step = 1,
++              .div_offset = 1,
++      }, {
++              .id = EN7523_CLK_SLIC,
++              .name = "slic",
++
++              .base_reg = REG_SPI_CLK_FREQ_SEL,
++              .base_bits = 1,
++              .base_shift = 0,
++              .base_values = slic_base,
++              .n_base_values = ARRAY_SIZE(slic_base),
++
++              .div_reg = REG_SPI_CLK_DIV_SEL,
++              .div_bits = 5,
++              .div_shift = 24,
++              .div_val0 = 20,
++              .div_step = 2,
++      }, {
++              .id = EN7523_CLK_SPI,
++              .name = "spi",
++
++              .base_reg = REG_SPI_CLK_FREQ_SEL,
++              .base_bits = 1,
++              .base_shift = 1,
++              .base_values = spi7583_base,
++              .n_base_values = ARRAY_SIZE(spi7583_base),
++
++              .div_reg = REG_SPI_CLK_DIV_SEL,
++              .div_bits = 5,
++              .div_shift = 8,
++              .div_val0 = 40,
++              .div_step = 2,
++      }, {
++              .id = EN7523_CLK_NPU,
++              .name = "npu",
++
++              .base_reg = REG_NPU_CLK_DIV_SEL,
++              .base_bits = 2,
++              .base_shift = 9,
++              .base_values = npu7583_base,
++              .n_base_values = ARRAY_SIZE(npu7583_base),
++
++              .div_bits = 3,
++              .div_shift = 0,
++              .div_step = 1,
++              .div_offset = 1,
++      }, {
++              .id = EN7523_CLK_CRYPTO,
++              .name = "crypto",
++
++              .base_reg = REG_CRYPTO_CLKSRC2,
++              .base_bits = 1,
++              .base_shift = 0,
++              .base_values = crypto7583_base,
++              .n_base_values = ARRAY_SIZE(crypto7583_base),
++      }, {
++              .id = EN7581_CLK_EMMC,
++              .name = "emmc",
++
++              .base_reg = REG_CRYPTO_CLKSRC2,
++              .base_bits = 1,
++              .base_shift = 13,
++              .base_values = emmc7583_base,
++              .n_base_values = ARRAY_SIZE(emmc7583_base),
++      }, {
++              .id = AN7583_CLK_MDIO0,
++              .name = "mdio0",
++
++              .base_reg = REG_CRYPTO_CLKSRC2,
++
++              .base_value = 25000000,
++
++              .div_bits = 4,
++              .div_shift = 15,
++              .div_step = 1,
++              .div_offset = 1,
++      }, {
++              .id = AN7583_CLK_MDIO1,
++              .name = "mdio1",
++
++              .base_reg = REG_CRYPTO_CLKSRC2,
++
++              .base_value = 25000000,
++
++              .div_bits = 4,
++              .div_shift = 19,
++              .div_step = 1,
++              .div_offset = 1,
++      }
++};
++
+ static const u16 en7581_rst_ofs[] = {
+       REG_RST_CTRL2,
+       REG_RST_CTRL1,
+@@ -369,6 +510,60 @@ static const u16 en7581_rst_map[] = {
+       [EN7581_XPON_MAC_RST]           = RST_NR_PER_BANK + 31,
+ };
++static const u16 an7583_rst_map[] = {
++      /* RST_CTRL2 */
++      [AN7583_XPON_PHY_RST]           = 0,
++      [AN7583_GPON_OLT_RST]           = 1,
++      [AN7583_CPU_TIMER2_RST]         = 2,
++      [AN7583_HSUART_RST]             = 3,
++      [AN7583_UART4_RST]              = 4,
++      [AN7583_UART5_RST]              = 5,
++      [AN7583_I2C2_RST]               = 6,
++      [AN7583_XSI_MAC_RST]            = 7,
++      [AN7583_XSI_PHY_RST]            = 8,
++      [AN7583_NPU_RST]                = 9,
++      [AN7583_TRNG_MSTART_RST]        = 12,
++      [AN7583_DUAL_HSI0_RST]          = 13,
++      [AN7583_DUAL_HSI1_RST]          = 14,
++      [AN7583_DUAL_HSI0_MAC_RST]      = 16,
++      [AN7583_DUAL_HSI1_MAC_RST]      = 17,
++      [AN7583_XPON_XFI_RST]           = 18,
++      [AN7583_WDMA_RST]               = 19,
++      [AN7583_WOE0_RST]               = 20,
++      [AN7583_HSDMA_RST]              = 22,
++      [AN7583_TDMA_RST]               = 24,
++      [AN7583_EMMC_RST]               = 25,
++      [AN7583_SOE_RST]                = 26,
++      [AN7583_XFP_MAC_RST]            = 28,
++      [AN7583_MDIO0]                  = 30,
++      [AN7583_MDIO1]                  = 31,
++      /* RST_CTRL1 */
++      [AN7583_PCM1_ZSI_ISI_RST]       = RST_NR_PER_BANK + 0,
++      [AN7583_FE_PDMA_RST]            = RST_NR_PER_BANK + 1,
++      [AN7583_FE_QDMA_RST]            = RST_NR_PER_BANK + 2,
++      [AN7583_PCM_SPIWP_RST]          = RST_NR_PER_BANK + 4,
++      [AN7583_CRYPTO_RST]             = RST_NR_PER_BANK + 6,
++      [AN7583_TIMER_RST]              = RST_NR_PER_BANK + 8,
++      [AN7583_PCM1_RST]               = RST_NR_PER_BANK + 11,
++      [AN7583_UART_RST]               = RST_NR_PER_BANK + 12,
++      [AN7583_GPIO_RST]               = RST_NR_PER_BANK + 13,
++      [AN7583_GDMA_RST]               = RST_NR_PER_BANK + 14,
++      [AN7583_I2C_MASTER_RST]         = RST_NR_PER_BANK + 16,
++      [AN7583_PCM2_ZSI_ISI_RST]       = RST_NR_PER_BANK + 17,
++      [AN7583_SFC_RST]                = RST_NR_PER_BANK + 18,
++      [AN7583_UART2_RST]              = RST_NR_PER_BANK + 19,
++      [AN7583_GDMP_RST]               = RST_NR_PER_BANK + 20,
++      [AN7583_FE_RST]                 = RST_NR_PER_BANK + 21,
++      [AN7583_USB_HOST_P0_RST]        = RST_NR_PER_BANK + 22,
++      [AN7583_GSW_RST]                = RST_NR_PER_BANK + 23,
++      [AN7583_SFC2_PCM_RST]           = RST_NR_PER_BANK + 25,
++      [AN7583_PCIE0_RST]              = RST_NR_PER_BANK + 26,
++      [AN7583_PCIE1_RST]              = RST_NR_PER_BANK + 27,
++      [AN7583_CPU_TIMER_RST]          = RST_NR_PER_BANK + 28,
++      [AN7583_PCIE_HB_RST]            = RST_NR_PER_BANK + 29,
++      [AN7583_XPON_MAC_RST]           = RST_NR_PER_BANK + 31,
++};
++
+ static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
+ {
+       if (!desc->base_bits)
+@@ -881,6 +1076,62 @@ static int en7581_clk_hw_init(struct pla
+       return en7581_reset_register(&pdev->dev, clk_map);
+ }
++static int an7583_reset_register(struct device *dev, struct regmap *map)
++{
++      struct en_rst_data *rst_data;
++
++      rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
++      if (!rst_data)
++              return -ENOMEM;
++
++      rst_data->bank_ofs = en7581_rst_ofs;
++      rst_data->idx_map = an7583_rst_map;
++      rst_data->map = map;
++
++      rst_data->rcdev.nr_resets = ARRAY_SIZE(an7583_rst_map);
++      rst_data->rcdev.of_xlate = en7523_reset_xlate;
++      rst_data->rcdev.ops = &en7581_reset_ops;
++      rst_data->rcdev.of_node = dev->of_node;
++      rst_data->rcdev.of_reset_n_cells = 1;
++      rst_data->rcdev.owner = THIS_MODULE;
++      rst_data->rcdev.dev = dev;
++
++      return devm_reset_controller_register(dev, &rst_data->rcdev);
++}
++
++static int an7583_clk_hw_init(struct platform_device *pdev,
++                            const struct en_clk_soc_data *soc_data,
++                            struct clk_hw_onecell_data *clk_data)
++{
++      struct device *dev = &pdev->dev;
++      struct regmap *map, *clk_map;
++      void __iomem *base;
++      int err;
++
++      map = syscon_regmap_lookup_by_phandle(dev->of_node, "airoha,chip-scu");
++      if (IS_ERR(map))
++              return PTR_ERR(map);
++
++      base = devm_platform_ioremap_resource(pdev, 0);
++      if (IS_ERR(base))
++              return PTR_ERR(base);
++
++      clk_map = devm_regmap_init_mmio(&pdev->dev, base, &en7523_clk_regmap_config);
++      if (IS_ERR(clk_map))
++              return PTR_ERR(clk_map);
++
++      err = en75xx_register_clocks(dev, soc_data, clk_data, map, clk_map);
++      if (err)
++              return err;
++
++      regmap_clear_bits(clk_map, REG_NP_SCU_SSTR,
++                        REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
++      regmap_update_bits(clk_map, REG_NP_SCU_PCIC, REG_PCIE_CTRL,
++                         FIELD_PREP(REG_PCIE_CTRL, 3));
++
++      return an7583_reset_register(dev, clk_map);
++}
++
+ static int en7523_clk_probe(struct platform_device *pdev)
+ {
+       const struct en_clk_soc_data *soc_data;
+@@ -940,9 +1191,23 @@ static const struct en_clk_soc_data en75
+       .hw_init = en7581_clk_hw_init,
+ };
++static const struct en_clk_soc_data an7583_data = {
++      .probe_child = true,
++      .base_clks = an7583_base_clks,
++      /* We increment num_clocks by 1 to account for additional PCIe clock */
++      .num_clocks = ARRAY_SIZE(an7583_base_clks) + 1,
++      .pcie_ops = {
++              .is_enabled = en7581_pci_is_enabled,
++              .enable = en7581_pci_enable,
++              .disable = en7581_pci_disable,
++      },
++      .hw_init = an7583_clk_hw_init,
++};
++
+ static const struct of_device_id of_match_clk_en7523[] = {
+       { .compatible = "airoha,en7523-scu", .data = &en7523_data },
+       { .compatible = "airoha,en7581-scu", .data = &en7581_data },
++      { .compatible = "airoha,an7583-scu", .data = &an7583_data },
+       { /* sentinel */ }
+ };
diff --git a/target/linux/airoha/patches-6.12/604-01-net-pcs-airoha-add-support-for-AN7583.patch b/target/linux/airoha/patches-6.12/604-01-net-pcs-airoha-add-support-for-AN7583.patch
new file mode 100644 (file)
index 0000000..6f0b3c9
--- /dev/null
@@ -0,0 +1,3002 @@
+From 500f525a21bfc18605b23e7b39fc1d8f74393b30 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Wed, 25 Jun 2025 00:00:59 +0200
+Subject: [PATCH 6/8] net: pcs: airoha: add support for Airoha AN7583 SoC
+
+Add support for Airoha AN7583 PCS. This use a new analog PHY
+implementation that doesn't require manual calibration but makes use of
+internal algo to lock to the center of the band EYE.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/net/pcs/airoha/Kconfig             |    7 +
+ drivers/net/pcs/airoha/Makefile            |    3 +
+ drivers/net/pcs/airoha/pcs-airoha-common.c |   50 +-
+ drivers/net/pcs/airoha/pcs-airoha.h        |  430 ++++
+ drivers/net/pcs/airoha/pcs-an7583.c        | 2199 ++++++++++++++++++++
+ 5 files changed, 2686 insertions(+), 3 deletions(-)
+ create mode 100644 drivers/net/pcs/airoha/pcs-an7583.c
+
+--- a/drivers/net/pcs/airoha/Kconfig
++++ b/drivers/net/pcs/airoha/Kconfig
+@@ -9,3 +9,10 @@ config PCS_AIROHA_AN7581
+       help
+         This module provides helper to phylink for managing the Airoha
+         AN7581 PCS for SoC Ethernet and PON SERDES.
++
++config PCS_AIROHA_AN7583
++      tristate "Airoha AN7583 PCS driver"
++      select PCS_AIROHA
++      help
++        This module provides helper to phylink for managing the Airoha
++        AN7583 PCS for SoC Ethernet and PON SERDES.
+--- a/drivers/net/pcs/airoha/Makefile
++++ b/drivers/net/pcs/airoha/Makefile
+@@ -5,3 +5,6 @@ pcs-airoha-objs                        := pcs-airoha-common.o
+ ifdef CONFIG_PCS_AIROHA_AN7581
+ pcs-airoha-objs                       += pcs-an7581.o
+ endif
++ifdef CONFIG_PCS_AIROHA_AN7583
++pcs-airoha-objs                       += pcs-an7583.o
++endif
+--- a/drivers/net/pcs/airoha/pcs-airoha-common.c
++++ b/drivers/net/pcs/airoha/pcs-airoha-common.c
+@@ -19,6 +19,7 @@
+ static void airoha_pcs_setup_scu_eth(struct airoha_pcs_priv *priv,
+                                    phy_interface_t interface)
+ {
++      struct device *dev = priv->dev;
+       u32 xsi_sel;
+       switch (interface) {
+@@ -36,6 +37,12 @@ static void airoha_pcs_setup_scu_eth(str
+       regmap_update_bits(priv->scu, AIROHA_SCU_SSR3,
+                          AIROHA_SCU_ETH_XSI_SEL,
+                          xsi_sel);
++
++      /* AN7583 require additional setting */
++      if (device_is_compatible(dev, "airoha,an7583-pcs-eth"))
++              regmap_update_bits(priv->scu, AIROHA_SCU_WAN_CONF,
++                                 AIROHA_SCU_ETH_MAC_SEL,
++                                 AIROHA_SCU_ETH_MAC_SEL_XFI);
+ }
+ static void airoha_pcs_setup_scu_pon(struct airoha_pcs_priv *priv,
+@@ -100,16 +107,24 @@ static int airoha_pcs_setup_scu(struct a
+ static void airoha_pcs_init_usxgmii(struct airoha_pcs_priv *priv)
+ {
++      const struct airoha_pcs_match_data *data = priv->data;
++
+       regmap_set_bits(priv->multi_sgmii, AIROHA_PCS_MULTI_SGMII_MSG_RX_CTRL_0,
+                       AIROHA_PCS_HSGMII_XFI_SEL);
+       /* Disable Hibernation */
+-      regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1,
+-                        AIROHA_PCS_USXGMII_SPEED_SEL_H);
++      if (data->hibernation_workaround)
++              regmap_clear_bits(priv->usxgmii_pcs, AIROHA_PCS_USXGMII_PCS_CTROL_1,
++                              AIROHA_PCS_USXGMII_SPEED_SEL_H);
+       /* FIXME: wait Airoha */
+       /* Avoid PCS sending garbage to MAC in some HW revision (E0) */
+-      regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0);
++      if (data->usxgmii_ber_time_fixup)
++              regmap_write(priv->usxgmii_pcs, AIROHA_PCS_USGMII_VENDOR_DEFINE_116, 0);
++
++      if (data->usxgmii_rx_gb_out_vld_tweak)
++              regmap_clear_bits(priv->usxgmii_pcs, AN7583_PCS_USXGMII_RTL_MODIFIED,
++                                AIROHA_PCS_USXGMII_MODIFIED_RX_GB_OUT_VLD);
+ }
+ static void airoha_pcs_init_hsgmii(struct airoha_pcs_priv *priv)
+@@ -434,6 +449,13 @@ static int airoha_pcs_config(struct phyl
+                       regmap_clear_bits(priv->usxgmii_pcs,
+                                         AIROHA_PCS_USXGMII_PCS_AN_CONTROL_0,
+                                         AIROHA_PCS_USXGMII_AN_ENABLE);
++
++              if (data->usxgmii_xfi_mode_sel &&
++                  neg_mode == PHYLINK_PCS_NEG_INBAND_ENABLED)
++                      regmap_set_bits(priv->usxgmii_pcs,
++                                      AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7,
++                                      AIROHA_PCS_USXGMII_XFI_MODE_TX_SEL |
++                                      AIROHA_PCS_USXGMII_XFI_MODE_RX_SEL);
+       }
+       /* Clear any force bit that my be set by bootloader */
+@@ -985,7 +1007,8 @@ static int airoha_pcs_probe(struct platf
+        * manual rx calibration is needed. This is only limited to
+        * any SoC revision before E2.
+        */
+-      if (data->port_type == AIROHA_PCS_ETH) {
++      if (device_is_compatible(dev, "airoha,an7581-pcs-eth") &&
++          data->port_type == AIROHA_PCS_ETH) {
+               u32 val;
+               ret = regmap_read(priv->scu, AIROHA_SCU_PDIDR, &val);
+@@ -1003,6 +1026,8 @@ static int airoha_pcs_probe(struct platf
+ static const struct airoha_pcs_match_data an7581_pcs_eth = {
+       .port_type = AIROHA_PCS_ETH,
++      .hibernation_workaround = true,
++      .usxgmii_ber_time_fixup = true,
+       .bringup = an7581_pcs_bringup,
+       .link_up = an7581_pcs_phya_link_up,
+       .rxlock_workaround = an7581_pcs_rxlock_workaround,
+@@ -1010,13 +1035,33 @@ static const struct airoha_pcs_match_dat
+ static const struct airoha_pcs_match_data an7581_pcs_pon = {
+       .port_type = AIROHA_PCS_PON,
++      .hibernation_workaround = true,
++      .usxgmii_ber_time_fixup = true,
+       .bringup = an7581_pcs_bringup,
+       .link_up = an7581_pcs_phya_link_up,
+ };
++static const struct airoha_pcs_match_data an7583_pcs_eth = {
++      .port_type = AIROHA_PCS_ETH,
++      .usxgmii_rx_gb_out_vld_tweak = true,
++      .usxgmii_xfi_mode_sel = true,
++      .bringup = an7583_pcs_common_phya_bringup,
++      .link_up = an7583_pcs_common_phya_link_up,
++};
++
++static const struct airoha_pcs_match_data an7583_pcs_pon = {
++      .port_type = AIROHA_PCS_PON,
++      .usxgmii_rx_gb_out_vld_tweak = true,
++      .usxgmii_xfi_mode_sel = true,
++      .bringup = an7583_pcs_common_phya_bringup,
++      .link_up = an7583_pcs_common_phya_link_up,
++};
++
+ static const struct of_device_id airoha_pcs_of_table[] = {
+       { .compatible = "airoha,an7581-pcs-eth", .data = &an7581_pcs_eth },
+       { .compatible = "airoha,an7581-pcs-pon", .data = &an7581_pcs_pon },
++      { .compatible = "airoha,an7583-pcs-eth", .data = &an7583_pcs_eth },
++      { .compatible = "airoha,an7583-pcs-pon", .data = &an7583_pcs_pon },
+       { /* sentinel */ },
+ };
+ MODULE_DEVICE_TABLE(of, airoha_pcs_of_table);
+--- a/drivers/net/pcs/airoha/pcs-airoha.h
++++ b/drivers/net/pcs/airoha/pcs-airoha.h
+@@ -14,6 +14,9 @@
+ #define AIROHA_SCU_PDIDR                      0x5c
+ #define   AIROHA_SCU_PRODUCT_ID                       GENMASK(15, 0)
+ #define AIROHA_SCU_WAN_CONF                   0x70
++#define   AIROHA_SCU_ETH_MAC_SEL              BIT(24)
++#define   AIROHA_SCU_ETH_MAC_SEL_XFI          FIELD_PREP_CONST(AIROHA_SCU_ETH_MAC_SEL, 0x0)
++#define   AIROHA_SCU_ETH_MAC_SEL_PON          FIELD_PREP_CONST(AIROHA_SCU_ETH_MAC_SEL, 0x1)
+ #define   AIROHA_SCU_WAN_SEL                  GENMASK(7, 0)
+ #define   AIROHA_SCU_WAN_SEL_SGMII            FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x10)
+ #define   AIROHA_SCU_WAN_SEL_HSGMII           FIELD_PREP_CONST(AIROHA_SCU_WAN_SEL, 0x11)
+@@ -244,6 +247,8 @@
+ #define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_6   0x31c
+ #define   AIROHA_PCS_USXGMII_TOG_PCS_AUTONEG_STS BIT(0)
+ #define AIROHA_PCS_USXGMII_PCS_AN_CONTROL_7   0x320
++#define   AIROHA_PCS_USXGMII_XFI_MODE_TX_SEL  BIT(20)
++#define   AIROHA_PCS_USXGMII_XFI_MODE_RX_SEL  BIT(16)
+ #define   AIROHA_PCS_USXGMII_RATE_UPDATE_MODE BIT(12)
+ #define   AIROHA_PCS_USXGMII_MODE             GENMASK(10, 8)
+ #define   AIROHA_PCS_USXGMII_MODE_10000               FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x0)
+@@ -251,9 +256,27 @@
+ #define   AIROHA_PCS_USXGMII_MODE_2500                FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x2)
+ #define   AIROHA_PCS_USXGMII_MODE_1000                FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x3)
+ #define   AIROHA_PCS_USXGMII_MODE_100         FIELD_PREP_CONST(AIROHA_PCS_USXGMII_MODE, 0x4)
++#define AN7583_PCS_USXGMII_RTL_MODIFIED               0x334
++#define   AIROHA_PCS_USXGMII_MODIFIED_RX_GB_OUT_VLD BIT(25)
+ /* PMA_PHYA */
+ #define AIROHA_PCS_ANA_PXP_CMN_EN             0x0
++#define   AIROHA_PCS_ANA_CMN_VREFSEL          GENMASK(18, 16)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_8V               FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x0)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_8_25V    FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x1)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_8_5V     FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x2)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_8_75V    FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x3)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_9V               FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x4)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_9_25V    FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x5)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_9_5V     FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x6)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL_9_75V    FIELD_PREP_CONST(AIROHA_PCS_ANA_CMN_VREFSEL, 0x7)
++#define   AIROHA_PCS_ANA_CMN_VREFSEL          GENMASK(18, 16)
++/* GENMASK(2, 0) input selection from 0 to 7
++ * BIT(3) OPAMP and path EN
++ * BIT(4) Current path measurement
++ * BIT(5) voltage/current path to PAD
++ */
++#define   AIROHA_PCS_ANA_CMN_MPXSELTOP_DC     GENMASK(13, 8)
+ #define   AIROHA_PCS_ANA_CMN_EN                       BIT(0)
+ #define AIROHA_PCS_ANA_PXP_JCPLL_IB_EXT_EN    0x4
+ #define   AIROHA_PCS_ANA_JCPLL_CHP_IOFST      GENMASK(29, 24)
+@@ -347,6 +370,8 @@
+ #define   AIROHA_PCS_ANA_JCPLL_TCL_KBAND_VREF GENMASK(20, 16)
+ #define   AIROHA_PCS_ANA_JCPLL_SPARE_L                GENMASK(15, 8)
+ #define     AIROHA_PCS_ANA_JCPLL_SPARE_L_LDO  FIELD_PREP_CONST(AIROHA_PCS_ANA_JCPLL_SPARE_L, BIT(5))
++#define AIROHA_PCS_ANA_PXP_JCPLL_FREQ_MEAS_EN 0x4c
++#define   AIROHA_PCS_ANA_TXPLL_IB_EXT_EN      BIT(24)
+ #define AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS    0x50
+ #define   AIROHA_PCS_ANA_TXPLL_LPF_BC         GENMASK(28, 24)
+ #define   AIROHA_PCS_ANA_TXPLL_LPF_BR         GENMASK(20, 16)
+@@ -370,6 +395,9 @@
+ #define   AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE, 0x3)
+ #define   AIROHA_PCS_ANA_TXPLL_POSTDIV_EN     BIT(8)
+ #define   AIROHA_PCS_ANA_TXPLL_KBAND_KS               GENMASK(1, 0)
++#define AIROHA_PCS_ANA_PXP_TXPLL_PHY_CK1_EN   0x60
++#define   AIROHA_PCS_ANA_TXPLL_PHY_CK2_EN     BIT(8)
++#define   AIROHA_PCS_ANA_TXPLL_PHY_CK1_EN     BIT(0)
+ #define AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL       0x64
+ #define   AIROHA_PCS_ANA_TXPLL_PLL_RSTB               BIT(24)
+ #define   AIROHA_PCS_ANA_TXPLL_RST_DLY                GENMASK(18, 16)
+@@ -435,16 +463,41 @@
+ #define   AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT    GENMASK(25, 24)
+ #define   AIROHA_PCS_ANA_TXPLL_LDO_OUT                GENMASK(17, 16)
+ #define   AIROHA_PCS_ANA_TXPLL_SSC_PERIOD     GENMASK(15, 0)
++#define AIROHA_PCS_ANA_PXP_TXPLL_VTP_EN               0x88
++#define   AIROHA_PCS_ANA_TXPLL_VTP            GENMASK(10, 8)
++#define   AIROHA_PCS_ANA_TXPLL_VTP_EN         BIT(0)
+ #define AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF       0x94
++#define   AIROHA_PCS_ANA_TXPLL_POSTDIV_D256_EN        BIT(25) /* 0: 128 1: 256 */
++#define   AIROHA_PCS_ANA_TXPLL_VCO_KBAND_MEAS_EN BIT(24)
++#define   AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN   BIT(16)
++#define   AIROHA_PCS_ANA_TXPLL_VREF_SEL               BIT(8)
++#define   AIROHA_PCS_ANA_TXPLL_VREF_SEL_VBG   FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VREF_SEL, 0x0)
++#define   AIROHA_PCS_ANA_TXPLL_VREF_SEL_AVDD  FIELD_PREP_CONST(AIROHA_PCS_ANA_TXPLL_VREF_SEL, 0x1)
+ #define   AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF GENMASK(4, 0)
++#define AN7583_PCS_ANA_PXP_TXPLL_CHP_DOUBLE_EN        0x98
++#define   AIROHA_PCS_ANA_TXPLL_SPARE_L                BIT(0) /* ICHP_DOUBLE */
++#define AIROHA_PCS_ANA_PXP_PLL_MONCLK_SEL     0xa0
++#define   AIROHA_PCS_ANA_TDC_AUTOEN           BIT(24)
++#define AIROHA_PCS_ANA_PXP_TDC_SYNC_CK_SEL    0xa8
++#define   AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL   GENMASK(17, 16)
++#define   AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN     BIT(8)
++#define AIROHA_PCS_ANA_PXP_TX_TXLBRC_EN               0xc0
++#define   AIROHA_PCS_ANA_TX_TERMCAL_VREF_L    GENMASK(26, 24)
++#define   AIROHA_PCS_ANA_TX_TERMCAL_VREF_H    GENMASK(18, 16)
+ #define AIROHA_PCS_ANA_PXP_TX_CKLDO_EN                0xc4
+ #define   AIROHA_PCS_ANA_TX_DMEDGEGEN_EN      BIT(24)
+ #define   AIROHA_PCS_ANA_TX_CKLDO_EN          BIT(0)
++#define AIROHA_PCS_ANA_PXP_TX_TERMCAL_SELPN   0xc8
++#define   AIROHA_PCS_ANA_TX_TDC_CK_SEL                GENMASK(17, 16)
+ #define AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL      0xcc
+ #define    AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE BIT(24)
+ #define    AIROHA_PCS_ANA_RX_PHY_CK_SEL               BIT(16)
+ #define      AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_PR FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x0)
+ #define      AIROHA_PCS_ANA_RX_PHY_CK_SEL_FROM_DES FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_PHY_CK_SEL, 0x1)
++#define    AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE BIT(8)
++#define    AIROHA_PCS_ANA_RX_BUSBIT_SEL               BIT(0)
++#define      AIROHA_PCS_ANA_RX_BUSBIT_SEL_8BIT        FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_BUSBIT_SEL, 0x0)
++#define      AIROHA_PCS_ANA_RX_BUSBIT_SEL_16BIT       FIELD_PREP_CONST(AIROHA_PCS_ANA_RX_BUSBIT_SEL, 0x1)
+ #define AIROHA_PCS_ANA_PXP_RX_REV_0           0xd4
+ #define   AIROHA_PCS_ANA_RX_REV_1             GENMASK(31, 16)
+ #define     AIROHA_PCS_ANA_REV_1_FE_EQ_BIAS_CTRL GENMASK(30, 28)
+@@ -452,6 +505,16 @@
+ #define     AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL GENMASK(22, 20)
+ #define     AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK GENMASK(19, 18)
+ #define     AIROHA_PCS_ANA_REV_1_FECUR_PWDB   BIT(16)
++#define   AIROHA_PCS_ANA_RX_REV_0             GENMASK(15, 0)
++#define     AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE GENMASK(13, 12)
++#define     AIROHA_PCS_ANA_REV_0_OSCAL_FE_MODE_SET_SEL BIT(11)
++#define     AIROHA_PCS_ANA_REV_0_FE_EQ_GAIN_MODE_TRAINING BIT(10)
++#define     AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_TRAINING GENMASK(9, 8)
++#define     AIROHA_PCS_ANA_REV_0_FE_EQ_GAIN_MODE_NORMAL BIT(6)
++#define     AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL GENMASK(5, 4)
++#define     AIROHA_PCS_ANA_REV_0_VOS_PNINV    GENMASK(3, 2)
++#define     AIROHA_PCS_ANA_REV_0_PLEYEBD4     BIT(1)
++#define     AIROHA_PCS_ANA_REV_0_PLEYE_XOR_MON_EN BIT(0)
+ #define AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV               0xd8
+ #define   AIROHA_PCS_ANA_RX_TDC_CK_SEL                BIT(24)
+ #define   AIROHA_PCS_ANA_RX_PHYCK_RSTB                BIT(16)
+@@ -460,6 +523,8 @@
+ #define AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV 0xdc
+ #define   AIROHA_PCS_ANA_CDR_PD_EDGE_DIS      BIT(8)
+ #define   AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV        BIT(0)
++#define AIROHA_PCS_ANA_PXP_CDR_LPF_BOT_LIM    0xe0
++#define   AIROHA_PCS_ANA_CDR_LPF_BOT_LIM      GENMASK(18, 0)
+ #define AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO      0xe8
+ #define   AIROHA_PCS_ANA_CDR_LPF_TOP_LIM      GENMASK(26, 8)
+ #define   AIROHA_PCS_ANA_CDR_LPF_RATIO                GENMASK(1, 0)
+@@ -475,6 +540,19 @@
+ #define   AIROHA_PCS_ANA_CDR_PR_DAC_BAND      GENMASK(20, 16)
+ #define   AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL        GENMASK(10, 8)
+ #define   AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL        GENMASK(2, 0)
++#define AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV   0x100
++#define   AIROHA_PCS_ANA_CDR_PR_RSTB_BYPASS   BIT(16)
++#define   AIROHA_PCS_ANA_CDR_PR_CKREF_DIV     GENMASK(1, 0)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_1 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x0)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_2 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x1)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_4 FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x2)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_X FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV, 0x3)
++#define AIROHA_PCS_ANA_PXP_CDR_PR_TDC_REF_SEL 0x108
++#define   AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1    GENMASK(25, 24)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_1        FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x0)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_2        FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x1)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_4        FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x2)
++#define     AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_X        FIELD_PREP_CONST(AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1, 0x3)
+ #define AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN    0x10c
+ #define   AIROHA_PCS_ANA_RX_DAC_MON           GENMASK(28, 24)
+ #define   AIROHA_PCS_ANA_CDR_PR_CAP_EN                BIT(19)
+@@ -484,6 +562,7 @@
+ #define   AIROHA_PCS_ANA_CDR_PR_MONDPR_EN     BIT(0)
+ #define AIROHA_PCS_ANA_PXP_RX_DAC_RANGE               0x110
+ #define   AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL   GENMASK(25, 24)
++#define   AIROHA_PCS_ANA_RX_DAC_RANGE_EYE     GENMASK(9, 8)
+ #define AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH    0x114
+ #define   AIROHA_PCS_ANA_RX_FE_50OHMS_SEL     GENMASK(25, 24)
+ #define   AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL    GENMASK(20, 16)
+@@ -532,7 +611,70 @@
+ #define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0       0x0
+ #define   AIROHA_PCS_PMA_SW_LCPLL_EN          BIT(24)
+ #define AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1       0x4
++#define   AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER   GENMASK(31, 24)
++#define   AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER GENMASK(23, 16)
++#define   AIROHA_PCS_PMA_LCPLL_EN_TIMER               GENMASK(15, 8)
+ #define   AIROHA_PCS_PMA_LCPLL_MAN_PWDB               BIT(0)
++#define AIROHA_PCS_PMA_LCPLL_TDC_PW_0         0x10
++#define   AIROHA_PCS_PMA_LCPLL_TDC_DIG_PWDB   BIT(0)
++#define AIROHA_PCS_PMA_LCPLL_TDC_PW_5         0x24
++#define   AIROHA_PCS_PMA_LCPLL_TDC_SYNC_IN_MODE       BIT(24)
++#define   AIROHA_PCS_PMA_LCPLL_AUTOK_TDC      BIT(16)
++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_0                0x28
++#define   AIROHA_PCS_PMA_LCPLL_KI             GENMASK(10, 8)
++#define   AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC GENMASK(1, 0)
++#define   AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_32 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x0)
++#define   AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_16 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x1)
++#define   AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_8 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x2)
++#define   AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_PON_RX_CDR_DIVTDC, 0x3)
++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_1                0x2c
++#define   AIROHA_PCS_PMA_LCPLL_A_TDC          GENMASK(11, 8)
++#define   AIROHA_PCS_PMA_LCPLL_GPON_SEL               BIT(0)
++#define   AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_EPON FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_GPON_SEL, 0x0)
++#define   AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_GPON FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_GPON_SEL, 0x1)
++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_3                0x34
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_LOAD      BIT(8)
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT     GENMASK(1, 0)
++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_5                0x3c
++#define   AIROHA_PCS_PMA_LCPLL_TDC_AUTOPW_NCPO        BIT(16)
++#define AIROHA_PCS_PMA_LCPLL_TDC_FLT_6                0x40
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY GENMASK(9, 8)
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x0)
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D1 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x1)
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D2 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x2)
++#define   AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY_SEL_D3 FIELD_PREP_CONST(AIROHA_PCS_PMA_LCPLL_NCPO_CHG_DELAY, 0x3)
++#define AIROHA_PCS_PMA_LCPLL_TDC_PCW_1                0x48
++#define   AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON GENMASK(30, 0)
++#define AIROHA_PCS_PMA_LCPLL_TDC_PCW_2                0x4c
++#define   AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON GENMASK(30, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0 0x68
++#define   AIROHA_PCS_PMA_X_MAX                        GENMASK(26, 16)
++#define   AIROHA_PCS_PMA_X_MIN                        GENMASK(10, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1 0x6c
++#define   AIROHA_PCS_PMA_INDEX_MODE           BIT(16)
++#define   AIROHA_PCS_PMA_Y_MAX                        GENMASK(14, 8)
++#define   AIROHA_PCS_PMA_Y_MIN                        GENMASK(6, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2 0x70
++#define   AIROHA_PCS_PMA_EYEDUR                       GENMASK(19, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3 0x74
++#define   AIROHA_PCS_PMA_EYE_NEXTPTS          BIT(16)
++#define   AIROHA_PCS_PMA_EYE_NEXTPTS_TOGGLE   BIT(8)
++#define   AIROHA_PCS_PMA_EYE_NEXTPTS_SEL      BIT(0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0 0x78
++#define   AIROHA_PCS_PMA_EYECNT_VTH           GENMASK(15, 8)
++#define   AIROHA_PCS_PMA_EYECNT_HTH           GENMASK(7, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1 0x7c
++#define   AIROHA_PCS_PMA_EO_VTH                       GENMASK(23, 16)
++#define   AIROHA_PCS_PMA_EO_HTH                       GENMASK(10, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0 0x80
++#define   AIROHA_PCS_PMA_EYE_MASK             GENMASK(31, 24)
++#define   AIROHA_PCS_PMA_CNTFOREVER           BIT(16)
++#define   AIROHA_PCS_PMA_CNTLEN                       GENMASK(9, 0)
++#define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1       0x84
++#define   AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B  BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_EYEDUR_EN      BIT(16)
++#define   AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B   BIT(8)
++#define   AIROHA_PCS_PMA_DISB_EYEDUR_EN               BIT(0)
+ #define AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2       0x88
+ #define   AIROHA_PCS_PMA_DATA_SHIFT           BIT(8)
+ #define   AIROHA_PCS_PMA_EYECNT_FAST          BIT(0)
+@@ -564,14 +706,49 @@
+ #define   AIROHA_PCS_PMA_RX_BLWC_RDY_EN               GENMASK(15, 0)
+ #define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6        0x104
+ #define   AIROHA_PCS_PMA_RX_OS_END            GENMASK(15, 0)
++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0 0x108
++#define   AIROHA_PCS_PMA_DISB_RX_FEOS_EN      BIT(24)
++#define   AIROHA_PCS_PMA_DISB_RX_PDOS_EN      BIT(16)
++#define   AIROHA_PCS_PMA_DISB_RX_PICAL_EN     BIT(8)
++#define   AIROHA_PCS_PMA_DISB_RX_OS_EN                BIT(0)
+ #define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1 0x10c
+ #define   AIROHA_PCS_PMA_DISB_RX_RDY          BIT(24)
++#define   AIROHA_PCS_PMA_DISB_RX_BLWC_EN      BIT(16)
++#define   AIROHA_PCS_PMA_DISB_RX_OS_RDY               BIT(8)
++#define   AIROHA_PCS_PMA_DISB_RX_SDCAL_EN     BIT(0)
++#define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0 0x110
++#define   AIROHA_PCS_PMA_FORCE_RX_FEOS_EN     BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_RX_PDOS_EN     BIT(16)
++#define   AIROHA_PCS_PMA_FORCE_RX_PICAL_EN    BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_RX_OS_EN               BIT(0)
+ #define AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1 0x114
+ #define   AIROHA_PCS_PMA_FORCE_RX_RDY         BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_RX_BLWC_EN     BIT(16)
++#define   AIROHA_PCS_PMA_FORCE_RX_OS_RDY      BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN    BIT(0)
++#define AIROHA_PCS_PMA_PHY_EQ_CTRL_0          0x118
++#define   AIROHA_PCS_PMA_VEO_MASK             GENMASK(31, 24)
++#define   AIROHA_PCS_PMA_HEO_MASK             GENMASK(18, 8)
++#define   AIROHA_PCS_PMA_EQ_EN_DELAY          GENMASK(7, 0)
++#define AIROHA_PCS_PMA_PHY_EQ_CTRL_1          0x11c
++#define   AIROHA_PCS_PMA_B_ZERO_SEL           BIT(24)
++#define   AIROHA_PCS_PMA_HEO_EMPHASIS         BIT(16)
++#define   AIROHA_PCS_PMA_A_MGAIN              BIT(8)
++#define   AIROHA_PCS_PMA_A_LGAIN              BIT(0)
+ #define AIROHA_PCS_PMA_PHY_EQ_CTRL_2          0x120
+ #define   AIROHA_PCS_PMA_EQ_DEBUG_SEL         GENMASK(17, 16)
+ #define   AIROHA_PCS_PMA_FOM_NUM_ORDER                GENMASK(12, 8)
+ #define   AIROHA_PCS_PMA_A_SEL                        GENMASK(1, 0)
++#define AIROHA_PCS_PMA_SS_RX_FEOS             0x144
++#define   AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE BIT(8)
++#define   AIROHA_PCS_PMA_LFSEL                        GENMASK(7, 0)
++#define AIROHA_PCS_PMA_SS_RX_BLWC             0x148
++#define   AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM  GENMASK(29, 23)
++#define   AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM  GENMASK(22, 16)
++#define   AIROHA_PCS_PMA_EQ_BLWC_GAIN         GENMASK(11, 8)
++#define   AIROHA_PCS_PMA_EQ_BLWC_POL          BIT(0)
++#define   AIROHA_PCS_PMA_EQ_BLWC_POL_NORMAL   FIELD_PREP_CONST(AIROHA_PCS_PMA_EQ_BLWC_POL, 0x0)
++#define   AIROHA_PCS_PMA_EQ_BLWC_POL_INVERSION        FIELD_PREP_CONST(AIROHA_PCS_PMA_EQ_BLWC_POL, 0x1)
+ #define AIROHA_PCS_PMA_SS_RX_FREQ_DET_1               0x14c
+ #define   AIROHA_PCS_PMA_UNLOCK_CYCLECNT      GENMASK(31, 16)
+ #define   AIROHA_PCS_PMA_LOCK_CYCLECNT                GENMASK(15, 0)
+@@ -590,31 +767,182 @@
+ #define   AIROHA_PCS_PMA_FREQLOCK_DET_EN_WAIT FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x2)
+ #define   AIROHA_PCS_PMA_FREQLOCK_DET_EN_NORMAL       FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x3)
+ #define   AIROHA_PCS_PMA_FREQLOCK_DET_EN_RX_STATE FIELD_PREP_CONST(AIROHA_PCS_PMA_FREQLOCK_DET_EN, 0x7)
++#define AIROHA_PCS_PMA_RX_PI_CAL              0x15c
++#define   AIROHA_PCS_PMA_KPGAIN                       GENMASK(10, 8)
++#define AIROHA_PCS_PMA_RX_CAL1                        0x160
++#define   AIROHA_PCS_PMA_CAL_CYC              GENMASK(25, 24)
++#define     AIROHA_PCS_PMA_CAL_CYC_63         FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x0)
++#define     AIROHA_PCS_PMA_CAL_CYC_15         FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x1)
++#define     AIROHA_PCS_PMA_CAL_CYC_31         FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x2)
++#define     AIROHA_PCS_PMA_CAL_CYC_127                FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_CYC, 0x3)
++#define   AIROHA_PCS_PMA_CAL_STB              GENMASK(17, 16)
++#define     AIROHA_PCS_PMA_CAL_STB_5US                FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x0)
++#define     AIROHA_PCS_PMA_CAL_STB_8US                FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x1)
++#define     AIROHA_PCS_PMA_CAL_STB_16US               FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x2)
++#define     AIROHA_PCS_PMA_CAL_STB_32US               FIELD_PREP_CONST(AIROHA_PCS_PMA_CAL_STB, 0x3)
++#define   AIROHA_PCS_PMA_CAL_1US_SET          GENMASK(15, 8)
++#define   AIROHA_PCS_PMA_SIM_FAST_EN          BIT(0)
++#define AIROHA_PCS_PMA_RX_CAL2                        0x164
++#define   AIROHA_PCS_PMA_CAL_CYC_TIME         GENMASK(17, 16)
++#define   AIROHA_PCS_PMA_CAL_OUT_OS           GENMASK(11, 8)
++#define   AIROHA_PCS_PMA_CAL_OS_PULSE         BIT(0)
+ #define AIROHA_PCS_PMA_SS_RX_SIGDET_1         0x16c
+ #define   AIROHA_PCS_PMA_SIGDET_EN            BIT(0)
++#define AIROHA_PCS_PMA_RX_FLL_0                       0x170
++#define   AIROHA_PCS_PMA_KBAND_KFC            GENMASK(25, 24)
++#define     AIROHA_PCS_PMA_KBAND_KFC_8                FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x0)
++#define     AIROHA_PCS_PMA_KBAND_KFC_16               FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x1)
++#define     AIROHA_PCS_PMA_KBAND_KFC_32               FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x2)
++#define     AIROHA_PCS_PMA_KBAND_KFC_64               FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_KFC, 0x3)
++#define   AIROHA_PCS_PMA_FPKDIV                       GENMASK(18, 8)
++#define   AIROHA_PCS_PMA_KBAND_PREDIV         GENMASK(2, 0)
++#define     AIROHA_PCS_PMA_KBAND_PREDIV_1     FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x0)
++#define     AIROHA_PCS_PMA_KBAND_PREDIV_2     FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x1)
++#define     AIROHA_PCS_PMA_KBAND_PREDIV_4     FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x2)
++#define     AIROHA_PCS_PMA_KBAND_PREDIV_8     FIELD_PREP_CONST(AIROHA_PCS_PMA_KBAND_PREDIV, 0x3)
+ #define AIROHA_PCS_PMA_RX_FLL_1                       0x174
++#define   AIROHA_PCS_PMA_SYMBOL_WD            GENMASK(26, 24)
++#define   AIROHA_PCS_PMA_SETTLE_TIME_SEL      GENMASK(18, 16)
+ #define   AIROHA_PCS_PMA_LPATH_IDAC           GENMASK(10, 0)
+ #define AIROHA_PCS_PMA_RX_FLL_2                       0x178
+ #define   AIROHA_PCS_PMA_CK_RATE              GENMASK(18, 16)
+ #define   AIROHA_PCS_PMA_CK_RATE_20           FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x0)
+ #define   AIROHA_PCS_PMA_CK_RATE_10           FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x1)
+ #define   AIROHA_PCS_PMA_CK_RATE_5            FIELD_PREP_CONST(AIROHA_PCS_PMA_CK_RATE, 0x2)
++#define   AIROHA_PCS_PMA_AMP                  GENMASK(10, 8)
++#define   AIROHA_PCS_PMA_PRBS_SEL             GENMASK(2, 0)
+ #define AIROHA_PCS_PMA_RX_FLL_5                       0x184
+ #define   AIROHA_PCS_PMA_FLL_IDAC_MIN         GENMASK(26, 16)
+ #define   AIROHA_PCS_PMA_FLL_IDAC_MAX         GENMASK(10, 0)
++#define AIROHA_PCS_PMA_RX_FLL_6                       0x188
++#define  AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN BIT(24)
++#define  AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN BIT(16)
++#define  AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN BIT(8)
++#define  AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN BIT(0)
+ #define AIROHA_PCS_PMA_RX_FLL_B                       0x19c
+ #define   AIROHA_PCS_PMA_LOAD_EN              BIT(0)
++#define AIROHA_PCS_PMA_RX_PDOS_CTRL_0         0x200
++#define   AIROHA_PCS_PMA_SAP_SEL              GENMASK(18, 16)
++#define     AIROHA_PCS_PMA_SAP_SEL_SHIFT_6    FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x0)
++#define     AIROHA_PCS_PMA_SAP_SEL_SHIFT_7    FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x1)
++#define     AIROHA_PCS_PMA_SAP_SEL_SHIFT_8    FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x2)
++#define     AIROHA_PCS_PMA_SAP_SEL_SHIFT_9    FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x3)
++#define     AIROHA_PCS_PMA_SAP_SEL_SHIFT_10   FIELD_PREP_CONST(AIROHA_PCS_PMA_SAP_SEL, 0x4)
++#define   AIROHA_PCS_PMA_EYE_BLWC_ADD         BIT(8)
++#define   AIROHA_PCS_PMA_DATA_BLWC_ADD                BIT(0)
++#define AIROHA_PCS_PMA_RX_RESET_0             0x204
++#define   AIROHA_PCS_PMA_CAL_RST_B            BIT(24)
++#define   AIROHA_PCS_PMA_EQ_PI_CAL_RST_B      BIT(16)
++#define   AIROHA_PCS_PMA_FEOS_RST_B           BIT(8)
+ #define AIROHA_PCS_PMA_RX_RESET_1             0x208
+ #define   AIROHA_PCS_PMA_SIGDET_RST_B         BIT(8)
++#define   AIROHA_PCS_PMA_PDOS_RST_B           BIT(0)
++#define AIROHA_PCS_PMA_RX_DEBUG_0             0x20c
++#define   AIROHA_PCS_PMA_RO_TOGGLE            BIT(24)
++#define AIROHA_PCS_PMA_BISTCTL_CONTROL                0x210
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL      GENMASK(4, 0)
++/*        AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_0        FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x0) */
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS7        FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x1)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS9        FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x2)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS15       FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x3)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS23       FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x4)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS31       FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x5)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_HFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x6)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_MFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x7)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_4 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x8)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_5_LFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x9)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_6 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xa)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_7 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xb)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_8_LFTP FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xc)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_9 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xd)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_10 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xe)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_SQUARE_11 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0xf)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PROG_80 FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x10)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_1        FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x11)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_ALL_0        FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x12)
++#define   AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS11       FIELD_PREP_CONST(AIROHA_PCS_PMA_BISTCTL_PAT_SEL, 0x13)
++#define AIROHA_PCS_PMA_BISTCTL_ALIGN_PAT      0x214
++#define AIROHA_PCS_PMA_BISTCTL_POLLUTION      0x220
++#define   AIROHA_PCS_PMA_BIST_TX_DATA_POLLUTION_LATCH BIT(16)
++#define AIROHA_PCS_PMA_BISTCTL_PRBS_INITIAL_SEED 0x224
++#define AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD 0x230
++#define   AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK GENMASK(15, 0)
++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_2               0x23c
++#define   AIROHA_PCS_PMA_PI_CAL_DATA_OUT      GENMASK(22, 16)
++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_5               0x248
++#define   AIROHA_PCS_PMA_VEO_RDY              BIT(24)
++#define   AIROHA_PCS_PMA_HEO_RDY              BIT(16)
++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_9               0x258
++#define   AIROHA_PCS_PMA_EO_Y_DONE            BIT(24)
++#define   AIROHA_PCS_PMA_EO_X_DONE            BIT(16)
++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_10      0x25c
++#define   AIROHA_PCS_PMA_EYE_EL                       GENMASK(26, 16)
++#define   AIROHA_PCS_PMA_EYE_ER                       GENMASK(10, 0)
+ #define AIROHA_PCS_PMA_TX_RST_B                       0x260
+ #define   AIROHA_PCS_PMA_TXCALIB_RST_B                BIT(8)
+ #define   AIROHA_PCS_PMA_TX_TOP_RST_B         BIT(0)
++#define AIROHA_PCS_PMA_TX_CALIB_0             0x264
++#define   AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL GENMASK(25, 24)
++#define   AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN BIT(16)
++#define AIROHA_PCS_PMA_RX_TORGS_DEBUG_11      0x290
++#define   AIROHA_PCS_PMA_EYE_EB                       GENMASK(14, 8)
++#define   AIROHA_PCS_PMA_EYE_EU                       GENMASK(6, 0)
++#define AIROHA_PCS_PMA_RX_FORCE_MODE_0                0x294
++#define   AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL GENMASK(1, 0)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_0         0x300
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_CDR_LPF_RSTB BIT(24)
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_GAIN_CTRL BIT(0)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_1         0x304
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E0       BIT(24)
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D1       BIT(16)
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D0       BIT(8)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_2         0x308
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE BIT(24)
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_VOS BIT(16)
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE BIT(8)
++#define   AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E1 BIT(0)
++#define AIROHA_PCS_PMA_RX_FORCE_MODE_3                0x30c
++#define   AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY  BIT(0)
++#define AIROHA_PCS_PMA_RX_FORCE_MODE_6                0x318
++#define   AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_EYECNT_RDY     BIT(0)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_3         0x31c
++#define   AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY   BIT(0)
+ #define AIROHA_PCS_PMA_RX_DISB_MODE_4         0x320
+ #define   AIROHA_PCS_PMA_DISB_BLWC_OFFSET     BIT(24)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_5         0x324
++#define   AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN  BIT(24)
++#define   AIROHA_PCS_PMA_DISB_EYECNT_RDY      BIT(16)
++#define AIROHA_PCS_PMA_RX_FORCE_MODE_7                0x328
++#define   AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B  BIT(16)
++#define   AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB BIT(0)
++#define AIROHA_PCS_PMA_RX_FORCE_MODE_8                0x32c
++#define   AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B        BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B  BIT(16)
++#define   AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B        BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B  BIT(0)
+ #define AIROHA_PCS_PMA_RX_FORCE_MODE_9                0x330
++#define   AIROHA_PCS_PMA_FORCE_EYE_TOP_EN     BIT(16)
++#define   AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O        BIT(8)
+ #define   AIROHA_PCS_PMA_FORCE_FBCK_LOCK      BIT(0)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_6         0x334
++#define   AIROHA_PCS_PMA_DISB_PDOS_RX_RST_B   BIT(16)
++#define   AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB       BIT(8)
++#define   AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB BIT(0)
++#define AIROHA_PCS_PMA_RX_DISB_MODE_7         0x338
++#define   AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B BIT(24)
++#define   AIROHA_PCS_PMA_DISB_FEOS_RX_RST_B   BIT(16)
++#define   AIROHA_PCS_PMA_DISB_SDCAL_REF_RST_B BIT(8)
++#define   AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B   BIT(0)
+ #define AIROHA_PCS_PMA_RX_DISB_MODE_8         0x33c
++#define   AIROHA_PCS_PMA_DISB_EYE_TOP_EN      BIT(16)
++#define   AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O BIT(8)
+ #define   AIROHA_PCS_PMA_DISB_FBCK_LOCK               BIT(0)
++#define AIROHA_PCS_PMA_SS_BIST_1              0x344
++#define   AIROHA_PCS_PMA_LNX_BISTCTL_BIT_ERROR_RST_SEL BIT(24)
++#define   AIROHA_PCS_PMA_ANLT_PX_LNX_LT_LOS   BIT(0)
+ #define AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0      0x34c
+ #define   AIROHA_PCS_PMA_XPON_CDR_PD_PWDB     BIT(24)
+ #define   AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB       BIT(16)
+@@ -637,7 +965,32 @@
+ #define   AIROHA_PCS_PMA_PLL_LOCK_TARGET_BEG  GENMASK(15, 0)
+ #define AIROHA_PCS_PMA_PLL_TDC_FREQDET_3      0x39c
+ #define   AIROHA_PCS_PMA_PLL_LOCK_LOCKTH      GENMASK(11, 8)
++#define AIROHA_PCS_PMA_ADD_CLKPATH_RST_0      0x410
++#define   AIROHA_PCS_PMA_CLKPATH_RSTB_CK      BIT(8)
++#define   AIROHA_PCS_PMA_CLKPATH_RST_EN               BIT(0)
++#define AIROHA_PCS_PMA_ADD_XPON_MODE_1                0x414
++#define   AIROHA_PCS_PMA_TX_BIST_GEN_EN               BIT(16)
++#define   AIROHA_PCS_PMA_R2T_MODE             BIT(8)
++#define AIROHA_PCS_PMA_ADD_RX2ANA_1           0x424
++#define   AIROHA_PCS_PMA_RX_DAC_E0            GENMASK(30, 24)
++#define   AIROHA_PCS_PMA_RX_DAC_D1            GENMASK(22, 16)
++#define   AIROHA_PCS_PMA_RX_DAC_D0            GENMASK(14, 8)
++#define   AIROHA_PCS_PMA_RX_DAC_EYE           GENMASK(6, 0)
++#define AIROHA_PCS_PMA_ADD_RX2ANA_2           0x428
++#define   AIROHA_PCS_PMA_RX_FEOS_OUT          GENMASK(13, 8)
++#define   AIROHA_PCS_PMA_RX_DAC_E1            GENMASK(6, 0)
++#define AIROHA_PCS_PMA_PON_TX_COUNTER_0               0x440
++#define   AIROHA_PCS_PMA_TXCALIB_5US          GENMASK(31, 16)
++#define   AIROHA_PCS_PMA_TXCALIB_50US         GENMASK(15, 0)
++#define AIROHA_PCS_PMA_PON_TX_COUNTER_1               0x444
++#define   AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT    GENMASK(31, 16)
++#define   AIROHA_PCS_PMA_TX_CK_EN_WAIT                GENMASK(15, 0)
++#define AIROHA_PCS_PMA_PON_TX_COUNTER_2               0x448
++#define   AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT   GENMASK(31, 16)
++#define   AIROHA_PCS_PMA_TX_POWER_ON_WAIT     GENMASK(15, 0)
+ #define AIROHA_PCS_PMA_SW_RST_SET             0x460
++#define   AIROHA_PCS_PMA_SW_XFI_RXMAC_RST_N   BIT(17)
++#define   AIROHA_PCS_PMA_SW_XFI_TXMAC_RST_N   BIT(16)
+ #define   AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N   BIT(11)
+ #define   AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N   BIT(10)
+ #define   AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N BIT(9)
+@@ -650,17 +1003,32 @@
+ #define   AIROHA_PCS_PMA_SW_TX_RST_N          BIT(2)
+ #define   AIROHA_PCS_PMA_SW_RX_RST_N          BIT(1)
+ #define   AIROHA_PCS_PMA_SW_RX_FIFO_RST_N     BIT(0)
++#define AIROHA_PCS_PMA_TX_DLY_CTRL            0x468
++#define   AIROHA_PCS_PMA_OUTBEN_DATA_MODE     GENMASK(30, 28)
++#define   AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE   GENMASK(23, 16)
++#define   AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE     GENMASK(14, 8)
++#define   AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE    GENMASK(6, 0)
+ #define AIROHA_PCS_PMA_XPON_INT_EN_3          0x474
+ #define   AIROHA_PCS_PMA_RX_SIGDET_INT_EN     BIT(16)
+ #define AIROHA_PCS_PMA_XPON_INT_STA_3         0x47c
+ #define   AIROHA_PCS_PMA_RX_SIGDET_INT                BIT(16)
+ #define AIROHA_PCS_PMA_RX_EXTRAL_CTRL         0x48c
++/* 4ref_ck step:
++ * - 0x1 4ref_ck
++ * - 0x2 8ref_ck
++ * - 0x3 12ref_ck
++ * ...
++ */
++#define   AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME  GENMASK(15, 8)
++#define   AIROHA_PCS_PMA_OS_RDY_LATCH         BIT(1)
+ #define   AIROHA_PCS_PMA_DISB_LEQ             BIT(0)
+ #define AIROHA_PCS_PMA_RX_FREQDET             0x530
+ #define   AIROHA_PCS_PMA_FL_OUT                       GENMASK(31, 16)
+ #define   AIROHA_PCS_PMA_FBCK_LOCK            BIT(0)
+ #define AIROHA_PCS_PMA_XPON_TX_RATE_CTRL      0x580
+ #define   AIROHA_PCS_PMA_PON_TX_RATE_CTRL     GENMASK(1, 0)
++#define AIROHA_PCS_PMA_MD32_MEM_CLK_CTRL      0x60c
++#define   AIROHA_PCS_PMA_MD32PM_CK_SEL                GENMASK(31, 0)
+ #define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN     0x768
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL BIT(24)
+ #define   AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL GENMASK(19, 16)
+@@ -683,8 +1051,13 @@
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 BIT(8)
+ #define   AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1   GENMASK(5, 0)
+ #define AIROHA_PCS_PMA_PXP_TX_RATE_CTRL               0x784
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE        GENMASK(22, 16)
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL BIT(8)
+ #define   AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL GENMASK(1, 0)
++#define AIROHA_PCS_PMA_PXP_CDR_PR_FLL_COR     0x790
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_DAC_EYE BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE  GENMASK(22, 16)
+ #define AIROHA_PCS_PMA_PXP_CDR_PR_IDAC                0x794
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW BIT(24)
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_IDAC BIT(16)
+@@ -729,6 +1102,14 @@
+ #define   AIROHA_PCS_PMA_FORCE_DA_JCPLL_EN    BIT(16)
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_JCPLL_CKOUT_EN BIT(8)
+ #define   AIROHA_PCS_PMA_FORCE_DA_JCPLL_CKOUT_EN BIT(0)
++#define AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB        0x83c
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON       BIT(16)
++#define AIROHA_PCS_PMA_PXP_RX_OSCAL_EN                0x840
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB BIT(24)
++#define   AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB       BIT(16)
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN BIT(0)
+ #define AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B      0x84c
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB BIT(24)
+ #define   AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB BIT(16)
+@@ -739,6 +1120,12 @@
+ #define   AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN    BIT(16)
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN BIT(8)
+ #define   AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN BIT(0)
++#define AIROHA_PCS_PMA_PXP_TXPLL_KBAND_LOAD_EN        0x858
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_DA_TXPLL_KBAND_LOAD_EN BIT(0)
++#define AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG  0x864
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW_CHG BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG BIT(0)
+ #define AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN               0x874
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL BIT(24)
+ #define   AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL BIT(16)
+@@ -750,10 +1137,31 @@
+ #define   AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN       BIT(16)
+ #define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB BIT(8)
+ #define   AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB   BIT(0)
++#define AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN   0x898
++#define   AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN BIT(8)
++#define   AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN BIT(0)
++#define AIROHA_PCS_PMA_DIG_RESERVE_12         0x8b8
++#define   AIROHA_PCS_PMA_RESERVE_12_FEOS_0    BIT(0)
++#define AIROHA_PCS_PMA_DIG_RESERVE_24         0x8fc
++#define   AIROHA_PCS_PMA_FORCE_RX_GEARBOX     BIT(12)
++#define   AIROHA_PCS_PMA_FORCE_SEL_RX_GEARBOX BIT(8)
+ #define AIROHA_PCS_MAX_CALIBRATION_TRY                50
+ #define AIROHA_PCS_MAX_NUM_RSTS                       2
++enum pon_eo_buf_vals {
++      EYE_EU,
++      EYE_EB,
++      DAC_D0,
++      DAC_D1,
++      DAC_E0,
++      DAC_E1,
++      DAC_EYE,
++      FEOS,
++
++      EO_BUF_MAX,
++};
++
+ enum xfi_port_type {
+       AIROHA_PCS_ETH,
+       AIROHA_PCS_PON,
+@@ -790,6 +1198,11 @@ struct airoha_pcs_port {
+ struct airoha_pcs_match_data {
+       enum xfi_port_type port_type;
++      bool hibernation_workaround;
++      bool usxgmii_ber_time_fixup;
++      bool usxgmii_rx_gb_out_vld_tweak;
++      bool usxgmii_xfi_mode_sel;
++
+       int (*bringup)(struct airoha_pcs_priv *priv,
+                       phy_interface_t interface);
+       void (*link_up)(struct airoha_pcs_priv *priv);
+@@ -820,3 +1233,20 @@ static inline int an7581_pcs_rxlock_work
+       return 0;
+ }
+ #endif
++
++#ifdef CONFIG_PCS_AIROHA_AN7583
++int an7583_pcs_common_phya_bringup(struct airoha_pcs_priv *priv,
++                                 phy_interface_t interface);
++
++void an7583_pcs_common_phya_link_up(struct airoha_pcs_priv *priv);
++#else
++static inline int an7583_pcs_common_phya_bringup(struct airoha_pcs_priv *priv,
++                                               phy_interface_t interface)
++{
++      return -EOPNOTSUPP;
++}
++
++static inline void an7583_pcs_common_phya_link_up(struct airoha_pcs_priv *priv)
++{
++}
++#endif
+--- /dev/null
++++ b/drivers/net/pcs/airoha/pcs-an7583.c
+@@ -0,0 +1,2199 @@
++// SPDX-License-Identifier: GPL-2.0
++/*
++ * Copyright (c) 2024 AIROHA Inc
++ * Author: Christian Marangi <ansuelsmth@gmail.com>
++ */
++#include <linux/phylink.h>
++#include <linux/regmap.h>
++
++#include "pcs-airoha.h"
++
++static void an7583_pcs_dig_reset_hold(struct airoha_pcs_priv *priv)
++{
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                        AIROHA_PCS_PMA_SW_RX_FIFO_RST_N |
++                        AIROHA_PCS_PMA_SW_TX_FIFO_RST_N);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                        AIROHA_PCS_PMA_SW_REF_RST_N);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                        AIROHA_PCS_PMA_SW_ALLPCS_RST_N);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                        AIROHA_PCS_PMA_SW_TX_RST_N |
++                        AIROHA_PCS_PMA_SW_RX_RST_N);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                        AIROHA_PCS_PMA_SW_PMA_RST_N);
++
++      usleep_range(50, 100);
++}
++
++static void an7583_pcs_dig_reset_release(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_REF_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_TX_RST_N |
++                      AIROHA_PCS_PMA_SW_RX_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_PMA_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_RX_FIFO_RST_N |
++                      AIROHA_PCS_PMA_SW_TX_FIFO_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_ALLPCS_RST_N);
++
++      usleep_range(100, 200);
++}
++
++static void an7583_pcs_common_phya_txpll(struct airoha_pcs_priv *priv,
++                                       phy_interface_t interface)
++{
++      u32 pcw, tdc_pcw;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_SGMII:  /* DS(RX)_1.25G  /  US(TX)_1.25G*/
++      case PHY_INTERFACE_MODE_1000BASEX:
++              pcw = 0x32000000;
++              tdc_pcw = 0x64000000;
++              break;
++      case PHY_INTERFACE_MODE_2500BASEX: /* DS(RX)_3.125G  /  US(TX)_3.125G */
++              pcw = 0x3e800000;
++              tdc_pcw = 0x7d000000;
++              break;
++      case PHY_INTERFACE_MODE_5GBASER: /* DS(RX)_5.15625G  /  US(TX)_5.15625G */
++      case PHY_INTERFACE_MODE_USXGMII: /* DS(RX)_10.31252G  /  US(TX)_10.3125G */
++      case PHY_INTERFACE_MODE_10GBASER:
++              pcw = 0x33900000;
++              tdc_pcw = 0x67200000;
++              break;
++      default:
++              return;
++      }
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_3,
++                      AIROHA_PCS_PMA_LCPLL_NCPO_LOAD);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW,
++                         AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW, pcw));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PCW_1,
++                         AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
++                         FIELD_PREP(AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_GPON,
++                                    tdc_pcw));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PCW_2,
++                         AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON,
++                         FIELD_PREP(AIROHA_PCS_PMA_LCPLL_PON_HRDDS_PCW_NCPO_EPON,
++                                    tdc_pcw));
++}
++
++static void an7583_pcs_common_phya_tx(struct airoha_pcs_priv *priv,
++                                    phy_interface_t interface)
++{
++      const struct airoha_pcs_match_data *data = priv->data;
++      u32 tx_rate_ctrl;
++      u32 ckin_divisor;
++      u32 fir_cn1, fir_c0b, fir_c1, fir_c2;
++      u32 tx_ben_exten_ftune;
++      u32 tx_dly_ben_ftune;
++      u32 tx_dly_data_ftune;
++
++      if (data->port_type == AIROHA_PCS_ETH)
++              tx_ben_exten_ftune = 0x2;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_SGMII:
++      case PHY_INTERFACE_MODE_1000BASEX:
++              ckin_divisor = BIT(1);
++              tx_rate_ctrl = BIT(0);
++              fir_cn1 = 0;
++              fir_c0b = 8;
++              fir_c1 = 0;
++              fir_c2 = 0;
++
++              if (data->port_type == AIROHA_PCS_PON) {
++                      tx_ben_exten_ftune = 0x7;
++                      tx_dly_ben_ftune = 0x2;
++                      tx_dly_data_ftune = 0x6;
++              }
++              break;
++      case PHY_INTERFACE_MODE_2500BASEX:
++              ckin_divisor = BIT(2);
++              tx_rate_ctrl = BIT(0);
++              fir_cn1 = 0;
++              fir_c0b = 8;
++              fir_c1 = 1;
++              fir_c2 = 0;
++              if (data->port_type == AIROHA_PCS_PON)
++                      tx_ben_exten_ftune = 0x2;
++              break;
++      case PHY_INTERFACE_MODE_5GBASER:
++              ckin_divisor = BIT(2);
++              tx_rate_ctrl = BIT(1);
++              fir_cn1 = 0;
++              fir_c0b = 14;
++              fir_c1 = 4;
++              fir_c2 = 0;
++              if (data->port_type == AIROHA_PCS_PON)
++                      tx_ben_exten_ftune = 0x2;
++              break;
++      case PHY_INTERFACE_MODE_USXGMII:
++      case PHY_INTERFACE_MODE_10GBASER:
++              ckin_divisor = BIT(2) | BIT(0);
++              tx_rate_ctrl = BIT(1);
++              fir_cn1 = 0;
++              fir_c0b = 14;
++              fir_c1 = 4;
++              fir_c2 = 0;
++
++              if (data->port_type == AIROHA_PCS_PON) {
++                      tx_ben_exten_ftune = 0x16;
++                      tx_dly_ben_ftune = 0xd;
++                      tx_dly_data_ftune = 0x30;
++              }
++
++              break;
++      default:
++              return;
++      }
++
++      regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_CKLDO_EN,
++                      AIROHA_PCS_ANA_TX_DMEDGEGEN_EN |
++                      AIROHA_PCS_ANA_TX_CKLDO_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CMN_EN,
++                         AIROHA_PCS_ANA_CMN_VREFSEL |
++                         AIROHA_PCS_ANA_CMN_MPXSELTOP_DC |
++                         AIROHA_PCS_ANA_CMN_EN,
++                         AIROHA_PCS_ANA_CMN_VREFSEL_9V |
++                         FIELD_PREP(AIROHA_PCS_ANA_CMN_MPXSELTOP_DC, 0x1) |
++                         AIROHA_PCS_ANA_CMN_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_ACJTAG_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_SEL |
++                      AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_SEL);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C0B,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 |
++                         AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1 |
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B |
++                         AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_CN1 |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_CN1, fir_cn1) |
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C0B |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C0B, fir_c0b));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_FIR_C1,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 |
++                         AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2 |
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 |
++                         AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C2 |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C2, fir_c2) |
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_FIR_C1 |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_FIR_C1, fir_c1));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_TERM_SEL,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR |
++                         AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_CKIN_DIVISOR |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_CKIN_DIVISOR,
++                                    ckin_divisor));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL |
++                         AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TX_RATE_CTRL |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_TX_RATE_CTRL,
++                                    tx_rate_ctrl));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_TX_RATE_CTRL,
++                         AIROHA_PCS_PMA_PON_TX_RATE_CTRL,
++                         FIELD_PREP(AIROHA_PCS_PMA_PON_TX_RATE_CTRL,
++                                    tx_rate_ctrl));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_DLY_CTRL,
++                         AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE,
++                         FIELD_PREP(AIROHA_PCS_PMA_TX_BEN_EXTEN_FTUNE, tx_ben_exten_ftune));
++
++      if (data->port_type == AIROHA_PCS_PON) {
++              if (interface == PHY_INTERFACE_MODE_SGMII || interface == PHY_INTERFACE_MODE_1000BASEX ||
++                  interface == PHY_INTERFACE_MODE_USXGMII || interface == PHY_INTERFACE_MODE_10GBASER)
++                      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_DLY_CTRL,
++                                      AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE |
++                                      AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE,
++                                      FIELD_PREP(AIROHA_PCS_PMA_TX_DLY_BEN_FTUNE, tx_dly_ben_ftune) |
++                                      FIELD_PREP(AIROHA_PCS_PMA_TX_DLY_DATA_FTUNE, tx_dly_data_ftune));
++
++              regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_MD32_MEM_CLK_CTRL,
++                         AIROHA_PCS_PMA_MD32PM_CK_SEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_MD32PM_CK_SEL, 0x3));
++
++              regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_DLY_CTRL,
++                         AIROHA_PCS_PMA_OUTBEN_DATA_MODE,
++                         FIELD_PREP(AIROHA_PCS_PMA_OUTBEN_DATA_MODE, 0x1));
++      }
++}
++
++static void an7583_pcs_common_phya_rx(struct airoha_pcs_priv *priv,
++                                    phy_interface_t interface)
++{
++      const struct airoha_pcs_match_data *data = priv->data;
++
++      u32 rx_rev0;
++      u32 fe_gain_ctrl;
++      u32 dig_reserve_0;
++      u32 rx_force_mode_0;
++      u32 cdr_pr_beta_dac;
++      u32 phyck_sel;
++      u32 phyck_div;
++      u32 lpf_ratio;
++      u32 busbit_sel;
++      u32 rx_rate_ctrl;
++      u32 osr;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_SGMII:
++      case PHY_INTERFACE_MODE_1000BASEX:
++              dig_reserve_0 = 0x300;
++              cdr_pr_beta_dac = 0x8;
++              phyck_sel = 0x1;
++              phyck_div = 0x29;
++              lpf_ratio = 0x3;
++              osr = 0x3;
++              rx_rate_ctrl = 0x0;
++              break;
++      case PHY_INTERFACE_MODE_2500BASEX:
++              dig_reserve_0 = 0x300;
++              cdr_pr_beta_dac = 0x6;
++              phyck_sel = 0x1;
++              phyck_div = 0xb;
++              lpf_ratio = 0x1;
++              osr = 0x1;
++              rx_rate_ctrl = 0x0;
++              break;
++      case PHY_INTERFACE_MODE_5GBASER:
++              dig_reserve_0 = 0x400;
++              cdr_pr_beta_dac = 0x8;
++              phyck_sel = 0x2;
++              phyck_div = 0x42;
++              lpf_ratio = 0x1;
++              osr = 0x1;
++              rx_rate_ctrl = 0x2;
++              break;
++      case PHY_INTERFACE_MODE_USXGMII:
++      case PHY_INTERFACE_MODE_10GBASER:
++              dig_reserve_0 = 0x100;
++              cdr_pr_beta_dac = 0x8;
++              phyck_sel = 0x2;
++              phyck_div = 0x42;
++              lpf_ratio = 0x0;
++              osr = 0x0;
++              rx_rate_ctrl = 0x2;
++              break;
++      default:
++              return;
++      }
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0,
++                         AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL |
++                         AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL |
++                         AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK,
++                         FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF1_BIAS_CTRL, BIT(2)) |
++                         FIELD_PREP(AIROHA_PCS_ANA_REV_1_FE_BUF2_BIAS_CTRL, BIT(2)) |
++                         FIELD_PREP(AIROHA_PCS_ANA_REV_1_SIGDET_ILEAK, 0x0));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_OSCAL_WATCH_WNDW,
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE,
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2VOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA2IOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1VOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_VGA1IOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2VOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE2IOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1VOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_CTLE1IOS |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_LVSH |
++                         AIROHA_PCS_ANA_RX_OSCAL_FORCE_COMPOS);
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PD_PICAL_CKD8_INV,
++                        AIROHA_PCS_ANA_CDR_PD_EDGE_DIS |
++                        AIROHA_PCS_ANA_CDR_PD_PICAL_CKD8_INV);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_RSTB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_INJCK_SEL |
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_INJCK_SEL);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_DIG_RESERVE_12,
++                      AIROHA_PCS_PMA_RESERVE_12_FEOS_0);
++
++      if (interface == PHY_INTERFACE_MODE_USXGMII ||
++          interface == PHY_INTERFACE_MODE_10GBASER) {
++              rx_rev0 = FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE, 0x1) |
++                        FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL, 0x3);
++              fe_gain_ctrl = 0x1;
++              rx_force_mode_0 = 0x1;
++      } else {
++              rx_rev0 = FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF2_BIAS_TYPE, 0x1) |
++                        AIROHA_PCS_ANA_REV_0_OSCAL_FE_MODE_SET_SEL |
++                        BIT(7) | /* FIXME: Missing documentation for this BIT */
++                        FIELD_PREP(AIROHA_PCS_ANA_REV_0_FE_BUF_GAIN_MODE_NORMAL, 0x3);
++              fe_gain_ctrl = 0x3;
++              rx_force_mode_0 = 0x3;
++      }
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_REV_0,
++                         AIROHA_PCS_ANA_RX_REV_0, rx_rev0);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL,
++                         AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL,
++                                    fe_gain_ctrl));
++
++      regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_DIG_RESERVE_0,
++                   dig_reserve_0);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_0,
++                         AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_XPON_RX_FE_GAIN_CTRL,
++                                    rx_force_mode_0));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_0,
++                        AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_GAIN_CTRL);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_BETA_DAC,
++                         AIROHA_PCS_ANA_CDR_PR_BETA_DAC,
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_BETA_DAC,
++                                    cdr_pr_beta_dac));
++
++      if (data->port_type == AIROHA_PCS_ETH &&
++          interface == PHY_INTERFACE_MODE_2500BASEX)
++              regmap_update_bits(priv->xfi_ana,
++                                 AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL,
++                                 AIROHA_PCS_ANA_CDR_PR_DAC_BAND,
++                                 FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_DAC_BAND,
++                                            0x6));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV,
++                         AIROHA_PCS_ANA_RX_PHYCK_SEL,
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_SEL, phyck_sel));
++
++      regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN,
++                      AIROHA_PCS_ANA_CDR_PR_XFICK_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL,
++                         AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE |
++                         AIROHA_PCS_ANA_RX_PHY_CK_SEL,
++                         AIROHA_PCS_ANA_RX_PHY_CK_SEL_FORCE);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV,
++                         AIROHA_PCS_ANA_RX_PHYCK_RSTB |
++                         AIROHA_PCS_ANA_RX_PHYCK_DIV,
++                         AIROHA_PCS_ANA_RX_PHYCK_RSTB |
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_PHYCK_DIV, phyck_div));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO,
++                         AIROHA_PCS_ANA_CDR_LPF_RATIO,
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO,
++                                    lpf_ratio));
++
++      if (interface == PHY_INTERFACE_MODE_5GBASER)
++              busbit_sel = AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE |
++                           AIROHA_PCS_ANA_RX_BUSBIT_SEL_16BIT;
++      else
++              busbit_sel = 0;
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_BUSBIT_SEL,
++                         AIROHA_PCS_ANA_RX_BUSBIT_SEL_FORCE |
++                         AIROHA_PCS_ANA_RX_BUSBIT_SEL,
++                         busbit_sel);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_AEQ_SPEED,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL |
++                         AIROHA_PCS_PMA_FORCE_DA_OSR_SEL,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_OSR_SEL |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_OSR_SEL, osr));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_XPON_RX_RESERVED_1,
++                         AIROHA_PCS_PMA_XPON_RX_RATE_CTRL,
++                         FIELD_PREP(AIROHA_PCS_PMA_XPON_RX_RATE_CTRL, rx_rate_ctrl));
++}
++
++static void an7583_pcs_common_phya_ana(struct airoha_pcs_priv *priv,
++                                     phy_interface_t interface)
++{
++      const struct airoha_pcs_match_data *data = priv->data;
++      u32 txpll_chp_br, txpll_chp_ibias;
++      u32 lpf_bwr;
++      u32 vco_cfix;
++      u32 tcl_amp_vref;
++      bool sdm_ifm;
++      bool sdm_di;
++      bool sdm_hren;
++      bool vcodiv;
++      bool chp_double_en;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_SGMII:
++      case PHY_INTERFACE_MODE_1000BASEX:
++              if (data->port_type == AIROHA_PCS_PON) {
++                      txpll_chp_br = 0xa;
++                      txpll_chp_ibias = 0x18;
++                      lpf_bwr = 0x16;
++              } else {
++                      txpll_chp_br = 0x5;
++                      txpll_chp_ibias = 0x31;
++                      lpf_bwr = 0xb;
++              }
++              vco_cfix = 0x3;
++              tcl_amp_vref = 0xb;
++              vcodiv = false;
++              sdm_hren = data->port_type == AIROHA_PCS_PON;
++              sdm_ifm = data->port_type == AIROHA_PCS_PON;
++              sdm_di = data->port_type == AIROHA_PCS_PON;
++              chp_double_en = false;
++              break;
++      case PHY_INTERFACE_MODE_2500BASEX:
++              txpll_chp_br = 0x5;
++              txpll_chp_ibias = 0x1e;
++              lpf_bwr = 0xb;
++              vco_cfix = 0x0;
++              tcl_amp_vref = 0xe;
++              vcodiv = true;
++              sdm_hren = false;
++              sdm_ifm = false;
++              sdm_di = false;
++              chp_double_en = data->port_type == AIROHA_PCS_PON;
++              break;
++      case PHY_INTERFACE_MODE_5GBASER:
++      case PHY_INTERFACE_MODE_10GBASER:
++      case PHY_INTERFACE_MODE_USXGMII:
++              txpll_chp_br = 0xa;
++              txpll_chp_ibias = 0x18;
++              lpf_bwr = 0x16;
++              sdm_hren = true;
++              vco_cfix = 0x2;
++              tcl_amp_vref = 0xb;
++              vcodiv = false;
++              sdm_ifm = true;
++              sdm_di = true;
++              chp_double_en = false;
++              break;
++      default:
++              return;
++      }
++
++      if (data->port_type == AIROHA_PCS_PON)
++              /* XPON TDC */
++              regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_PLL_MONCLK_SEL,
++                              AIROHA_PCS_ANA_TDC_AUTOEN);
++
++      /* TXPLL VCO LDO Out */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD,
++                         AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT |
++                         AIROHA_PCS_ANA_TXPLL_LDO_OUT,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_VCO_OUT, 0x1) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LDO_OUT, 0x1));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VTP_EN,
++                         AIROHA_PCS_ANA_TXPLL_VTP |
++                         AIROHA_PCS_ANA_TXPLL_VTP_EN,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VTP, 0x0) |
++                         AIROHA_PCS_ANA_TXPLL_VTP_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TDC_SYNC_CK_SEL,
++                         AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL |
++                         AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN,
++                         FIELD_PREP(AIROHA_PCS_ANA_PLL_LDO_CKDRV_VSEL, 0x1) |
++                         AIROHA_PCS_ANA_PLL_LDO_CKDRV_EN);
++
++      /* Setup RSTB */
++      /* FIXME: different order */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_REFIN_INTERNAL,
++                         AIROHA_PCS_ANA_TXPLL_PLL_RSTB |
++                         AIROHA_PCS_ANA_TXPLL_RST_DLY |
++                         AIROHA_PCS_ANA_TXPLL_REFIN_DIV |
++                         AIROHA_PCS_ANA_TXPLL_REFIN_INTERNAL,
++                         AIROHA_PCS_ANA_TXPLL_PLL_RSTB |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_RST_DLY, 0x4) |
++                         AIROHA_PCS_ANA_TXPLL_REFIN_DIV_1);
++
++      /* Setup SDM */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_DI_EN,
++                         AIROHA_PCS_ANA_TXPLL_SDM_MODE |
++                         AIROHA_PCS_ANA_TXPLL_SDM_IFM |
++                         AIROHA_PCS_ANA_TXPLL_SDM_DI_LS |
++                         AIROHA_PCS_ANA_TXPLL_SDM_DI_EN,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SDM_MODE, 0) |
++                         (sdm_ifm ? AIROHA_PCS_ANA_TXPLL_SDM_IFM : 0) |
++                         AIROHA_PCS_ANA_TXPLL_SDM_DI_LS_2_23 |
++                         (sdm_di ? AIROHA_PCS_ANA_TXPLL_SDM_DI_EN : 0));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD,
++                         AIROHA_PCS_ANA_TXPLL_SDM_HREN |
++                         AIROHA_PCS_ANA_TXPLL_SDM_OUT |
++                         AIROHA_PCS_ANA_TXPLL_SDM_ORD,
++                         (sdm_hren ? AIROHA_PCS_ANA_TXPLL_SDM_HREN : 0) |
++                         AIROHA_PCS_ANA_TXPLL_SDM_ORD_3SDM);
++
++      /* Setup SSC */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_DELTA1,
++                         AIROHA_PCS_ANA_TXPLL_SSC_DELTA |
++                         AIROHA_PCS_ANA_TXPLL_SSC_DELTA1,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_DELTA1, 0x0));
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_EN,
++                        AIROHA_PCS_ANA_TXPLL_SSC_TRI_EN |
++                        AIROHA_PCS_ANA_TXPLL_SSC_PHASE_INI |
++                        AIROHA_PCS_ANA_TXPLL_SSC_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SSC_PERIOD,
++                         AIROHA_PCS_ANA_TXPLL_SSC_PERIOD,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_SSC_PERIOD, 0x0));
++
++      regmap_update_bits(priv->xfi_ana, AN7583_PCS_ANA_PXP_TXPLL_CHP_DOUBLE_EN,
++                         AIROHA_PCS_ANA_TXPLL_SPARE_L,
++                         chp_double_en ? AIROHA_PCS_ANA_TXPLL_SPARE_L : 0);
++
++      /* Setup LPF */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_CHP_IBIAS,
++                         AIROHA_PCS_ANA_TXPLL_LPF_BC |
++                         AIROHA_PCS_ANA_TXPLL_LPF_BR |
++                         AIROHA_PCS_ANA_TXPLL_CHP_IOFST |
++                         AIROHA_PCS_ANA_TXPLL_CHP_IBIAS,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BC, 0x1f) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BR, txpll_chp_br) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IOFST, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_CHP_IBIAS, txpll_chp_ibias));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP,
++                         AIROHA_PCS_ANA_TXPLL_LPF_BWC |
++                         AIROHA_PCS_ANA_TXPLL_LPF_BWR |
++                         AIROHA_PCS_ANA_TXPLL_LPF_BP,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWC, 0x18) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BWR, lpf_bwr) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_LPF_BP, 0x2));
++
++      /* Setup VCO */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN,
++                         AIROHA_PCS_ANA_TXPLL_VCO_CFIX,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_CFIX, vco_cfix));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_VCO_HALFLSB_EN,
++                         AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L |
++                         AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H |
++                         AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR |
++                         AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR |
++                         AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_L, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_VCOVAR_BIAS_H, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_TCLVAR, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_VCO_SCAPWR, 0x7) |
++                         AIROHA_PCS_ANA_TXPLL_VCO_HALFLSB_EN);
++
++      /* Setup KBand */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_CODE,
++                         AIROHA_PCS_ANA_TXPLL_KBAND_KF |
++                         AIROHA_PCS_ANA_TXPLL_KBAND_KFC |
++                         AIROHA_PCS_ANA_TXPLL_KBAND_DIV |
++                         AIROHA_PCS_ANA_TXPLL_KBAND_CODE,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KF, 0x3) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KFC, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_DIV, 0x2) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_CODE, 0xe4));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS,
++                         AIROHA_PCS_ANA_TXPLL_KBAND_KS,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_KBAND_KS, 0x1));
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_LPF_BP,
++                        AIROHA_PCS_ANA_TXPLL_KBAND_OPTION);
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF,
++                        AIROHA_PCS_ANA_TXPLL_VCO_KBAND_MEAS_EN);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_KBAND_LOAD_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN |
++                         AIROHA_PCS_PMA_FORCE_DA_TXPLL_KBAND_LOAD_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_KBAND_LOAD_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_KBAND_KS,
++                         AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE |
++                         AIROHA_PCS_ANA_TXPLL_POSTDIV_EN,
++                         AIROHA_PCS_ANA_TXPLL_MMD_PREDIV_MODE_2 |
++                         AIROHA_PCS_ANA_TXPLL_POSTDIV_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_AMP_GAIN,
++                         AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF |
++                         AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_AMP_VREF, tcl_amp_vref) |
++                         AIROHA_PCS_ANA_TXPLL_TCL_AMP_GAIN_4);
++
++      if (interface == PHY_INTERFACE_MODE_2500BASEX)
++              regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF,
++                              AIROHA_PCS_ANA_TXPLL_POSTDIV_D256_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN,
++                         AIROHA_PCS_ANA_TXPLL_VCODIV,
++                         vcodiv ? AIROHA_PCS_ANA_TXPLL_VCODIV_2 :
++                                  AIROHA_PCS_ANA_TXPLL_VCODIV_1);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF,
++                         AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF,
++                         FIELD_PREP(AIROHA_PCS_ANA_TXPLL_TCL_KBAND_VREF, 0xf));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_LPF_EN,
++                         AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW |
++                         AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN,
++                         AIROHA_PCS_ANA_TXPLL_TCL_LPF_BW_0_5 |
++                         AIROHA_PCS_ANA_TXPLL_TCL_LPF_EN);
++
++      regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_SDM_ORD,
++                      AIROHA_PCS_ANA_TXPLL_TCL_AMP_EN);
++
++      /* Setup TX TermCal */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_TXLBRC_EN,
++                         AIROHA_PCS_ANA_TX_TERMCAL_VREF_L |
++                         AIROHA_PCS_ANA_TX_TERMCAL_VREF_H,
++                         FIELD_PREP(AIROHA_PCS_ANA_TX_TERMCAL_VREF_L, 0x2) |
++                         FIELD_PREP(AIROHA_PCS_ANA_TX_TERMCAL_VREF_H, 0x2));
++
++      /* Setup XPON RX */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_EQ_HZEN,
++                         AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN |
++                         AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN |
++                         AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN |
++                         AIROHA_PCS_ANA_RX_FE_EQ_HZEN,
++                         AIROHA_PCS_ANA_RX_FE_VB_EQ3_EN |
++                         AIROHA_PCS_ANA_RX_FE_VB_EQ2_EN |
++                         AIROHA_PCS_ANA_RX_FE_VB_EQ1_EN);
++
++      regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_FE_VCM_GEN_PWDB,
++                      AIROHA_PCS_ANA_FE_VCM_GEN_PWDB);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO,
++                         AIROHA_PCS_ANA_CDR_LPF_TOP_LIM,
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_TOP_LIM, 0x8000));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_BOT_LIM,
++                         AIROHA_PCS_ANA_CDR_LPF_BOT_LIM,
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_BOT_LIM, 0x78000));
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV,
++                        AIROHA_PCS_ANA_CDR_PR_RSTB_BYPASS);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE,
++                         AIROHA_PCS_ANA_RX_DAC_RANGE_EYE,
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_DAC_RANGE_EYE, 0x2));
++}
++
++static void an7583_pcs_cfg_phy_type(struct airoha_pcs_priv *priv,
++                                  phy_interface_t interface)
++{
++      const struct airoha_pcs_match_data *data = priv->data;
++
++      /* Enable PLL force selection and Force Disable */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN |
++                         AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN);
++
++      if (data->port_type == AIROHA_PCS_PON) {
++              /* TDC */
++              regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_3,
++                                 AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT,
++                                 FIELD_PREP(AIROHA_PCS_PMA_LCPLL_NCPO_SHIFT, 0x1));
++              regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_1,
++                                 AIROHA_PCS_PMA_LCPLL_A_TDC,
++                                 FIELD_PREP(AIROHA_PCS_PMA_LCPLL_A_TDC, 0x5));
++              regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TX_TERMCAL_SELPN,
++                                 AIROHA_PCS_ANA_TX_TDC_CK_SEL,
++                                 FIELD_PREP(AIROHA_PCS_ANA_TX_TDC_CK_SEL, 0x0));
++              regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_PHYCK_DIV,
++                              AIROHA_PCS_ANA_RX_TDC_CK_SEL);
++      }
++
++      /* PLL EN HW Mode */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_1,
++                         AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER |
++                         AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER |
++                         AIROHA_PCS_PMA_LCPLL_EN_TIMER |
++                         AIROHA_PCS_PMA_LCPLL_MAN_PWDB,
++                         FIELD_PREP(AIROHA_PCS_PMA_LCPLL_CK_STB_TIMER, 0x1) |
++                         FIELD_PREP(AIROHA_PCS_PMA_LCPLL_PCW_MAN_LOAD_TIMER, 0x10) |
++                         FIELD_PREP(AIROHA_PCS_PMA_LCPLL_EN_TIMER, 0xa) |
++                         AIROHA_PCS_PMA_LCPLL_MAN_PWDB);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PON_TX_COUNTER_1,
++                         AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT |
++                         AIROHA_PCS_PMA_TX_CK_EN_WAIT,
++                         FIELD_PREP(AIROHA_PCS_PMA_TX_HSDATA_EN_WAIT, 0x113) |
++                         FIELD_PREP(AIROHA_PCS_PMA_TX_CK_EN_WAIT, 0xfa));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PON_TX_COUNTER_2,
++                         AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT |
++                         AIROHA_PCS_PMA_TX_POWER_ON_WAIT,
++                         FIELD_PREP(AIROHA_PCS_PMA_TX_SERDES_RDY_WAIT, 0x9b) |
++                         FIELD_PREP(AIROHA_PCS_PMA_TX_POWER_ON_WAIT, 0x210));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PON_TX_COUNTER_0,
++                         AIROHA_PCS_PMA_TXCALIB_5US |
++                         AIROHA_PCS_PMA_TXCALIB_50US,
++                         FIELD_PREP(AIROHA_PCS_PMA_TXCALIB_5US, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_TXCALIB_50US, 0x26));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_0,
++                         AIROHA_PCS_PMA_LCPLL_KI,
++                         FIELD_PREP(AIROHA_PCS_PMA_LCPLL_KI, 0x3));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PW_5,
++                        AIROHA_PCS_PMA_LCPLL_TDC_SYNC_IN_MODE);
++
++      an7583_pcs_common_phya_txpll(priv, interface);
++      an7583_pcs_common_phya_tx(priv, interface);
++
++      /* RX HW mode counter */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0,
++                         AIROHA_PCS_PMA_RX_OS_START,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_OS_START, 0x1));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_6,
++                         AIROHA_PCS_PMA_RX_OS_END,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_OS_END, 0x2));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_0,
++                         AIROHA_PCS_PMA_OSC_SPEED_OPT,
++                         AIROHA_PCS_PMA_OSC_SPEED_OPT_0_1);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_1,
++                         AIROHA_PCS_PMA_RX_PICAL_END |
++                         AIROHA_PCS_PMA_RX_PICAL_START,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_END, 0x3e8) |
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_PICAL_START, 0x2));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_4,
++                         AIROHA_PCS_PMA_RX_SDCAL_END |
++                         AIROHA_PCS_PMA_RX_SDCAL_START,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_END, 0x3e8) |
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_SDCAL_START, 0x2));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_2,
++                         AIROHA_PCS_PMA_RX_PDOS_END |
++                         AIROHA_PCS_PMA_RX_PDOS_START,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_END, 0x3e8) |
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_PDOS_START, 0x2));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_3,
++                         AIROHA_PCS_PMA_RX_FEOS_END |
++                         AIROHA_PCS_PMA_RX_FEOS_START,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_END, 0x3e8) |
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_FEOS_START, 0x2));
++
++      /* RX Settings */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_2,
++                         AIROHA_PCS_PMA_FOM_NUM_ORDER |
++                         AIROHA_PCS_PMA_A_SEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_FOM_NUM_ORDER, 0x1) |
++                         FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x3));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0,
++                         AIROHA_PCS_PMA_X_MAX | AIROHA_PCS_PMA_X_MIN,
++                         FIELD_PREP(AIROHA_PCS_PMA_X_MAX, 0x240) |
++                         FIELD_PREP(AIROHA_PCS_PMA_X_MIN, 0x1c0));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2,
++                        AIROHA_PCS_PMA_DATA_SHIFT);
++
++      an7583_pcs_common_phya_rx(priv, interface);
++      an7583_pcs_common_phya_ana(priv, interface);
++
++      /* Setup EYE */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2,
++                      AIROHA_PCS_PMA_EYECNT_FAST);
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3,
++                      AIROHA_PCS_PMA_EYE_NEXTPTS);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0,
++                         AIROHA_PCS_PMA_EYECNT_VTH |
++                         AIROHA_PCS_PMA_EYECNT_HTH,
++                         FIELD_PREP(AIROHA_PCS_PMA_EYECNT_VTH, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EYECNT_HTH, 0x4));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1,
++                         AIROHA_PCS_PMA_EO_VTH |
++                         AIROHA_PCS_PMA_EO_HTH,
++                         FIELD_PREP(AIROHA_PCS_PMA_EO_VTH, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EO_HTH, 0x4));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0,
++                         AIROHA_PCS_PMA_EYE_MASK |
++                         AIROHA_PCS_PMA_CNTLEN,
++                         FIELD_PREP(AIROHA_PCS_PMA_EYE_MASK, 0xff) |
++                         FIELD_PREP(AIROHA_PCS_PMA_CNTLEN, 0xd0));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0,
++                         AIROHA_PCS_PMA_VEO_MASK |
++                         AIROHA_PCS_PMA_HEO_MASK |
++                         AIROHA_PCS_PMA_EQ_EN_DELAY,
++                         FIELD_PREP(AIROHA_PCS_PMA_VEO_MASK, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_PMA_HEO_MASK, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x1));
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_1,
++                      AIROHA_PCS_PMA_A_LGAIN);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CAL1,
++                         AIROHA_PCS_PMA_CAL_CYC |
++                         AIROHA_PCS_PMA_CAL_STB |
++                         AIROHA_PCS_PMA_CAL_1US_SET |
++                         AIROHA_PCS_PMA_SIM_FAST_EN,
++                         AIROHA_PCS_PMA_CAL_CYC_15 |
++                         AIROHA_PCS_PMA_CAL_STB_8US |
++                         FIELD_PREP(AIROHA_PCS_PMA_CAL_1US_SET, 0x2e) |
++                         AIROHA_PCS_PMA_SIM_FAST_EN);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CAL2,
++                         AIROHA_PCS_PMA_CAL_CYC_TIME |
++                         AIROHA_PCS_PMA_CAL_OUT_OS |
++                         AIROHA_PCS_PMA_CAL_OS_PULSE,
++                         FIELD_PREP(AIROHA_PCS_PMA_CAL_CYC_TIME, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_PMA_CAL_OUT_OS, 0x0));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_CTRL_5,
++                         AIROHA_PCS_PMA_RX_RDY |
++                         AIROHA_PCS_PMA_RX_BLWC_RDY_EN,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_RDY, 0xa) |
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_BLWC_RDY_EN, 0x5));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FEOS,
++                         AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE |
++                         AIROHA_PCS_PMA_LFSEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_FORCE_BLWC_FREEZE, 0x0));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1,
++                         AIROHA_PCS_PMA_INDEX_MODE |
++                         AIROHA_PCS_PMA_Y_MAX |
++                         AIROHA_PCS_PMA_Y_MIN,
++                         AIROHA_PCS_PMA_INDEX_MODE |
++                         FIELD_PREP(AIROHA_PCS_PMA_Y_MAX, 0x3f) |
++                         FIELD_PREP(AIROHA_PCS_PMA_Y_MIN, 0x40));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2,
++                         AIROHA_PCS_PMA_EYEDUR,
++                         FIELD_PREP(AIROHA_PCS_PMA_EYEDUR, 0x18));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EXTRAL_CTRL,
++                         AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME |
++                         AIROHA_PCS_PMA_OS_RDY_LATCH |
++                         AIROHA_PCS_PMA_DISB_LEQ,
++                         FIELD_PREP(AIROHA_PCS_PMA_L2D_TRIG_EQ_EN_TIME, 0x2) |
++                         AIROHA_PCS_PMA_OS_RDY_LATCH);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_0,
++                         AIROHA_PCS_PMA_KBAND_KFC |
++                         AIROHA_PCS_PMA_FPKDIV |
++                         AIROHA_PCS_PMA_KBAND_PREDIV,
++                         AIROHA_PCS_PMA_KBAND_KFC_8 |
++                         FIELD_PREP(AIROHA_PCS_PMA_FPKDIV, 0xa5) |
++                         AIROHA_PCS_PMA_KBAND_PREDIV_4);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_1,
++                         AIROHA_PCS_PMA_SYMBOL_WD |
++                         AIROHA_PCS_PMA_SETTLE_TIME_SEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_SYMBOL_WD, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_SETTLE_TIME_SEL, 0x1));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_5,
++                         AIROHA_PCS_PMA_FLL_IDAC_MIN |
++                         AIROHA_PCS_PMA_FLL_IDAC_MAX,
++                         FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MIN, 0x400) |
++                         FIELD_PREP(AIROHA_PCS_PMA_FLL_IDAC_MAX, 0x1ff));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_2,
++                         AIROHA_PCS_PMA_AMP |
++                         AIROHA_PCS_PMA_PRBS_SEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_AMP, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_PRBS_SEL, 0x3));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_4,
++                        AIROHA_PCS_PMA_DISB_BLWC_OFFSET);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PDOS_CTRL_0,
++                         AIROHA_PCS_PMA_EYE_BLWC_ADD |
++                         AIROHA_PCS_PMA_DATA_BLWC_ADD,
++                         AIROHA_PCS_PMA_DATA_BLWC_ADD);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_BLWC,
++                         AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM |
++                         AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM |
++                         AIROHA_PCS_PMA_EQ_BLWC_GAIN |
++                         AIROHA_PCS_PMA_EQ_BLWC_POL,
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_BLWC_CNT_BOT_LIM, 0x10) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_BLWC_CNT_TOP_LIM, 0x70) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_BLWC_GAIN, 0xa) |
++                         AIROHA_PCS_PMA_EQ_BLWC_POL_INVERSION);
++}
++
++static void an7583_pcs_common_phya_txpll_on(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_CKOUT_EN |
++                      AIROHA_PCS_PMA_FORCE_DA_TXPLL_CKOUT_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_LCPLL_PWCTL_SETTING_0,
++                      AIROHA_PCS_PMA_SW_LCPLL_EN);
++
++      udelay(6);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_CKOUT_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_EN |
++                      AIROHA_PCS_PMA_FORCE_DA_TXPLL_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF,
++                         AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN |
++                         AIROHA_PCS_ANA_TXPLL_VREF_SEL,
++                         AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN |
++                         AIROHA_PCS_ANA_TXPLL_VREF_SEL_VBG);
++
++      regmap_set_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_PHY_CK1_EN,
++                      AIROHA_PCS_ANA_TXPLL_PHY_CK2_EN |
++                      AIROHA_PCS_ANA_TXPLL_PHY_CK1_EN);
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_TXPLL_TCL_KBAND_VREF,
++                        AIROHA_PCS_ANA_TXPLL_FREQ_MEAS_EN);
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_JCPLL_FREQ_MEAS_EN,
++                        AIROHA_PCS_ANA_TXPLL_IB_EXT_EN);
++
++      usleep_range(500, 1000);
++}
++
++static void an7583_pcs_common_phya_tx_on(struct airoha_pcs_priv *priv)
++{
++      u32 xfi_tx_term_sel = 0x1;
++      // int efuse_valid;
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B,
++                      AIROHA_PCS_PMA_TX_TOP_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_ADD_CLKPATH_RST_0,
++                      AIROHA_PCS_PMA_CLKPATH_RSTB_CK |
++                      AIROHA_PCS_PMA_CLKPATH_RST_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_RST_B,
++                      AIROHA_PCS_PMA_TXCALIB_RST_B |
++                      AIROHA_PCS_PMA_TX_TOP_RST_B);
++
++      usleep_range(100, 200);
++
++      /* TODO handle efuse */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_TX_CALIB_0,
++                         AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL |
++                         AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN,
++                         FIELD_PREP(AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL,
++                                    xfi_tx_term_sel) |
++                         AIROHA_PCS_PMA_TXCALIB_FORCE_TERMP_SEL_EN);
++}
++
++static void an7583_pcs_common_phya_rx_preset(struct airoha_pcs_priv *priv,
++                                           phy_interface_t interface)
++{
++      u32 cdr_pr_buf_in_sr;
++      bool cdr_pr_cap_en;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_2500BASEX:
++              cdr_pr_cap_en = true;
++              cdr_pr_buf_in_sr = 0x6;
++              break;
++      case PHY_INTERFACE_MODE_SGMII:
++      case PHY_INTERFACE_MODE_1000BASEX:
++      case PHY_INTERFACE_MODE_5GBASER:
++      case PHY_INTERFACE_MODE_10GBASER:
++      case PHY_INTERFACE_MODE_USXGMII:
++              cdr_pr_cap_en = false;
++              cdr_pr_buf_in_sr = 0x7;
++              break;
++      default:
++              return;
++      }
++
++      /* Setup RX Precondition */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH,
++                         AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL |
++                         AIROHA_PCS_ANA_RX_SIGDET_PEAK,
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_VTH_SEL, 0x2) |
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_PEAK, 0x2));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_DAC_RANGE,
++                         AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL,
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_SIGDET_LPF_CTRL, 0x3));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_MONPR_EN,
++                         AIROHA_PCS_ANA_CDR_PR_CAP_EN |
++                         AIROHA_PCS_ANA_CDR_BUF_IN_SR,
++                         (cdr_pr_cap_en ? AIROHA_PCS_ANA_CDR_PR_CAP_EN : 0) |
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_BUF_IN_SR, cdr_pr_buf_in_sr));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_OS_RDY);
++
++      /* Setup L2R */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA);
++
++      /* Setup LEQ setting */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL |
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, 0x0));
++
++      /* Keep EYE reset */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                      AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8,
++                        AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                        AIROHA_PCS_PMA_FORCE_EYE_TOP_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8,
++                        AIROHA_PCS_PMA_DISB_EYE_TOP_EN);
++
++      /* Kepp BLWC reset */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                        AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_RX_BLWC_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                      AIROHA_PCS_PMA_FORCE_RX_BLWC_EN);
++}
++
++static void an7583_pcs_common_phya_rx_on(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PWDB |
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PWDB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB |
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB,
++                        AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_KBAND_RSTB |
++                        AIROHA_PCS_PMA_FORCE_DA_CDR_PR_KBAND_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PD_PWDB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PD_PWDB |
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PD_PWDB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PWDB |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_FE_PWDB);
++
++      /* RX SigDet Pwdb */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_PWDB |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_PWDB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SCAN_RST_B,
++                        AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SCAN_RST_B |
++                        AIROHA_PCS_PMA_FORCE_DA_RX_SCAN_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_0,
++                      AIROHA_PCS_PMA_XPON_CDR_PD_PWDB |
++                      AIROHA_PCS_PMA_XPON_CDR_PR_PIEYE_PWDB |
++                      AIROHA_PCS_PMA_XPON_CDR_PW_PWDB |
++                      AIROHA_PCS_PMA_XPON_RX_FE_PWDB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_DA_XPON_PWDB_1,
++                      AIROHA_PCS_PMA_RX_SIDGET_PWDB);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_SYS_EN_SEL_0,
++                         AIROHA_PCS_PMA_RX_SYS_EN_SEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_RX_SYS_EN_SEL, 0x1));
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_VREG_IBAND_VAL,
++                         AIROHA_PCS_ANA_CDR_PR_FBKSEL |
++                         AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL |
++                         AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL,
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_FBKSEL, 0x0) |
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_CKBUF_VAL, 0x5) |
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_PR_VREG_IBAND_VAL, 0x5));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_PDOS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_FEOS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_SDCAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_OS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_BLWC_EN);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_CKREF_DIV,
++                         AIROHA_PCS_ANA_CDR_PR_CKREF_DIV,
++                         AIROHA_PCS_ANA_CDR_PR_CKREF_DIV_1);
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_PR_TDC_REF_SEL,
++                         AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1,
++                         AIROHA_PCS_ANA_CDR_PR_CKREF_DIV1_1);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_RX_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_REF_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB);
++
++      usleep_range(100, 200);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                        AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB);
++}
++
++static void an7583_pcs_common_phya_l2d(struct airoha_pcs_priv *priv)
++{
++      /* Setup LPF L2D force and disable */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA);
++
++      usleep_range(200, 300);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB);
++}
++
++static void an7583_pcs_common_phya_tdc_off(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_IDAC,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_3,
++                      AIROHA_PCS_PMA_LCPLL_NCPO_LOAD);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_TXPLL_SDM_PCW_CHG);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG,
++                        AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TXPLL_SDM_PCW_CHG,
++                      AIROHA_PCS_PMA_FORCE_DA_TXPLL_SDM_PCW_CHG);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_FLT_1,
++                         AIROHA_PCS_PMA_LCPLL_GPON_SEL,
++                         AIROHA_PCS_PMA_LCPLL_GPON_SEL_FROM_EPON);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_LCPLL_TDC_PW_0,
++                        AIROHA_PCS_PMA_LCPLL_TDC_DIG_PWDB);
++
++      usleep_range(100, 200);
++}
++
++static void an7583_pcs_common_phya_rx_oscal(struct airoha_pcs_priv *priv)
++{
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8,
++                        AIROHA_PCS_PMA_DISB_FBCK_LOCK);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                      AIROHA_PCS_PMA_FORCE_FBCK_LOCK);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN);
++
++      usleep_range(200, 300);
++
++      /* Set normal of force mode */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_OS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_OS_RDY);
++
++      /* Disable force mode signal */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_RDY);
++
++      /* Release reset enable */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                      AIROHA_PCS_PMA_FORCE_RX_OS_EN);
++}
++
++static void an7583_pcs_common_phya_pical(struct airoha_pcs_priv *priv)
++{
++      /* Pre Condition */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PI_CAL,
++                         AIROHA_PCS_PMA_KPGAIN,
++                         FIELD_PREP(AIROHA_PCS_PMA_KPGAIN, 0x4));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0,
++                         AIROHA_PCS_PMA_EQ_EN_DELAY,
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x8));
++
++      /* Reset Block */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                        AIROHA_PCS_PMA_EQ_PI_CAL_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                        AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6,
++                        AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                        AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6,
++                        AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_3,
++                        AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY);
++
++      /* Enable */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                        AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5,
++                        AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3,
++                        AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY);
++
++      /* Release Reset and Enable */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                      AIROHA_PCS_PMA_EQ_PI_CAL_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                      AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                      AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                      AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                      AIROHA_PCS_PMA_FORCE_RX_PICAL_EN);
++
++      usleep_range(200, 300);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                        AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3,
++                      AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY);
++}
++
++static void an7583_pcs_common_phya_pdos(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN);
++
++      /* Pre Condition */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_OS_RDY);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_1,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E0);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_1,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D1);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_1,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_D0);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_E1);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                        AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                        AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_EYEDUR_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_EYEDUR_EN);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PDOS_CTRL_0,
++                         AIROHA_PCS_PMA_SAP_SEL,
++                         AIROHA_PCS_PMA_SAP_SEL_SHIFT_8);
++
++      /* Reset Block */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                        AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6,
++                        AIROHA_PCS_PMA_DISB_PDOS_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_1,
++                        AIROHA_PCS_PMA_PDOS_RST_B);
++
++      /* Disable */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_PDOS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_PDOS_EN);
++
++      /* Release Reset and Enable */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_OS_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                      AIROHA_PCS_PMA_FORCE_PDOS_RX_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_1,
++                      AIROHA_PCS_PMA_PDOS_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                      AIROHA_PCS_PMA_FORCE_RX_PDOS_EN);
++
++      usleep_range(200, 300);
++
++      /* Disable (again) */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_PDOS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_EN);
++
++      /* Release EYE related */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_EYEDUR_INIT_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_EYECNT_RX_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                      AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_EYEDUR_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_EYEDUR_EN);
++
++      /* Disable PDOS */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_FE_PWDB,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_PDOSCAL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_PDOSCAL_EN);
++}
++
++static void an7583_pcs_common_phya_feos(struct airoha_pcs_priv *priv)
++{
++      /* Pre Condition */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_OS_RDY);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_FE_VOS);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_BLWC_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                        AIROHA_PCS_PMA_DISB_BLWC_RX_RST_B);
++
++      /* Setting */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_RX_FEOS,
++                         AIROHA_PCS_PMA_LFSEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_LFSEL, 0x30));
++
++      /* Reset */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                        AIROHA_PCS_PMA_DISB_FEOS_RX_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                        AIROHA_PCS_PMA_FEOS_RST_B);
++
++      /* Disable */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_FEOS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_FEOS_EN);
++
++      /* Release Reset and Enable */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                      AIROHA_PCS_PMA_FORCE_RX_OS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_OS_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                      AIROHA_PCS_PMA_FORCE_FEOS_RX_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                      AIROHA_PCS_PMA_FEOS_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                      AIROHA_PCS_PMA_FORCE_RX_FEOS_EN);
++
++      usleep_range(1000, 1500);
++
++      /* Disable */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_FEOS_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_OS_EN);
++}
++
++static void an7583_pcs_common_phya_sdcal(struct airoha_pcs_priv *priv)
++{
++      /* Pre Condition */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN |
++                      AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN);
++
++      /* Reset */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                        AIROHA_PCS_PMA_CAL_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                        AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_SDCAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                        AIROHA_PCS_PMA_DISB_SDCAL_REF_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN);
++
++      /* Release Reset and Enable */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                      AIROHA_PCS_PMA_CAL_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_8,
++                      AIROHA_PCS_PMA_FORCE_SDCAL_REF_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                      AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN);
++
++      usleep_range(200, 300);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                        AIROHA_PCS_PMA_FORCE_RX_SDCAL_EN);
++
++      /* SigDet Cal Disable */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_SIGDET_CAL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_SIGDET_CAL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_SIGDET_CAL_EN);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN_RSTB,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_CKON,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_CKON);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_RSTB,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_RSTB);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_RX_OSCAL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_OSCAL_EN,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_OSCAL_EN);
++}
++
++static void an7583_pcs_common_phya_phy_status(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                      AIROHA_PCS_PMA_FORCE_RX_OS_RDY);
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_OS_RDY);
++      udelay(1);
++}
++
++static void an7583_pcs_common_phya_eye_setting(struct airoha_pcs_priv *priv,
++                                             phy_interface_t interface)
++{
++      u32 x_min, x_max;
++      u32 cdr_lpf_ratio;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_SGMII:
++      case PHY_INTERFACE_MODE_1000BASEX:
++              x_min = 0x0;
++              x_max = 0x400;
++              cdr_lpf_ratio = 0x3;
++              break;
++      case PHY_INTERFACE_MODE_2500BASEX:
++              x_min = 0x140;
++              x_max = 0x2c0;
++              cdr_lpf_ratio = 0x0;
++              break;
++      case PHY_INTERFACE_MODE_5GBASER:
++              x_min = 0x180;
++              x_max = 0x280;
++              cdr_lpf_ratio = 0x1;
++              break;
++      case PHY_INTERFACE_MODE_10GBASER:
++      case PHY_INTERFACE_MODE_USXGMII:
++              x_min = 0x1c0;
++              x_max = 0x234;
++              cdr_lpf_ratio = 0x0;
++              break;
++      default:
++              return;
++      }
++
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_CDR_LPF_RATIO,
++                         AIROHA_PCS_ANA_CDR_LPF_RATIO,
++                         FIELD_PREP(AIROHA_PCS_ANA_CDR_LPF_RATIO,
++                                    cdr_lpf_ratio));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0,
++                         AIROHA_PCS_PMA_EYE_MASK,
++                         FIELD_PREP(AIROHA_PCS_PMA_EYE_MASK, 0xff));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_0,
++                         AIROHA_PCS_PMA_X_MAX | AIROHA_PCS_PMA_X_MIN,
++                         FIELD_PREP(AIROHA_PCS_PMA_X_MAX, x_max) |
++                         FIELD_PREP(AIROHA_PCS_PMA_X_MIN, x_min));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0,
++                         AIROHA_PCS_PMA_CNTLEN,
++                         FIELD_PREP(AIROHA_PCS_PMA_CNTLEN, 0xf8));
++
++      regmap_clear_bits(priv->xfi_ana, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_0,
++                        AIROHA_PCS_PMA_CNTFOREVER);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_2,
++                        AIROHA_PCS_PMA_DATA_SHIFT);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_1,
++                        AIROHA_PCS_PMA_INDEX_MODE);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_2,
++                         AIROHA_PCS_PMA_EYEDUR,
++                         FIELD_PREP(AIROHA_PCS_PMA_EYEDUR, 0x44c));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEINDEX_CTRL_3,
++                         AIROHA_PCS_PMA_EYE_NEXTPTS |
++                         AIROHA_PCS_PMA_EYE_NEXTPTS_TOGGLE |
++                         AIROHA_PCS_PMA_EYE_NEXTPTS_SEL,
++                         AIROHA_PCS_PMA_EYE_NEXTPTS);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_0,
++                         AIROHA_PCS_PMA_EYECNT_VTH |
++                         AIROHA_PCS_PMA_EYECNT_HTH,
++                         FIELD_PREP(AIROHA_PCS_PMA_EYECNT_VTH, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EYECNT_HTH, 0x4));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYEOPENING_CTRL_1,
++                         AIROHA_PCS_PMA_EO_VTH |
++                         AIROHA_PCS_PMA_EO_HTH,
++                         FIELD_PREP(AIROHA_PCS_PMA_EO_VTH, 0x4) |
++                         FIELD_PREP(AIROHA_PCS_PMA_EO_HTH, 0x4));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_1,
++                        AIROHA_PCS_PMA_B_ZERO_SEL |
++                        AIROHA_PCS_PMA_HEO_EMPHASIS |
++                        AIROHA_PCS_PMA_A_MGAIN |
++                        AIROHA_PCS_PMA_A_LGAIN);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_2,
++                         AIROHA_PCS_PMA_A_SEL,
++                         FIELD_PREP(AIROHA_PCS_PMA_A_SEL, 0x1));
++}
++
++static void an7583_pcs_common_phya_eye_cal(struct airoha_pcs_priv *priv)
++{
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_TX_RATE_CTRL,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE, 0x0));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_FLL_COR,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_DAC_EYE |
++                         AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_DAC_EYE, 0x0));
++
++      /* Redo PICal and reset Block */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0,
++                         AIROHA_PCS_PMA_EQ_EN_DELAY,
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x80));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PI_CAL,
++                         AIROHA_PCS_PMA_KPGAIN,
++                         FIELD_PREP(AIROHA_PCS_PMA_KPGAIN, 0x1));
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                        AIROHA_PCS_PMA_EQ_PI_CAL_RST_B);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                        AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6,
++                        AIROHA_PCS_PMA_DISB_RX_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                        AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_6,
++                        AIROHA_PCS_PMA_DISB_REF_AND_PICAL_RSTB);
++
++      /* Enable PICal */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5,
++                        AIROHA_PCS_PMA_DISB_RX_OR_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                        AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_0,
++                        AIROHA_PCS_PMA_DISB_RX_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_0,
++                        AIROHA_PCS_PMA_FORCE_RX_PICAL_EN);
++
++      /* Release Reset */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_RESET_0,
++                      AIROHA_PCS_PMA_EQ_PI_CAL_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                      AIROHA_PCS_PMA_FORCE_RX_AND_PICAL_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_7,
++                      AIROHA_PCS_PMA_FORCE_REF_AND_PICAL_RSTB);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                      AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN);
++
++      usleep_range(1000, 1500);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                        AIROHA_PCS_PMA_FORCE_RX_OR_PICAL_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_3,
++                        AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3,
++                      AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5,
++                        AIROHA_PCS_PMA_DISB_EYECNT_RDY);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                      AIROHA_PCS_PMA_FORCE_EYECNT_RDY);
++
++      usleep_range(1000, 1500);
++}
++
++static void an7583_pcs_common_phya_eye_eo_read(struct airoha_pcs_priv *priv,
++                                             u32 *heo, u32 *veo)
++{
++      u32 eo_buf[EO_BUF_MAX];
++      u32 eye_el, eye_er;
++      u32 feos;
++      u32 val;
++      int i;
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_6,
++                      AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN |
++                      AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN |
++                      AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN |
++                      AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN);
++
++      usleep_range(50, 100);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FLL_6,
++                        AIROHA_PCS_PMA_LNX_SW_FLL_4_LATCH_EN |
++                        AIROHA_PCS_PMA_LNX_SW_FLL_3_LATCH_EN |
++                        AIROHA_PCS_PMA_LNX_SW_FLL_2_LATCH_EN |
++                        AIROHA_PCS_PMA_LNX_SW_FLL_1_LATCH_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DEBUG_0,
++                        AIROHA_PCS_PMA_RO_TOGGLE);
++
++      usleep_range(100, 200);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DEBUG_0,
++                      AIROHA_PCS_PMA_RO_TOGGLE);
++
++      regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_TORGS_DEBUG_10, &val);
++      eye_el = FIELD_GET(AIROHA_PCS_PMA_EYE_EL, val);
++      eye_er = FIELD_GET(AIROHA_PCS_PMA_EYE_ER, val);
++
++      regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_TORGS_DEBUG_11, &val);
++      eo_buf[EYE_EU] = FIELD_GET(AIROHA_PCS_PMA_EYE_EU, val);
++      eo_buf[EYE_EB] = FIELD_GET(AIROHA_PCS_PMA_EYE_EB, val);
++
++      regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_ADD_RX2ANA_1, &val);
++      eo_buf[DAC_EYE] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_EYE, val);
++      eo_buf[DAC_D0] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_D0, val);
++      eo_buf[DAC_D1] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_D1, val);
++      eo_buf[DAC_E0] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_E0, val);
++
++      regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_ADD_RX2ANA_2, &val);
++      eo_buf[FEOS] = FIELD_GET(AIROHA_PCS_PMA_RX_FEOS_OUT, val);
++      eo_buf[DAC_E1] = FIELD_GET(AIROHA_PCS_PMA_RX_DAC_E1, val);
++
++      feos = eo_buf[FEOS];
++
++      for (i = 0; i < ARRAY_SIZE(eo_buf); i++) {
++              if ((eo_buf[i] == feos) && (eo_buf[i] >= 32))
++                      eo_buf[i] = eo_buf[i] - 64;
++              else if (eo_buf[i] >= 64)
++                      eo_buf[i] = eo_buf[i] - 128;
++      }
++
++      /* Check if CLK unlocking happens (E0 result validity) */
++      regmap_read(priv->xfi_pma, AIROHA_PCS_PMA_RX_TORGS_DEBUG_5, &val);
++      if (!FIELD_GET(AIROHA_PCS_PMA_HEO_RDY, val)) {
++              regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_0,
++                                AIROHA_PCS_PMA_DISB_DA_XPON_CDR_LPF_RSTB);
++
++              regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_0,
++                                AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB);
++
++              usleep_range(500, 700);
++
++              regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_0,
++                                AIROHA_PCS_PMA_FORCE_DA_XPON_CDR_LPF_RSTB);
++
++              usleep_range(500, 700);
++      }
++
++      *heo = abs(eye_er - eye_el);
++      *veo = abs(eo_buf[EYE_EU] - eo_buf[EYE_EB]);
++}
++
++static void an7583_pcs_common_phya_eye_eo(struct airoha_pcs_priv *priv,
++                                        phy_interface_t interface,
++                                        u32 *heo, u32 *veo)
++{
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8,
++                        AIROHA_PCS_PMA_DISB_EYE_RESET_PLU_O);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                      AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                        AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8,
++                        AIROHA_PCS_PMA_DISB_EYE_TOP_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                        AIROHA_PCS_PMA_FORCE_EYE_TOP_EN);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                      AIROHA_PCS_PMA_FORCE_EYE_TOP_EN);
++
++      if (interface == PHY_INTERFACE_MODE_10GBASER ||
++          interface == PHY_INTERFACE_MODE_USXGMII)
++              usleep_range(5500, 6000);
++      else
++              msleep(55);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_2,
++                      AIROHA_PCS_PMA_DISB_DA_XPON_CDR_PR_PIEYE |
++                      AIROHA_PCS_PMA_DISB_DA_XPON_RX_DAC_EYE);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_EYEDUR_INIT_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_7,
++                      AIROHA_PCS_PMA_DISB_EYECNT_RX_RST_B);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_EYE_TOP_EYECNT_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_EYEDUR_EN);
++
++      an7583_pcs_common_phya_eye_eo_read(priv, heo, veo);
++
++      /* Clear Eye SW value */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                      AIROHA_PCS_PMA_FORCE_EYE_RESET_PLU_O);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_8,
++                        AIROHA_PCS_PMA_DISB_EYE_TOP_EN);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_9,
++                        AIROHA_PCS_PMA_FORCE_EYE_TOP_EN);
++
++      /* Reset PICal Rdy */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_3,
++                        AIROHA_PCS_PMA_DISB_RQ_PI_CAL_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_3,
++                        AIROHA_PCS_PMA_FORCE_EQ_PI_CAL_RDY);
++
++      /* Reset Eyecnt Rdy */
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_DISB_MODE_5,
++                        AIROHA_PCS_PMA_DISB_EYECNT_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_FORCE_MODE_6,
++                        AIROHA_PCS_PMA_FORCE_EYECNT_RDY);
++}
++
++static void an7583_pcs_common_phya_eo_scan(struct airoha_pcs_priv *priv,
++                                         phy_interface_t interface)
++{
++
++      u32 best_heo = 0, best_veo = 0;
++      u32 leq_gain, best_leq_gain;
++      u32 best_leq_peacking = 0;
++
++      switch (interface) {
++      case PHY_INTERFACE_MODE_SGMII:
++      case PHY_INTERFACE_MODE_1000BASEX:
++      case PHY_INTERFACE_MODE_2500BASEX:
++      case PHY_INTERFACE_MODE_5GBASER:
++              leq_gain = 3;
++              break;
++      case PHY_INTERFACE_MODE_10GBASER:
++      case PHY_INTERFACE_MODE_USXGMII:
++              leq_gain = 1;
++              break;
++      default:
++              return;
++      }
++
++      best_leq_gain = leq_gain;
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_PR_PIEYE_PWDB,
++                      AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_PR_PIEYE_PWDB |
++                      AIROHA_PCS_PMA_FORCE_DA_CDR_PR_PIEYE_PWDB);
++
++      an7583_pcs_common_phya_eye_setting(priv, interface);
++
++      /* EYE Open */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PHY_EQ_CTRL_0,
++                         AIROHA_PCS_PMA_EQ_EN_DELAY,
++                         FIELD_PREP(AIROHA_PCS_PMA_EQ_EN_DELAY, 0x80));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_PI_CAL,
++                         AIROHA_PCS_PMA_KPGAIN,
++                         FIELD_PREP(AIROHA_PCS_PMA_KPGAIN, 0x4));
++
++      for (; leq_gain <= FIELD_MAX(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL); leq_gain++) {
++              u32 leq_peaking;
++              u32 heo, veo;
++
++              regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL,
++                                 AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL |
++                                 AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL,
++                                 AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_GAIN_CTRL |
++                                 FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, leq_gain));
++
++              for (leq_peaking = 0; leq_peaking <= FIELD_MAX(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL); leq_peaking++) {
++                      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN,
++                                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL |
++                                         AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL,
++                                         AIROHA_PCS_PMA_FORCE_SEL_DA_RX_FE_PEAKING_CTRL |
++                                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, leq_peaking));
++
++                      usleep_range(500, 700);
++
++                      an7583_pcs_common_phya_eye_cal(priv);
++                      an7583_pcs_common_phya_eye_eo(priv, interface, &heo, &veo);
++
++                      if (veo > 53 && best_veo > 53) {
++                              if (heo > best_heo) {
++                                      best_heo = heo;
++                                      best_veo = veo;
++                                      best_leq_peacking = leq_peaking;
++                                      best_leq_gain = leq_gain;
++                              } else if (heo == best_heo && veo > best_veo) {
++                                      best_heo = heo;
++                                      best_veo = veo;
++                                      best_leq_peacking = leq_peaking;
++                                      best_leq_gain = leq_gain;
++                              }
++                      } else {
++                              if (veo > best_veo) {
++                                      best_heo = heo;
++                                      best_veo = veo;
++                                      best_leq_peacking = leq_peaking;
++                                      best_leq_gain = leq_gain;
++                              }
++                      }
++              }
++      }
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_FE_GAIN_CTRL,
++                         AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_GAIN_CTRL, best_leq_gain));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_JCPLL_SDM_SCAN,
++                         AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL,
++                         FIELD_PREP(AIROHA_PCS_PMA_FORCE_DA_RX_FE_PEAKING_CTRL, best_leq_peacking));
++}
++
++static void an7583_pcs_common_phya_rxrdy(struct airoha_pcs_priv *priv)
++{
++      u32 xfi_rx_term_sel = 0x1;
++      // int efuse_valid;
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                      AIROHA_PCS_PMA_FORCE_RX_RDY);
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                        AIROHA_PCS_PMA_DISB_RX_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                        AIROHA_PCS_PMA_SW_RX_FIFO_RST_N);
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_RX_FIFO_RST_N);
++
++      /* TODO HANDLE EFUSE */
++      regmap_update_bits(priv->xfi_ana, AIROHA_PCS_ANA_PXP_RX_SIGDET_NOVTH,
++                         AIROHA_PCS_ANA_RX_FE_50OHMS_SEL,
++                         FIELD_PREP(AIROHA_PCS_ANA_RX_FE_50OHMS_SEL,
++                                    xfi_rx_term_sel));
++}
++
++static void an7583_pcs_common_phya_bist_setting(struct airoha_pcs_priv *priv)
++{
++      regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_ALIGN_PAT,
++                   0x8ff1fd53);
++      regmap_write(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_PRBS_INITIAL_SEED,
++                   0xFF1FD53);
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD,
++                         AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK,
++                         FIELD_PREP(AIROHA_PCS_PMA_BISTCTL_PRBS_FAIL_THRESHOLD_MASK, 0x1));
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_CONTROL,
++                         AIROHA_PCS_PMA_BISTCTL_PAT_SEL,
++                         AIROHA_PCS_PMA_BISTCTL_PAT_SEL_PRBS31);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_BISTCTL_POLLUTION,
++                      AIROHA_PCS_PMA_BIST_TX_DATA_POLLUTION_LATCH);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_SS_BIST_1,
++                        AIROHA_PCS_PMA_LNX_BISTCTL_BIT_ERROR_RST_SEL |
++                        AIROHA_PCS_PMA_ANLT_PX_LNX_LT_LOS);
++}
++
++static void an7583_pcs_first_plug_in(struct airoha_pcs_priv *priv,
++                                   phy_interface_t interface)
++{
++      const struct airoha_pcs_match_data *data = priv->data;
++
++      an7583_pcs_common_phya_rx_preset(priv, interface);
++      if (data->port_type == AIROHA_PCS_PON)
++              an7583_pcs_common_phya_tdc_off(priv);
++      an7583_pcs_common_phya_rx_on(priv);
++      an7583_pcs_common_phya_l2d(priv);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_REF_RST_N);
++
++      an7583_pcs_common_phya_rx_oscal(priv);
++      an7583_pcs_common_phya_pical(priv);
++      an7583_pcs_common_phya_pdos(priv);
++      an7583_pcs_common_phya_feos(priv);
++      an7583_pcs_common_phya_sdcal(priv);
++      an7583_pcs_common_phya_phy_status(priv);
++
++      an7583_pcs_dig_reset_release(priv);
++
++      an7583_pcs_common_phya_l2d(priv);
++
++      if (data->port_type == AIROHA_PCS_PON)
++              an7583_pcs_common_phya_eo_scan(priv, interface);
++      an7583_pcs_common_phya_rxrdy(priv);
++      if (data->port_type == AIROHA_PCS_PON)
++              an7583_pcs_common_phya_bist_setting(priv);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_ADD_XPON_MODE_1,
++                        AIROHA_PCS_PMA_TX_BIST_GEN_EN |
++                        AIROHA_PCS_PMA_R2T_MODE);
++}
++
++static void an7583_pcs_ana_reset_release(struct airoha_pcs_priv *priv)
++{
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_XFI_RXPCS_RST_N |
++                      AIROHA_PCS_PMA_SW_XFI_TXPCS_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_XFI_RXPCS_BIST_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_HSG_RXPCS_RST_N |
++                      AIROHA_PCS_PMA_SW_HSG_TXPCS_RST_N);
++
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_SW_RST_SET,
++                      AIROHA_PCS_PMA_SW_XFI_RXMAC_RST_N |
++                      AIROHA_PCS_PMA_SW_XFI_TXMAC_RST_N);
++}
++
++int an7583_pcs_common_phya_bringup(struct airoha_pcs_priv *priv,
++                                 phy_interface_t interface)
++{
++      an7583_pcs_dig_reset_hold(priv);
++
++      an7583_pcs_cfg_phy_type(priv, interface);
++
++      an7583_pcs_common_phya_txpll_on(priv);
++
++      an7583_pcs_common_phya_tx_on(priv);
++
++      an7583_pcs_first_plug_in(priv, interface);
++
++      an7583_pcs_ana_reset_release(priv);
++
++      return 0;
++}
++
++void an7583_pcs_common_phya_link_up(struct airoha_pcs_priv *priv)
++{
++      /* First CDR reset */
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB);
++
++      usleep_range(700, 1000);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB);
++
++      usleep_range(100, 200);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_RSTB |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB,
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_RSTB);
++
++      regmap_update_bits(priv->xfi_pma, AIROHA_PCS_PMA_PXP_CDR_LPF_LCK_2DATA,
++                         AIROHA_PCS_PMA_FORCE_SEL_DA_CDR_LPF_LCK2DATA |
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA,
++                         AIROHA_PCS_PMA_FORCE_DA_CDR_LPF_LCK2DATA);
++
++      /* Then RX Rdy reset */
++      regmap_set_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_DISB_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_RX_RDY);
++
++      regmap_clear_bits(priv->xfi_pma, AIROHA_PCS_PMA_RX_CTRL_SEQUENCE_FORCE_CTRL_1,
++                      AIROHA_PCS_PMA_DISB_RX_RDY);
++}
diff --git a/target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch b/target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch
new file mode 100644 (file)
index 0000000..0fa14de
--- /dev/null
@@ -0,0 +1,26 @@
+From 6548e580509397a622b7c504a79de93414771459 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Wed, 25 Jun 2025 00:04:36 +0200
+Subject: [PATCH 6/6] net: ethernet: airoha: define sport value for GDM3
+
+On Airoha AN7583, the Serdes Ethernet goes through the GDM3 port.
+To correctly receive packet for QDMA, add the sport value to identify
+packet from GDM3 port.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -616,6 +616,9 @@ static int airoha_qdma_get_gdm_port(stru
+       case 0x18:
+               port = 3; /* GDM4 */
+               break;
++      case 0x16:
++              port = 2; /* GDM3 */
++              break;
+       case 0x10 ... 0x14:
+               port = 0; /* GDM1 */
+               break;
diff --git a/target/linux/airoha/patches-6.12/605-net-pcs-airoha-add-support-for-optional-xfi-reset-li.patch b/target/linux/airoha/patches-6.12/605-net-pcs-airoha-add-support-for-optional-xfi-reset-li.patch
new file mode 100644 (file)
index 0000000..5f48c34
--- /dev/null
@@ -0,0 +1,63 @@
+From 961800f3badd72e4efda39f219ac4cbec5791433 Mon Sep 17 00:00:00 2001
+From: Christian Marangi <ansuelsmth@gmail.com>
+Date: Sat, 26 Jul 2025 22:58:10 +0200
+Subject: [PATCH 7/8] net: pcs: airoha: add support for optional xfi reset line
+
+On Airoha AN7583 there is a dedicated reset line for the PON XFI Serdes.
+This is needed to permit changing the WAN sel register or the system
+will stall on accessing the XFI register.
+
+Add support for this optional dedicated reset to permit correct
+configuration of the PON Serdes.
+
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+---
+ drivers/net/pcs/airoha/pcs-airoha-common.c | 12 ++++++++++++
+ drivers/net/pcs/airoha/pcs-airoha.h        |  1 +
+ 2 files changed, 13 insertions(+)
+
+--- a/drivers/net/pcs/airoha/pcs-airoha-common.c
++++ b/drivers/net/pcs/airoha/pcs-airoha-common.c
+@@ -82,6 +82,10 @@ static int airoha_pcs_setup_scu(struct a
+       const struct airoha_pcs_match_data *data = priv->data;
+       int ret;
++      ret = reset_control_assert(priv->xfi_rst);
++      if (ret)
++              return ret;
++
+       switch (data->port_type) {
+       case AIROHA_PCS_ETH:
+               airoha_pcs_setup_scu_eth(priv, interface);
+@@ -91,6 +95,10 @@ static int airoha_pcs_setup_scu(struct a
+               break;
+       }
++      ret = reset_control_deassert(priv->xfi_rst);
++      if (ret)
++              return ret;
++
+       /* TODO better handle reset from MAC */
+       ret = reset_control_bulk_assert(ARRAY_SIZE(priv->rsts),
+                                       priv->rsts);
+@@ -1003,6 +1011,10 @@ static int airoha_pcs_probe(struct platf
+       if (ret)
+               return dev_err_probe(dev, ret, "failed to get bulk reset lines\n");
++      priv->xfi_rst = devm_reset_control_get_optional_exclusive(dev, "xfi");
++      if (IS_ERR(priv->xfi_rst))
++              return dev_err_probe(dev, PTR_ERR(priv->xfi_rst), "failed to get xfi reset lines\n");
++
+       /* For Ethernet PCS, read the AN7581 SoC revision to check if
+        * manual rx calibration is needed. This is only limited to
+        * any SoC revision before E2.
+--- a/drivers/net/pcs/airoha/pcs-airoha.h
++++ b/drivers/net/pcs/airoha/pcs-airoha.h
+@@ -1184,6 +1184,7 @@ struct airoha_pcs_priv {
+       struct regmap *xfi_pma;
+       struct regmap *xfi_ana;
++      struct reset_control *xfi_rst;
+       struct reset_control_bulk_data rsts[AIROHA_PCS_MAX_NUM_RSTS];
+       bool manual_rx_calib;