mirror of
https://git.openwrt.org/openwrt/openwrt.git/
synced 2025-10-06 03:02:55 +02:00
airoha: switch to 6.12 and drop 6.6
Switch Airoha targets to 6.12 and drop 6.6 support. Signed-off-by: Andrew LaMarche <andrewjlamarche@gmail.com> Link: https://github.com/openwrt/openwrt/pull/20137 Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
committed by
Robert Marko
parent
ce3ab2646b
commit
10f3f6d6d8
@@ -6,8 +6,7 @@ BOARDNAME:=Airoha ARM
|
||||
SUBTARGETS:=en7523 an7581
|
||||
FEATURES:=dt squashfs nand ramdisk gpio
|
||||
|
||||
KERNEL_PATCHVER:=6.6
|
||||
KERNEL_TESTING_PATCHVER:=6.12
|
||||
KERNEL_PATCHVER:=6.12
|
||||
|
||||
include $(INCLUDE_DIR)/target.mk
|
||||
|
||||
|
@@ -1,371 +0,0 @@
|
||||
CONFIG_64BIT=y
|
||||
CONFIG_AIROHA_CPU_PM_DOMAIN=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_PAGE_SHIFT=12
|
||||
CONFIG_ARM64_PA_BITS=48
|
||||
CONFIG_ARM64_PA_BITS_48=y
|
||||
CONFIG_ARM64_TAGGED_ADDR_ABI=y
|
||||
CONFIG_ARM64_VA_BITS=39
|
||||
CONFIG_ARM64_VA_BITS_39=y
|
||||
CONFIG_ARM_AIROHA_SOC_CPUFREQ=y
|
||||
CONFIG_ARM_AMBA=y
|
||||
CONFIG_ARM_ARCH_TIMER=y
|
||||
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARM_GIC_V2M=y
|
||||
CONFIG_ARM_GIC_V3=y
|
||||
CONFIG_ARM_GIC_V3_ITS=y
|
||||
CONFIG_ARM_GIC_V3_ITS_PCI=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_CONTEXT_TRACKING=y
|
||||
CONFIG_CONTEXT_TRACKING_IDLE=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_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_OF=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_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_HW_RANDOM=y
|
||||
CONFIG_HW_RANDOM_AIROHA=y
|
||||
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_WORK=y
|
||||
CONFIG_JBD2=y
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_LOCK_DEBUGGING_SUPPORT=y
|
||||
CONFIG_LOCK_SPIN_ON_OWNER=y
|
||||
CONFIG_LZO_COMPRESS=y
|
||||
CONFIG_LZO_DECOMPRESS=y
|
||||
CONFIG_MDIO_BUS=y
|
||||
CONFIG_MDIO_DEVICE=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_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_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_MTK_LYNXI=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_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_PREEMPT_NONE_BUILD=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_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_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_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
|
@@ -1,300 +0,0 @@
|
||||
CONFIG_ALIGNMENT_TRAP=y
|
||||
CONFIG_ARCH_32BIT_OFF_T=y
|
||||
CONFIG_ARCH_AIROHA=y
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
CONFIG_ARCH_KEEP_MEMBLOCK=y
|
||||
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
|
||||
CONFIG_ARCH_MULTIPLATFORM=y
|
||||
CONFIG_ARCH_MULTI_V6_V7=y
|
||||
CONFIG_ARCH_MULTI_V7=y
|
||||
CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
|
||||
CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
|
||||
CONFIG_ARCH_SELECT_MEMORY_MODEL=y
|
||||
CONFIG_ARCH_SPARSEMEM_ENABLE=y
|
||||
CONFIG_ARCH_STACKWALK=y
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
CONFIG_ARM=y
|
||||
CONFIG_ARM_AMBA=y
|
||||
CONFIG_ARM_ARCH_TIMER=y
|
||||
CONFIG_ARM_ARCH_TIMER_EVTSTREAM=y
|
||||
CONFIG_ARM_CPU_SUSPEND=y
|
||||
CONFIG_ARM_GIC=y
|
||||
CONFIG_ARM_GIC_V3=y
|
||||
CONFIG_ARM_GIC_V3_ITS=y
|
||||
CONFIG_ARM_GIC_V3_ITS_PCI=y
|
||||
CONFIG_ARM_HAS_GROUP_RELOCS=y
|
||||
CONFIG_ARM_HEAVY_MB=y
|
||||
# CONFIG_ARM_HIGHBANK_CPUIDLE is not set
|
||||
CONFIG_ARM_L1_CACHE_SHIFT=6
|
||||
CONFIG_ARM_L1_CACHE_SHIFT_6=y
|
||||
CONFIG_ARM_PATCH_IDIV=y
|
||||
CONFIG_ARM_PATCH_PHYS_VIRT=y
|
||||
CONFIG_ARM_PSCI=y
|
||||
CONFIG_ARM_PSCI_FW=y
|
||||
# CONFIG_ARM_SMMU is not set
|
||||
CONFIG_ARM_THUMB=y
|
||||
CONFIG_ARM_UNWIND=y
|
||||
CONFIG_ARM_VIRT_EXT=y
|
||||
CONFIG_ATAGS=y
|
||||
CONFIG_AUTO_ZRELADDR=y
|
||||
CONFIG_BINFMT_FLAT_ARGVP_ENVP_ON_STACK=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_BLK_MQ_PCI=y
|
||||
CONFIG_BLK_PM=y
|
||||
CONFIG_BSD_PROCESS_ACCT=y
|
||||
CONFIG_BSD_PROCESS_ACCT_V3=y
|
||||
CONFIG_CACHE_L2X0=y
|
||||
CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
|
||||
CONFIG_CLONE_BACKWARDS=y
|
||||
CONFIG_CMDLINE="rootfstype=squashfs,jffs2"
|
||||
CONFIG_CMDLINE_FROM_BOOTLOADER=y
|
||||
CONFIG_COMMON_CLK=y
|
||||
CONFIG_COMMON_CLK_EN7523=y
|
||||
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
|
||||
CONFIG_COMPAT_32BIT_TIME=y
|
||||
CONFIG_CONTEXT_TRACKING=y
|
||||
CONFIG_CONTEXT_TRACKING_IDLE=y
|
||||
CONFIG_CPU_32v6K=y
|
||||
CONFIG_CPU_32v7=y
|
||||
CONFIG_CPU_ABRT_EV7=y
|
||||
CONFIG_CPU_CACHE_V7=y
|
||||
CONFIG_CPU_CACHE_VIPT=y
|
||||
CONFIG_CPU_COPY_V6=y
|
||||
CONFIG_CPU_CP15=y
|
||||
CONFIG_CPU_CP15_MMU=y
|
||||
CONFIG_CPU_HAS_ASID=y
|
||||
CONFIG_CPU_IDLE=y
|
||||
CONFIG_CPU_IDLE_GOV_MENU=y
|
||||
CONFIG_CPU_LITTLE_ENDIAN=y
|
||||
CONFIG_CPU_MITIGATIONS=y
|
||||
CONFIG_CPU_PABRT_V7=y
|
||||
CONFIG_CPU_PM=y
|
||||
CONFIG_CPU_RMAP=y
|
||||
CONFIG_CPU_SPECTRE=y
|
||||
CONFIG_CPU_THUMB_CAPABLE=y
|
||||
CONFIG_CPU_TLB_V7=y
|
||||
CONFIG_CPU_V7=y
|
||||
CONFIG_CRC16=y
|
||||
CONFIG_CRYPTO_DEFLATE=y
|
||||
CONFIG_CRYPTO_HASH_INFO=y
|
||||
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
|
||||
CONFIG_CRYPTO_LIB_GF128MUL=y
|
||||
CONFIG_CRYPTO_LIB_SHA1=y
|
||||
CONFIG_CRYPTO_LIB_UTILS=y
|
||||
CONFIG_CRYPTO_LZO=y
|
||||
CONFIG_CRYPTO_ZSTD=y
|
||||
CONFIG_CURRENT_POINTER_IN_TPIDRURO=y
|
||||
CONFIG_DCACHE_WORD_ACCESS=y
|
||||
CONFIG_DEBUG_INFO=y
|
||||
CONFIG_DEBUG_LL_INCLUDE="mach/debug-macro.S"
|
||||
CONFIG_DEBUG_MISC=y
|
||||
CONFIG_DMA_OPS=y
|
||||
CONFIG_DTC=y
|
||||
CONFIG_EDAC_ATOMIC_SCRUB=y
|
||||
CONFIG_EDAC_SUPPORT=y
|
||||
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
|
||||
CONFIG_FIXED_PHY=y
|
||||
CONFIG_FIX_EARLYCON_MEM=y
|
||||
CONFIG_FS_IOMAP=y
|
||||
CONFIG_FUNCTION_ALIGNMENT=0
|
||||
CONFIG_FWNODE_MDIO=y
|
||||
CONFIG_FW_LOADER_PAGED_BUF=y
|
||||
CONFIG_FW_LOADER_SYSFS=y
|
||||
CONFIG_GCC_ASM_GOTO_OUTPUT_WORKAROUND=y
|
||||
CONFIG_GENERIC_ALLOCATOR=y
|
||||
CONFIG_GENERIC_ARCH_TOPOLOGY=y
|
||||
CONFIG_GENERIC_BUG=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
|
||||
CONFIG_GENERIC_CPU_AUTOPROBE=y
|
||||
CONFIG_GENERIC_CPU_VULNERABILITIES=y
|
||||
CONFIG_GENERIC_EARLY_IOREMAP=y
|
||||
CONFIG_GENERIC_GETTIMEOFDAY=y
|
||||
CONFIG_GENERIC_IDLE_POLL_SETUP=y
|
||||
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
|
||||
CONFIG_GENERIC_IRQ_MIGRATION=y
|
||||
CONFIG_GENERIC_IRQ_MULTI_HANDLER=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_GENERIC_VDSO_32=y
|
||||
CONFIG_GPIOLIB_IRQCHIP=y
|
||||
CONFIG_GPIO_CDEV=y
|
||||
CONFIG_GPIO_EN7523=y
|
||||
CONFIG_GPIO_GENERIC=y
|
||||
# CONFIG_HARDEN_BRANCH_HISTORY is not set
|
||||
# CONFIG_HARDEN_BRANCH_PREDICTOR is not set
|
||||
CONFIG_HARDIRQS_SW_RESEND=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAS_IOPORT_MAP=y
|
||||
CONFIG_HAVE_SMP=y
|
||||
CONFIG_HOTPLUG_CORE_SYNC=y
|
||||
CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
|
||||
CONFIG_HOTPLUG_CPU=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HZ_FIXED=0
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
# CONFIG_IOMMUFD is not set
|
||||
# CONFIG_IOMMU_DEBUGFS is not set
|
||||
# CONFIG_IOMMU_IO_PGTABLE_ARMV7S is not set
|
||||
# CONFIG_IOMMU_IO_PGTABLE_LPAE is not set
|
||||
CONFIG_IOMMU_SUPPORT=y
|
||||
CONFIG_IRQCHIP=y
|
||||
CONFIG_IRQSTACKS=y
|
||||
CONFIG_IRQ_DOMAIN=y
|
||||
CONFIG_IRQ_DOMAIN_HIERARCHY=y
|
||||
CONFIG_IRQ_FORCED_THREADING=y
|
||||
CONFIG_IRQ_TIME_ACCOUNTING=y
|
||||
CONFIG_IRQ_WORK=y
|
||||
# CONFIG_LEDS_BRIGHTNESS_HW_CHANGED is not set
|
||||
CONFIG_LIBFDT=y
|
||||
CONFIG_LOCK_DEBUGGING_SUPPORT=y
|
||||
CONFIG_LOCK_SPIN_ON_OWNER=y
|
||||
CONFIG_LZO_COMPRESS=y
|
||||
CONFIG_LZO_DECOMPRESS=y
|
||||
CONFIG_MDIO_BUS=y
|
||||
CONFIG_MDIO_DEVICE=y
|
||||
CONFIG_MDIO_DEVRES=y
|
||||
CONFIG_MFD_SYSCON=y
|
||||
CONFIG_MIGHT_HAVE_CACHE_L2X0=y
|
||||
CONFIG_MIGRATION=y
|
||||
CONFIG_MMU_LAZY_TLB_REFCOUNT=y
|
||||
CONFIG_MODULES_USE_ELF_REL=y
|
||||
CONFIG_MTD_NAND_CORE=y
|
||||
CONFIG_MTD_NAND_ECC=y
|
||||
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
|
||||
CONFIG_MTD_SPI_NAND=y
|
||||
CONFIG_MTD_SPI_NOR=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_SRCU_NMI_SAFE=y
|
||||
CONFIG_NET_EGRESS=y
|
||||
CONFIG_NET_FLOW_LIMIT=y
|
||||
CONFIG_NET_INGRESS=y
|
||||
CONFIG_NET_SELFTESTS=y
|
||||
CONFIG_NET_XGRESS=y
|
||||
CONFIG_NLS=y
|
||||
CONFIG_NO_HZ_COMMON=y
|
||||
CONFIG_NO_HZ_IDLE=y
|
||||
CONFIG_NR_CPUS=2
|
||||
CONFIG_NVMEM=y
|
||||
CONFIG_NVMEM_LAYOUTS=y
|
||||
CONFIG_NVMEM_SYSFS=y
|
||||
CONFIG_OF=y
|
||||
CONFIG_OF_ADDRESS=y
|
||||
CONFIG_OF_EARLY_FLATTREE=y
|
||||
CONFIG_OF_FLATTREE=y
|
||||
CONFIG_OF_GPIO=y
|
||||
CONFIG_OF_IRQ=y
|
||||
CONFIG_OF_KOBJ=y
|
||||
CONFIG_OF_MDIO=y
|
||||
CONFIG_OLD_SIGACTION=y
|
||||
CONFIG_OLD_SIGSUSPEND3=y
|
||||
CONFIG_OUTER_CACHE=y
|
||||
CONFIG_OUTER_CACHE_SYNC=y
|
||||
CONFIG_PADATA=y
|
||||
CONFIG_PAGE_OFFSET=0xC0000000
|
||||
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_PCIEPORTBUS=y
|
||||
CONFIG_PCIE_MEDIATEK=y
|
||||
CONFIG_PCIE_PME=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PCI_DOMAINS_GENERIC=y
|
||||
CONFIG_PCI_MSI=y
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PGTABLE_LEVELS=2
|
||||
CONFIG_PHYLIB=y
|
||||
CONFIG_PHYLIB_LEDS=y
|
||||
CONFIG_PINCTRL=y
|
||||
CONFIG_PM=y
|
||||
CONFIG_PM_CLK=y
|
||||
CONFIG_PREEMPT_NONE_BUILD=y
|
||||
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
|
||||
CONFIG_PWM=y
|
||||
CONFIG_PWM_SYSFS=y
|
||||
CONFIG_RANDSTRUCT_NONE=y
|
||||
CONFIG_RAS=y
|
||||
CONFIG_RATIONAL=y
|
||||
CONFIG_REGMAP=y
|
||||
CONFIG_REGMAP_MMIO=y
|
||||
CONFIG_RESET_CONTROLLER=y
|
||||
CONFIG_RFS_ACCEL=y
|
||||
CONFIG_RPS=y
|
||||
CONFIG_RWSEM_SPIN_ON_OWNER=y
|
||||
CONFIG_SCSI=y
|
||||
CONFIG_SCSI_COMMON=y
|
||||
CONFIG_SERIAL_8250_EXTENDED=y
|
||||
CONFIG_SERIAL_8250_FSL=y
|
||||
# CONFIG_SERIAL_8250_SHARE_IRQ is not set
|
||||
CONFIG_SERIAL_MCTRL_GPIO=y
|
||||
CONFIG_SERIAL_OF_PLATFORM=y
|
||||
CONFIG_SGL_ALLOC=y
|
||||
CONFIG_SG_POOL=y
|
||||
CONFIG_SMP=y
|
||||
CONFIG_SMP_ON_UP=y
|
||||
CONFIG_SOCK_RX_QUEUE_MAPPING=y
|
||||
CONFIG_SOFTIRQ_ON_OWN_STACK=y
|
||||
CONFIG_SPARSE_IRQ=y
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_AIROHA_EN7523=y
|
||||
CONFIG_SPI_MASTER=y
|
||||
CONFIG_SPI_MEM=y
|
||||
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y
|
||||
CONFIG_STACKTRACE=y
|
||||
# CONFIG_SWAP is not set
|
||||
CONFIG_SWPHY=y
|
||||
CONFIG_SWP_EMULATE=y
|
||||
CONFIG_SYS_SUPPORTS_APM_EMULATION=y
|
||||
CONFIG_THREAD_INFO_IN_TASK=y
|
||||
CONFIG_TICK_CPU_ACCOUNTING=y
|
||||
CONFIG_TIMER_OF=y
|
||||
CONFIG_TIMER_PROBE=y
|
||||
CONFIG_TREE_RCU=y
|
||||
CONFIG_TREE_SRCU=y
|
||||
CONFIG_UBIFS_FS=y
|
||||
CONFIG_UNCOMPRESS_INCLUDE="debug/uncompress.h"
|
||||
CONFIG_UNWINDER_ARM=y
|
||||
CONFIG_USB=y
|
||||
CONFIG_USB_COMMON=y
|
||||
CONFIG_USB_SUPPORT=y
|
||||
CONFIG_USB_XHCI_HCD=y
|
||||
# CONFIG_USB_XHCI_PLATFORM is not set
|
||||
CONFIG_USE_OF=y
|
||||
# CONFIG_VFP is not set
|
||||
CONFIG_WATCHDOG_CORE=y
|
||||
# CONFIG_WQ_POWER_EFFICIENT_DEFAULT is not set
|
||||
CONFIG_XPS=y
|
||||
CONFIG_XXHASH=y
|
||||
CONFIG_XZ_DEC_ARM=y
|
||||
CONFIG_XZ_DEC_BCJ=y
|
||||
CONFIG_ZBOOT_ROM_BSS=0
|
||||
CONFIG_ZBOOT_ROM_TEXT=0
|
||||
CONFIG_ZLIB_DEFLATE=y
|
||||
CONFIG_ZLIB_INFLATE=y
|
||||
CONFIG_ZSTD_COMMON=y
|
||||
CONFIG_ZSTD_COMPRESS=y
|
||||
CONFIG_ZSTD_DECOMPRESS=y
|
@@ -1,34 +0,0 @@
|
||||
From 428ae88ef519f2009fac37563de76ffa6f93046f Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Danzberger <dd@embedd.com>
|
||||
Date: Sat, 9 Mar 2024 10:32:16 +0100
|
||||
Subject: [PATCH] arm64: add Airoha EN7581 platform
|
||||
|
||||
Introduce the Kconfig entry for the Airoha EN7581 multicore architecture
|
||||
available in the Airoha EN7581 evaluation board.
|
||||
|
||||
Signed-off-by: Daniel Danzberger <dd@embedd.com>
|
||||
Co-developed-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/d52d95db313e6a58ba997ba2181faf78a1014bcc.1709975956.git.lorenzo@kernel.org
|
||||
Signed-off-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
|
||||
---
|
||||
arch/arm64/Kconfig.platforms | 7 +++++++
|
||||
1 file changed, 7 insertions(+)
|
||||
|
||||
--- a/arch/arm64/Kconfig.platforms
|
||||
+++ b/arch/arm64/Kconfig.platforms
|
||||
@@ -8,6 +8,13 @@ config ARCH_ACTIONS
|
||||
help
|
||||
This enables support for the Actions Semiconductor S900 SoC family.
|
||||
|
||||
+config ARCH_AIROHA
|
||||
+ bool "Airoha SoC Support"
|
||||
+ select ARM_PSCI
|
||||
+ select HAVE_ARM_ARCH_TIMER
|
||||
+ help
|
||||
+ This enables support for the ARM64 based Airoha SoCs.
|
||||
+
|
||||
config ARCH_SUNXI
|
||||
bool "Allwinner sunxi 64-bit SoC Family"
|
||||
select ARCH_HAS_RESET_CONTROLLER
|
@@ -1,27 +0,0 @@
|
||||
From fd6acb0d21b8683fd8804129beeb4fe629488aff Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 9 Jul 2024 00:42:38 +0200
|
||||
Subject: [PATCH] i2c: mt7621: Add Airoha EN7581 i2c support
|
||||
|
||||
Introduce i2c support to Airoha EN7581 SoC through the i2c-mt7621
|
||||
driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Ray Liu <ray.liu@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Andi Shyti <andi.shyti@kernel.org>
|
||||
---
|
||||
drivers/i2c/busses/Kconfig | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/i2c/busses/Kconfig
|
||||
+++ b/drivers/i2c/busses/Kconfig
|
||||
@@ -841,7 +841,7 @@ config I2C_MT65XX
|
||||
|
||||
config I2C_MT7621
|
||||
tristate "MT7621/MT7628 I2C Controller"
|
||||
- depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || COMPILE_TEST
|
||||
+ depends on (RALINK && (SOC_MT7620 || SOC_MT7621)) || ARCH_AIROHA || COMPILE_TEST
|
||||
help
|
||||
Say Y here to include support for I2C controller in the
|
||||
MediaTek MT7621/MT7628 SoCs.
|
File diff suppressed because it is too large
Load Diff
@@ -1,46 +0,0 @@
|
||||
From 1f038d5897fe6b439039fc28420842abcc0d126b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 17 Jul 2024 10:15:46 +0200
|
||||
Subject: [PATCH] net: airoha: fix error branch in airoha_dev_xmit and
|
||||
airoha_set_gdm_ports
|
||||
|
||||
Fix error case management in airoha_dev_xmit routine since we need to
|
||||
DMA unmap pending buffers starting from q->head.
|
||||
Moreover fix a typo in error case branch in airoha_set_gdm_ports
|
||||
routine.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/b628871bc8ae4861b5e2ab4db90aaf373cbb7cee.1721203880.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -977,7 +977,7 @@ static int airoha_set_gdm_ports(struct a
|
||||
return 0;
|
||||
|
||||
error:
|
||||
- for (i--; i >= 0; i++)
|
||||
+ for (i--; i >= 0; i--)
|
||||
airoha_set_gdm_port(eth, port_list[i], false);
|
||||
|
||||
return err;
|
||||
@@ -2432,9 +2432,11 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
return NETDEV_TX_OK;
|
||||
|
||||
error_unmap:
|
||||
- for (i--; i >= 0; i++)
|
||||
- dma_unmap_single(dev->dev.parent, q->entry[i].dma_addr,
|
||||
- q->entry[i].dma_len, DMA_TO_DEVICE);
|
||||
+ for (i--; i >= 0; i--) {
|
||||
+ index = (q->head + i) % q->ndesc;
|
||||
+ dma_unmap_single(dev->dev.parent, q->entry[index].dma_addr,
|
||||
+ q->entry[index].dma_len, DMA_TO_DEVICE);
|
||||
+ }
|
||||
|
||||
spin_unlock_bh(&q->lock);
|
||||
error:
|
@@ -1,39 +0,0 @@
|
||||
From 4e076ff6ad5302c015617da30d877b4cdcbdf613 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 17 Jul 2024 10:47:19 +0200
|
||||
Subject: [PATCH] net: airoha: Fix NULL pointer dereference in
|
||||
airoha_qdma_cleanup_rx_queue()
|
||||
|
||||
Move page_pool_get_dma_dir() inside the while loop of
|
||||
airoha_qdma_cleanup_rx_queue routine in order to avoid possible NULL
|
||||
pointer dereference if airoha_qdma_init_rx_queue() fails before
|
||||
properly allocating the page_pool pointer.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/7330a41bba720c33abc039955f6172457a3a34f0.1721205981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 3 +--
|
||||
1 file changed, 1 insertion(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1586,7 +1586,6 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
struct airoha_eth *eth = q->eth;
|
||||
|
||||
while (q->queued) {
|
||||
@@ -1594,7 +1593,7 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
struct page *page = virt_to_head_page(e->buf);
|
||||
|
||||
dma_sync_single_for_cpu(eth->dev, e->dma_addr, e->dma_len,
|
||||
- dir);
|
||||
+ page_pool_get_dma_dir(q->page_pool));
|
||||
page_pool_put_full_page(q->page_pool, page, false);
|
||||
q->tail = (q->tail + 1) % q->ndesc;
|
||||
q->queued--;
|
@@ -1,27 +0,0 @@
|
||||
From 39a9c25bcdfb5e88995841c47439b74cac74a527 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 19 Jul 2024 22:38:31 +0200
|
||||
Subject: [PATCH] net: airoha: Fix MBI_RX_AGE_SEL_MASK definition
|
||||
|
||||
Fix copy-paste error in MBI_RX_AGE_SEL_MASK macro definition
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/d27d0465be1bff3369e886e5f10c4d37fefc4934.1721419930.git.lorenzo@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -249,7 +249,7 @@
|
||||
#define REG_FE_GDM_RX_ETH_L1023_CNT_H(_n) (GDM_BASE(_n) + 0x2fc)
|
||||
|
||||
#define REG_GDM2_CHN_RLS (GDM2_BASE + 0x20)
|
||||
-#define MBI_RX_AGE_SEL_MASK GENMASK(18, 17)
|
||||
+#define MBI_RX_AGE_SEL_MASK GENMASK(26, 25)
|
||||
#define MBI_TX_AGE_SEL_MASK GENMASK(18, 17)
|
||||
|
||||
#define REG_GDM3_FWD_CFG GDM3_BASE
|
@@ -1,553 +0,0 @@
|
||||
From 16874d1cf3818a5804cded8eaff634122b1d6c7c Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:03 +0200
|
||||
Subject: [PATCH 1/8] net: airoha: Introduce airoha_qdma struct
|
||||
|
||||
Introduce airoha_qdma struct and move qdma IO register mapping in
|
||||
airoha_qdma. This is a preliminary patch to enable both QDMA controllers
|
||||
available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/7df163bdc72ee29c3d27a0cbf54522ffeeafe53c.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 197 ++++++++++++---------
|
||||
1 file changed, 112 insertions(+), 85 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 1
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -782,6 +783,10 @@ struct airoha_hw_stats {
|
||||
u64 rx_len[7];
|
||||
};
|
||||
|
||||
+struct airoha_qdma {
|
||||
+ void __iomem *regs;
|
||||
+};
|
||||
+
|
||||
struct airoha_gdm_port {
|
||||
struct net_device *dev;
|
||||
struct airoha_eth *eth;
|
||||
@@ -794,8 +799,6 @@ struct airoha_eth {
|
||||
struct device *dev;
|
||||
|
||||
unsigned long state;
|
||||
-
|
||||
- void __iomem *qdma_regs;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
/* protect concurrent irqmask accesses */
|
||||
@@ -806,6 +809,7 @@ struct airoha_eth {
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
|
||||
struct net_device *napi_dev;
|
||||
@@ -850,16 +854,16 @@ static u32 airoha_rmw(void __iomem *base
|
||||
#define airoha_fe_clear(eth, offset, val) \
|
||||
airoha_rmw((eth)->fe_regs, (offset), (val), 0)
|
||||
|
||||
-#define airoha_qdma_rr(eth, offset) \
|
||||
- airoha_rr((eth)->qdma_regs, (offset))
|
||||
-#define airoha_qdma_wr(eth, offset, val) \
|
||||
- airoha_wr((eth)->qdma_regs, (offset), (val))
|
||||
-#define airoha_qdma_rmw(eth, offset, mask, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), (mask), (val))
|
||||
-#define airoha_qdma_set(eth, offset, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), 0, (val))
|
||||
-#define airoha_qdma_clear(eth, offset, val) \
|
||||
- airoha_rmw((eth)->qdma_regs, (offset), (val), 0)
|
||||
+#define airoha_qdma_rr(qdma, offset) \
|
||||
+ airoha_rr((qdma)->regs, (offset))
|
||||
+#define airoha_qdma_wr(qdma, offset, val) \
|
||||
+ airoha_wr((qdma)->regs, (offset), (val))
|
||||
+#define airoha_qdma_rmw(qdma, offset, mask, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (mask), (val))
|
||||
+#define airoha_qdma_set(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), 0, (val))
|
||||
+#define airoha_qdma_clear(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
|
||||
static void airoha_qdma_set_irqmask(struct airoha_eth *eth, int index,
|
||||
u32 clear, u32 set)
|
||||
@@ -873,11 +877,12 @@ static void airoha_qdma_set_irqmask(stru
|
||||
|
||||
eth->irqmask[index] &= ~clear;
|
||||
eth->irqmask[index] |= set;
|
||||
- airoha_qdma_wr(eth, REG_INT_ENABLE(index), eth->irqmask[index]);
|
||||
+ airoha_qdma_wr(ð->qdma[0], REG_INT_ENABLE(index),
|
||||
+ eth->irqmask[index]);
|
||||
/* Read irq_enable register in order to guarantee the update above
|
||||
* completes in the spinlock critical section.
|
||||
*/
|
||||
- airoha_qdma_rr(eth, REG_INT_ENABLE(index));
|
||||
+ airoha_qdma_rr(ð->qdma[0], REG_INT_ENABLE(index));
|
||||
|
||||
spin_unlock_irqrestore(ð->irq_lock, flags);
|
||||
}
|
||||
@@ -1383,6 +1388,7 @@ static int airoha_fe_init(struct airoha_
|
||||
static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
int qid = q - ð->q_rx[0];
|
||||
int nframes = 0;
|
||||
@@ -1420,7 +1426,8 @@ static int airoha_qdma_fill_rx_queue(str
|
||||
WRITE_ONCE(desc->msg2, 0);
|
||||
WRITE_ONCE(desc->msg3, 0);
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_RX_CPU_IDX(qid), RX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_CPU_IDX(qid),
|
||||
+ RX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_CPU_IDX_MASK, q->head));
|
||||
}
|
||||
|
||||
@@ -1529,7 +1536,8 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
}
|
||||
|
||||
static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q, int ndesc)
|
||||
+ struct airoha_queue *q,
|
||||
+ struct airoha_qdma *qdma, int ndesc)
|
||||
{
|
||||
const struct page_pool_params pp_params = {
|
||||
.order = 0,
|
||||
@@ -1569,14 +1577,15 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
netif_napi_add(eth->napi_dev, &q->napi, airoha_qdma_rx_napi_poll);
|
||||
|
||||
- airoha_qdma_wr(eth, REG_RX_RING_BASE(qid), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_RX_RING_SIZE(qid), RX_RING_SIZE_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_RX_RING_BASE(qid), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid),
|
||||
+ RX_RING_SIZE_MASK,
|
||||
FIELD_PREP(RX_RING_SIZE_MASK, ndesc));
|
||||
|
||||
thr = clamp(ndesc >> 3, 1, 32);
|
||||
- airoha_qdma_rmw(eth, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_RING_SIZE(qid), RX_RING_THR_MASK,
|
||||
FIELD_PREP(RX_RING_THR_MASK, thr));
|
||||
- airoha_qdma_rmw(eth, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_RX_DMA_IDX(qid), RX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(RX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
airoha_qdma_fill_rx_queue(q);
|
||||
@@ -1600,7 +1609,8 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_rx(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1613,7 +1623,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
}
|
||||
|
||||
err = airoha_qdma_init_rx_queue(eth, ð->q_rx[i],
|
||||
- RX_DSCP_NUM(i));
|
||||
+ qdma, RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1624,11 +1634,13 @@ static int airoha_qdma_init_rx(struct ai
|
||||
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_tx_irq_queue *irq_q;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct airoha_eth *eth;
|
||||
int id, done = 0;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
eth = irq_q->eth;
|
||||
+ qdma = ð->qdma[0];
|
||||
id = irq_q - ð->q_tx_irq[0];
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
@@ -1698,9 +1710,9 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
int i, len = done >> 7;
|
||||
|
||||
for (i = 0; i < len; i++)
|
||||
- airoha_qdma_rmw(eth, REG_IRQ_CLEAR_LEN(id),
|
||||
+ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id),
|
||||
IRQ_CLEAR_LEN_MASK, 0x80);
|
||||
- airoha_qdma_rmw(eth, REG_IRQ_CLEAR_LEN(id),
|
||||
+ airoha_qdma_rmw(qdma, REG_IRQ_CLEAR_LEN(id),
|
||||
IRQ_CLEAR_LEN_MASK, (done & 0x7f));
|
||||
}
|
||||
|
||||
@@ -1712,7 +1724,8 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
}
|
||||
|
||||
static int airoha_qdma_init_tx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q, int size)
|
||||
+ struct airoha_queue *q,
|
||||
+ struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int i, qid = q - ð->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
@@ -1739,10 +1752,10 @@ static int airoha_qdma_init_tx_queue(str
|
||||
WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val));
|
||||
}
|
||||
|
||||
- airoha_qdma_wr(eth, REG_TX_RING_BASE(qid), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
||||
- airoha_qdma_rmw(eth, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_DMA_IDX(qid), TX_RING_DMA_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_DMA_IDX_MASK, q->head));
|
||||
|
||||
return 0;
|
||||
@@ -1750,7 +1763,7 @@ static int airoha_qdma_init_tx_queue(str
|
||||
|
||||
static int airoha_qdma_tx_irq_init(struct airoha_eth *eth,
|
||||
struct airoha_tx_irq_queue *irq_q,
|
||||
- int size)
|
||||
+ struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int id = irq_q - ð->q_tx_irq[0];
|
||||
dma_addr_t dma_addr;
|
||||
@@ -1766,29 +1779,30 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
irq_q->size = size;
|
||||
irq_q->eth = eth;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
- airoha_qdma_rmw(eth, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
+ airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
FIELD_PREP(TX_IRQ_DEPTH_MASK, size));
|
||||
- airoha_qdma_rmw(eth, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_THR_MASK,
|
||||
FIELD_PREP(TX_IRQ_THR_MASK, 1));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_tx(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
err = airoha_qdma_tx_irq_init(eth, ð->q_tx_irq[i],
|
||||
- IRQ_QUEUE_LEN(i));
|
||||
+ qdma, IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
err = airoha_qdma_init_tx_queue(eth, ð->q_tx[i],
|
||||
- TX_DSCP_NUM);
|
||||
+ qdma, TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1815,7 +1829,8 @@ static void airoha_qdma_cleanup_tx_queue
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
dma_addr_t dma_addr;
|
||||
u32 status;
|
||||
@@ -1827,7 +1842,7 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
if (!eth->hfwd.desc)
|
||||
return -ENOMEM;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_FWD_DSCP_BASE, dma_addr);
|
||||
+ airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr);
|
||||
|
||||
size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM;
|
||||
eth->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
@@ -1835,14 +1850,14 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
if (!eth->hfwd.q)
|
||||
return -ENOMEM;
|
||||
|
||||
- airoha_qdma_wr(eth, REG_FWD_BUF_BASE, dma_addr);
|
||||
+ airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr);
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_HW_FWD_DSCP_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_HW_FWD_DSCP_CFG,
|
||||
HW_FWD_DSCP_PAYLOAD_SIZE_MASK,
|
||||
FIELD_PREP(HW_FWD_DSCP_PAYLOAD_SIZE_MASK, 0));
|
||||
- airoha_qdma_rmw(eth, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_FWD_DSCP_LOW_THR, FWD_DSCP_LOW_THR_MASK,
|
||||
FIELD_PREP(FWD_DSCP_LOW_THR_MASK, 128));
|
||||
- airoha_qdma_rmw(eth, REG_LMGR_INIT_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_LMGR_INIT_CFG,
|
||||
LMGR_INIT_START | LMGR_SRAM_MODE_MASK |
|
||||
HW_FWD_DESC_NUM_MASK,
|
||||
FIELD_PREP(HW_FWD_DESC_NUM_MASK, HW_DSCP_NUM) |
|
||||
@@ -1850,67 +1865,69 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
|
||||
return read_poll_timeout(airoha_qdma_rr, status,
|
||||
!(status & LMGR_INIT_START), USEC_PER_MSEC,
|
||||
- 30 * USEC_PER_MSEC, true, eth,
|
||||
+ 30 * USEC_PER_MSEC, true, qdma,
|
||||
REG_LMGR_INIT_CFG);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_init_qos(struct airoha_eth *eth)
|
||||
+static void airoha_qdma_init_qos(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
- airoha_qdma_clear(eth, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
- airoha_qdma_set(eth, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
+ airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
+ airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
|
||||
- airoha_qdma_clear(eth, REG_PSE_BUF_USAGE_CFG,
|
||||
+ airoha_qdma_clear(qdma, REG_PSE_BUF_USAGE_CFG,
|
||||
PSE_BUF_ESTIMATE_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_EN_MASK |
|
||||
EGRESS_RATE_METER_EQ_RATE_EN_MASK);
|
||||
/* 2047us x 31 = 63.457ms */
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_WINDOW_SZ_MASK,
|
||||
FIELD_PREP(EGRESS_RATE_METER_WINDOW_SZ_MASK, 0x1f));
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_RATE_METER_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_RATE_METER_CFG,
|
||||
EGRESS_RATE_METER_TIMESLICE_MASK,
|
||||
FIELD_PREP(EGRESS_RATE_METER_TIMESLICE_MASK, 0x7ff));
|
||||
|
||||
/* ratelimit init */
|
||||
- airoha_qdma_set(eth, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_set(qdma, REG_GLB_TRTCM_CFG, GLB_TRTCM_EN_MASK);
|
||||
/* fast-tick 25us */
|
||||
- airoha_qdma_rmw(eth, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_FAST_TICK_MASK,
|
||||
FIELD_PREP(GLB_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_GLB_TRTCM_CFG, GLB_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(GLB_SLOW_TICK_RATIO_MASK, 40));
|
||||
|
||||
- airoha_qdma_set(eth, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK,
|
||||
+ airoha_qdma_set(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG, EGRESS_FAST_TICK_MASK,
|
||||
FIELD_PREP(EGRESS_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_EGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_EGRESS_TRTCM_CFG,
|
||||
EGRESS_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(EGRESS_SLOW_TICK_RATIO_MASK, 40));
|
||||
|
||||
- airoha_qdma_set(eth, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK);
|
||||
- airoha_qdma_clear(eth, REG_INGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_clear(qdma, REG_INGRESS_TRTCM_CFG,
|
||||
INGRESS_TRTCM_MODE_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG, INGRESS_FAST_TICK_MASK,
|
||||
FIELD_PREP(INGRESS_FAST_TICK_MASK, 125));
|
||||
- airoha_qdma_rmw(eth, REG_INGRESS_TRTCM_CFG,
|
||||
+ airoha_qdma_rmw(qdma, REG_INGRESS_TRTCM_CFG,
|
||||
INGRESS_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(INGRESS_SLOW_TICK_RATIO_MASK, 8));
|
||||
|
||||
- airoha_qdma_set(eth, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK);
|
||||
- airoha_qdma_rmw(eth, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK,
|
||||
+ airoha_qdma_set(qdma, REG_SLA_TRTCM_CFG, SLA_TRTCM_EN_MASK);
|
||||
+ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_FAST_TICK_MASK,
|
||||
FIELD_PREP(SLA_FAST_TICK_MASK, 25));
|
||||
- airoha_qdma_rmw(eth, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_SLA_TRTCM_CFG, SLA_SLOW_TICK_RATIO_MASK,
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
-static int airoha_qdma_hw_init(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_hw_init(struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* clear pending irqs */
|
||||
for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++)
|
||||
- airoha_qdma_wr(eth, REG_INT_STATUS(i), 0xffffffff);
|
||||
+ airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
|
||||
|
||||
/* setup irqs */
|
||||
airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
@@ -1923,14 +1940,14 @@ static int airoha_qdma_hw_init(struct ai
|
||||
continue;
|
||||
|
||||
if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i))
|
||||
- airoha_qdma_set(eth, REG_TX_RING_BLOCKING(i),
|
||||
+ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(i),
|
||||
TX_RING_IRQ_BLOCKING_CFG_MASK);
|
||||
else
|
||||
- airoha_qdma_clear(eth, REG_TX_RING_BLOCKING(i),
|
||||
+ airoha_qdma_clear(qdma, REG_TX_RING_BLOCKING(i),
|
||||
TX_RING_IRQ_BLOCKING_CFG_MASK);
|
||||
}
|
||||
|
||||
- airoha_qdma_wr(eth, REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_wr(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_RX_2B_OFFSET_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_DMA_PREFERENCE_MASK, 3) |
|
||||
GLOBAL_CFG_CPU_TXR_RR_MASK |
|
||||
@@ -1941,18 +1958,18 @@ static int airoha_qdma_hw_init(struct ai
|
||||
GLOBAL_CFG_TX_WB_DONE_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2));
|
||||
|
||||
- airoha_qdma_init_qos(eth);
|
||||
+ airoha_qdma_init_qos(eth, qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
if (!eth->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- airoha_qdma_clear(eth, REG_RX_DELAY_INT_IDX(i),
|
||||
+ airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i),
|
||||
RX_DELAY_INT_MASK);
|
||||
}
|
||||
|
||||
- airoha_qdma_set(eth, REG_TXQ_CNGST_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG,
|
||||
TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN);
|
||||
|
||||
return 0;
|
||||
@@ -1962,12 +1979,14 @@ static irqreturn_t airoha_irq_handler(in
|
||||
{
|
||||
struct airoha_eth *eth = dev_instance;
|
||||
u32 intr[ARRAY_SIZE(eth->irqmask)];
|
||||
+ struct airoha_qdma *qdma;
|
||||
int i;
|
||||
|
||||
+ qdma = ð->qdma[0];
|
||||
for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++) {
|
||||
- intr[i] = airoha_qdma_rr(eth, REG_INT_STATUS(i));
|
||||
+ intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
|
||||
intr[i] &= eth->irqmask[i];
|
||||
- airoha_qdma_wr(eth, REG_INT_STATUS(i), intr[i]);
|
||||
+ airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
if (!test_bit(DEV_STATE_INITIALIZED, ð->state))
|
||||
@@ -1997,7 +2016,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
|
||||
- status = airoha_qdma_rr(eth, REG_IRQ_STATUS(i));
|
||||
+ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||||
irq_q->head = head % irq_q->size;
|
||||
irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
@@ -2011,6 +2030,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
|
||||
static int airoha_qdma_init(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int err;
|
||||
|
||||
err = devm_request_irq(eth->dev, eth->irq, airoha_irq_handler,
|
||||
@@ -2018,19 +2038,19 @@ static int airoha_qdma_init(struct airoh
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_rx(eth);
|
||||
+ err = airoha_qdma_init_rx(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_tx(eth);
|
||||
+ err = airoha_qdma_init_tx(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_hfwd_queues(eth);
|
||||
+ err = airoha_qdma_init_hfwd_queues(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(eth);
|
||||
+ err = airoha_qdma_hw_init(eth, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -2263,8 +2283,9 @@ static int airoha_dev_open(struct net_de
|
||||
airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK);
|
||||
- airoha_qdma_set(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ airoha_qdma_set(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2280,8 +2301,9 @@ static int airoha_dev_stop(struct net_de
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_TX_DMA_EN_MASK);
|
||||
- airoha_qdma_clear(eth, REG_QDMA_GLOBAL_CFG, GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ airoha_qdma_clear(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2341,6 +2363,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
struct airoha_eth *eth = port->eth;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
u16 index;
|
||||
@@ -2368,6 +2391,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
+ qdma = ð->qdma[0];
|
||||
q = ð->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
@@ -2412,7 +2436,8 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
e->dma_addr = addr;
|
||||
e->dma_len = len;
|
||||
|
||||
- airoha_qdma_rmw(eth, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
+ TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
|
||||
|
||||
data = skb_frag_address(frag);
|
||||
@@ -2614,9 +2639,11 @@ static int airoha_probe(struct platform_
|
||||
return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs),
|
||||
"failed to iomap fe regs\n");
|
||||
|
||||
- eth->qdma_regs = devm_platform_ioremap_resource_byname(pdev, "qdma0");
|
||||
- if (IS_ERR(eth->qdma_regs))
|
||||
- return dev_err_probe(eth->dev, PTR_ERR(eth->qdma_regs),
|
||||
+ eth->qdma[0].regs = devm_platform_ioremap_resource_byname(pdev,
|
||||
+ "qdma0");
|
||||
+ if (IS_ERR(eth->qdma[0].regs))
|
||||
+ return dev_err_probe(eth->dev,
|
||||
+ PTR_ERR(eth->qdma[0].regs),
|
||||
"failed to iomap qdma regs\n");
|
||||
|
||||
eth->rsts[0].id = "fe";
|
@@ -1,318 +0,0 @@
|
||||
From 245c7bc86b198e5ec227eba6b582da73cb0721c8 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:04 +0200
|
||||
Subject: [PATCH 2/8] net: airoha: Move airoha_queues in airoha_qdma
|
||||
|
||||
QDMA controllers available in EN7581 SoC have independent tx/rx hw queues
|
||||
so move them in airoha_queues structure.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/795fc4797bffbf7f0a1351308aa9bf0e65b5126e.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 126 +++++++++++----------
|
||||
1 file changed, 65 insertions(+), 61 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -785,6 +785,17 @@ struct airoha_hw_stats {
|
||||
|
||||
struct airoha_qdma {
|
||||
void __iomem *regs;
|
||||
+
|
||||
+ struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
+
|
||||
+ struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
+ struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
+
|
||||
+ /* descriptor and packet buffers for qdma hw forward */
|
||||
+ struct {
|
||||
+ void *desc;
|
||||
+ void *q;
|
||||
+ } hfwd;
|
||||
};
|
||||
|
||||
struct airoha_gdm_port {
|
||||
@@ -809,20 +820,10 @@ struct airoha_eth {
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
- struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
- struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
-
|
||||
struct net_device *napi_dev;
|
||||
- struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
- struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
-
|
||||
- struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
- /* descriptor and packet buffers for qdma hw forward */
|
||||
- struct {
|
||||
- void *desc;
|
||||
- void *q;
|
||||
- } hfwd;
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
+ struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
};
|
||||
|
||||
static u32 airoha_rr(void __iomem *base, u32 offset)
|
||||
@@ -1390,7 +1391,7 @@ static int airoha_qdma_fill_rx_queue(str
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
- int qid = q - ð->q_rx[0];
|
||||
+ int qid = q - &qdma->q_rx[0];
|
||||
int nframes = 0;
|
||||
|
||||
while (q->queued < q->ndesc - 1) {
|
||||
@@ -1457,8 +1458,9 @@ static int airoha_qdma_get_gdm_port(stru
|
||||
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
struct airoha_eth *eth = q->eth;
|
||||
- int qid = q - ð->q_rx[0];
|
||||
+ int qid = q - &qdma->q_rx[0];
|
||||
int done = 0;
|
||||
|
||||
while (done < budget) {
|
||||
@@ -1550,7 +1552,7 @@ static int airoha_qdma_init_rx_queue(str
|
||||
.dev = eth->dev,
|
||||
.napi = &q->napi,
|
||||
};
|
||||
- int qid = q - ð->q_rx[0], thr;
|
||||
+ int qid = q - &qdma->q_rx[0], thr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
q->buf_size = PAGE_SIZE / 2;
|
||||
@@ -1614,7 +1616,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
{
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
int err;
|
||||
|
||||
if (!(RX_DONE_INT_MASK & BIT(i))) {
|
||||
@@ -1622,7 +1624,7 @@ static int airoha_qdma_init_rx(struct ai
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = airoha_qdma_init_rx_queue(eth, ð->q_rx[i],
|
||||
+ err = airoha_qdma_init_rx_queue(eth, &qdma->q_rx[i],
|
||||
qdma, RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1641,7 +1643,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
eth = irq_q->eth;
|
||||
qdma = ð->qdma[0];
|
||||
- id = irq_q - ð->q_tx_irq[0];
|
||||
+ id = irq_q - &qdma->q_tx_irq[0];
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
@@ -1658,10 +1660,10 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||||
qid = FIELD_GET(IRQ_RING_IDX_MASK, val);
|
||||
|
||||
- if (qid >= ARRAY_SIZE(eth->q_tx))
|
||||
+ if (qid >= ARRAY_SIZE(qdma->q_tx))
|
||||
continue;
|
||||
|
||||
- q = ð->q_tx[qid];
|
||||
+ q = &qdma->q_tx[qid];
|
||||
if (!q->ndesc)
|
||||
continue;
|
||||
|
||||
@@ -1727,7 +1729,7 @@ static int airoha_qdma_init_tx_queue(str
|
||||
struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
- int i, qid = q - ð->q_tx[0];
|
||||
+ int i, qid = q - &qdma->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
@@ -1765,7 +1767,7 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
struct airoha_tx_irq_queue *irq_q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
- int id = irq_q - ð->q_tx_irq[0];
|
||||
+ int id = irq_q - &qdma->q_tx_irq[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
netif_napi_add_tx(eth->napi_dev, &irq_q->napi,
|
||||
@@ -1793,15 +1795,15 @@ static int airoha_qdma_init_tx(struct ai
|
||||
{
|
||||
int i, err;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- err = airoha_qdma_tx_irq_init(eth, ð->q_tx_irq[i],
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ err = airoha_qdma_tx_irq_init(eth, &qdma->q_tx_irq[i],
|
||||
qdma, IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- err = airoha_qdma_init_tx_queue(eth, ð->q_tx[i],
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ err = airoha_qdma_init_tx_queue(eth, &qdma->q_tx[i],
|
||||
qdma, TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -1837,17 +1839,17 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
int size;
|
||||
|
||||
size = HW_DSCP_NUM * sizeof(struct airoha_qdma_fwd_desc);
|
||||
- eth->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!eth->hfwd.desc)
|
||||
+ qdma->hfwd.desc = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!qdma->hfwd.desc)
|
||||
return -ENOMEM;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_FWD_DSCP_BASE, dma_addr);
|
||||
|
||||
size = AIROHA_MAX_PACKET_SIZE * HW_DSCP_NUM;
|
||||
- eth->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
- GFP_KERNEL);
|
||||
- if (!eth->hfwd.q)
|
||||
+ qdma->hfwd.q = dmam_alloc_coherent(eth->dev, size, &dma_addr,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!qdma->hfwd.q)
|
||||
return -ENOMEM;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_FWD_BUF_BASE, dma_addr);
|
||||
@@ -1935,8 +1937,8 @@ static int airoha_qdma_hw_init(struct ai
|
||||
airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
|
||||
/* setup irq binding */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- if (!eth->q_tx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
continue;
|
||||
|
||||
if (TX_RING_IRQ_BLOCKING_MAP_MASK & BIT(i))
|
||||
@@ -1961,8 +1963,8 @@ static int airoha_qdma_hw_init(struct ai
|
||||
airoha_qdma_init_qos(eth, qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
airoha_qdma_clear(qdma, REG_RX_DELAY_INT_IDX(i),
|
||||
@@ -1996,18 +1998,18 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
if (intr[1] & BIT(i))
|
||||
- napi_schedule(ð->q_rx[i].napi);
|
||||
+ napi_schedule(&qdma->q_rx[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
if (intr[0] & INT_TX_MASK) {
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- struct airoha_tx_irq_queue *irq_q = ð->q_tx_irq[i];
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i];
|
||||
u32 status, head;
|
||||
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
@@ -2021,7 +2023,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
irq_q->head = head % irq_q->size;
|
||||
irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
|
||||
- napi_schedule(ð->q_tx_irq[i].napi);
|
||||
+ napi_schedule(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2080,44 +2082,46 @@ static int airoha_hw_init(struct airoha_
|
||||
|
||||
static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_disable(ð->q_rx[i].napi);
|
||||
- netif_napi_del(ð->q_rx[i].napi);
|
||||
- airoha_qdma_cleanup_rx_queue(ð->q_rx[i]);
|
||||
- if (eth->q_rx[i].page_pool)
|
||||
- page_pool_destroy(eth->q_rx[i].page_pool);
|
||||
+ napi_disable(&qdma->q_rx[i].napi);
|
||||
+ netif_napi_del(&qdma->q_rx[i].napi);
|
||||
+ airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
|
||||
+ if (qdma->q_rx[i].page_pool)
|
||||
+ page_pool_destroy(qdma->q_rx[i].page_pool);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++) {
|
||||
- napi_disable(ð->q_tx_irq[i].napi);
|
||||
- netif_napi_del(ð->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
+ napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+ netif_napi_del(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx); i++) {
|
||||
- if (!eth->q_tx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- airoha_qdma_cleanup_tx_queue(ð->q_tx[i]);
|
||||
+ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
static void airoha_qdma_start_napi(struct airoha_eth *eth)
|
||||
{
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_tx_irq); i++)
|
||||
- napi_enable(ð->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
+ napi_enable(&qdma->q_tx_irq[i].napi);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->q_rx); i++) {
|
||||
- if (!eth->q_rx[i].ndesc)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_enable(ð->q_rx[i].napi);
|
||||
+ napi_enable(&qdma->q_rx[i].napi);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2392,7 +2396,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
qdma = ð->qdma[0];
|
||||
- q = ð->q_tx[qid];
|
||||
+ q = &qdma->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
|
@@ -1,236 +0,0 @@
|
||||
From 19e47fc2aeda3a657c4f64144ffd6e65f7a66601 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:05 +0200
|
||||
Subject: [PATCH 3/8] net: airoha: Move irq_mask in airoha_qdma structure
|
||||
|
||||
QDMA controllers have independent irq lines, so move irqmask in
|
||||
airoha_qdma structure. This is a preliminary patch to support multiple
|
||||
QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/1c8a06e8be605278a7b2f3cd8ac06e74bf5ebf2b.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 84 +++++++++++-----------
|
||||
1 file changed, 42 insertions(+), 42 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -786,6 +786,11 @@ struct airoha_hw_stats {
|
||||
struct airoha_qdma {
|
||||
void __iomem *regs;
|
||||
|
||||
+ /* protect concurrent irqmask accesses */
|
||||
+ spinlock_t irq_lock;
|
||||
+ u32 irqmask[QDMA_INT_REG_MAX];
|
||||
+ int irq;
|
||||
+
|
||||
struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
@@ -812,11 +817,6 @@ struct airoha_eth {
|
||||
unsigned long state;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
- /* protect concurrent irqmask accesses */
|
||||
- spinlock_t irq_lock;
|
||||
- u32 irqmask[QDMA_INT_REG_MAX];
|
||||
- int irq;
|
||||
-
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
@@ -866,38 +866,37 @@ static u32 airoha_rmw(void __iomem *base
|
||||
#define airoha_qdma_clear(qdma, offset, val) \
|
||||
airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
|
||||
-static void airoha_qdma_set_irqmask(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index,
|
||||
u32 clear, u32 set)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
- if (WARN_ON_ONCE(index >= ARRAY_SIZE(eth->irqmask)))
|
||||
+ if (WARN_ON_ONCE(index >= ARRAY_SIZE(qdma->irqmask)))
|
||||
return;
|
||||
|
||||
- spin_lock_irqsave(ð->irq_lock, flags);
|
||||
+ spin_lock_irqsave(&qdma->irq_lock, flags);
|
||||
|
||||
- eth->irqmask[index] &= ~clear;
|
||||
- eth->irqmask[index] |= set;
|
||||
- airoha_qdma_wr(ð->qdma[0], REG_INT_ENABLE(index),
|
||||
- eth->irqmask[index]);
|
||||
+ qdma->irqmask[index] &= ~clear;
|
||||
+ qdma->irqmask[index] |= set;
|
||||
+ airoha_qdma_wr(qdma, REG_INT_ENABLE(index), qdma->irqmask[index]);
|
||||
/* Read irq_enable register in order to guarantee the update above
|
||||
* completes in the spinlock critical section.
|
||||
*/
|
||||
- airoha_qdma_rr(ð->qdma[0], REG_INT_ENABLE(index));
|
||||
+ airoha_qdma_rr(qdma, REG_INT_ENABLE(index));
|
||||
|
||||
- spin_unlock_irqrestore(ð->irq_lock, flags);
|
||||
+ spin_unlock_irqrestore(&qdma->irq_lock, flags);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_irq_enable(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_irq_enable(struct airoha_qdma *qdma, int index,
|
||||
u32 mask)
|
||||
{
|
||||
- airoha_qdma_set_irqmask(eth, index, 0, mask);
|
||||
+ airoha_qdma_set_irqmask(qdma, index, 0, mask);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_irq_disable(struct airoha_eth *eth, int index,
|
||||
+static void airoha_qdma_irq_disable(struct airoha_qdma *qdma, int index,
|
||||
u32 mask)
|
||||
{
|
||||
- airoha_qdma_set_irqmask(eth, index, mask, 0);
|
||||
+ airoha_qdma_set_irqmask(qdma, index, mask, 0);
|
||||
}
|
||||
|
||||
static void airoha_set_macaddr(struct airoha_eth *eth, const u8 *addr)
|
||||
@@ -1522,7 +1521,7 @@ static int airoha_qdma_rx_process(struct
|
||||
static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
int cur, done = 0;
|
||||
|
||||
do {
|
||||
@@ -1531,7 +1530,7 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
} while (cur && done < budget);
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
return done;
|
||||
@@ -1719,7 +1718,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
}
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0,
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(id));
|
||||
|
||||
return done;
|
||||
@@ -1928,13 +1927,13 @@ static int airoha_qdma_hw_init(struct ai
|
||||
int i;
|
||||
|
||||
/* clear pending irqs */
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++)
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++)
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), 0xffffffff);
|
||||
|
||||
/* setup irqs */
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
|
||||
- airoha_qdma_irq_enable(eth, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX0, INT_IDX0_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1, INT_IDX1_MASK);
|
||||
+ airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX4, INT_IDX4_MASK);
|
||||
|
||||
/* setup irq binding */
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
@@ -1980,14 +1979,13 @@ static int airoha_qdma_hw_init(struct ai
|
||||
static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
struct airoha_eth *eth = dev_instance;
|
||||
- u32 intr[ARRAY_SIZE(eth->irqmask)];
|
||||
- struct airoha_qdma *qdma;
|
||||
+ struct airoha_qdma *qdma = ð->qdma[0];
|
||||
+ u32 intr[ARRAY_SIZE(qdma->irqmask)];
|
||||
int i;
|
||||
|
||||
- qdma = ð->qdma[0];
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->irqmask); i++) {
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->irqmask); i++) {
|
||||
intr[i] = airoha_qdma_rr(qdma, REG_INT_STATUS(i));
|
||||
- intr[i] &= eth->irqmask[i];
|
||||
+ intr[i] &= qdma->irqmask[i];
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
@@ -1995,7 +1993,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
return IRQ_NONE;
|
||||
|
||||
if (intr[1] & RX_DONE_INT_MASK) {
|
||||
- airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2015,7 +2013,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
continue;
|
||||
|
||||
- airoha_qdma_irq_disable(eth, QDMA_INT_REG_IDX0,
|
||||
+ airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
|
||||
status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
@@ -2030,12 +2028,18 @@ static irqreturn_t airoha_irq_handler(in
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init(struct airoha_eth *eth)
|
||||
+static int airoha_qdma_init(struct platform_device *pdev,
|
||||
+ struct airoha_eth *eth)
|
||||
{
|
||||
struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int err;
|
||||
|
||||
- err = devm_request_irq(eth->dev, eth->irq, airoha_irq_handler,
|
||||
+ spin_lock_init(&qdma->irq_lock);
|
||||
+ qdma->irq = platform_get_irq(pdev, 0);
|
||||
+ if (qdma->irq < 0)
|
||||
+ return qdma->irq;
|
||||
+
|
||||
+ err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
|
||||
IRQF_SHARED, KBUILD_MODNAME, eth);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -2061,7 +2065,8 @@ static int airoha_qdma_init(struct airoh
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_hw_init(struct airoha_eth *eth)
|
||||
+static int airoha_hw_init(struct platform_device *pdev,
|
||||
+ struct airoha_eth *eth)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -2077,7 +2082,7 @@ static int airoha_hw_init(struct airoha_
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- return airoha_qdma_init(eth);
|
||||
+ return airoha_qdma_init(pdev, eth);
|
||||
}
|
||||
|
||||
static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
@@ -2674,11 +2679,6 @@ static int airoha_probe(struct platform_
|
||||
return err;
|
||||
}
|
||||
|
||||
- spin_lock_init(ð->irq_lock);
|
||||
- eth->irq = platform_get_irq(pdev, 0);
|
||||
- if (eth->irq < 0)
|
||||
- return eth->irq;
|
||||
-
|
||||
eth->napi_dev = alloc_netdev_dummy(0);
|
||||
if (!eth->napi_dev)
|
||||
return -ENOMEM;
|
||||
@@ -2688,7 +2688,7 @@ static int airoha_probe(struct platform_
|
||||
strscpy(eth->napi_dev->name, "qdma_eth", sizeof(eth->napi_dev->name));
|
||||
platform_set_drvdata(pdev, eth);
|
||||
|
||||
- err = airoha_hw_init(eth);
|
||||
+ err = airoha_hw_init(pdev, eth);
|
||||
if (err)
|
||||
goto error;
|
||||
|
@@ -1,306 +0,0 @@
|
||||
From 9a2500ab22f059e596942172a8e4a60ae8243ce4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:06 +0200
|
||||
Subject: [PATCH 4/8] net: airoha: Add airoha_qdma pointer in
|
||||
airoha_tx_irq_queue/airoha_queue structures
|
||||
|
||||
Move airoha_eth pointer in airoha_qdma structure from
|
||||
airoha_tx_irq_queue/airoha_queue ones. This is a preliminary patch to
|
||||
introduce support for multi-QDMA controllers available on EN7581.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/074565b82fd0ceefe66e186f21133d825dbd48eb.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 84 +++++++++++-----------
|
||||
1 file changed, 41 insertions(+), 43 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -728,7 +728,7 @@ struct airoha_queue_entry {
|
||||
};
|
||||
|
||||
struct airoha_queue {
|
||||
- struct airoha_eth *eth;
|
||||
+ struct airoha_qdma *qdma;
|
||||
|
||||
/* protect concurrent queue accesses */
|
||||
spinlock_t lock;
|
||||
@@ -747,7 +747,7 @@ struct airoha_queue {
|
||||
};
|
||||
|
||||
struct airoha_tx_irq_queue {
|
||||
- struct airoha_eth *eth;
|
||||
+ struct airoha_qdma *qdma;
|
||||
|
||||
struct napi_struct napi;
|
||||
u32 *q;
|
||||
@@ -784,6 +784,7 @@ struct airoha_hw_stats {
|
||||
};
|
||||
|
||||
struct airoha_qdma {
|
||||
+ struct airoha_eth *eth;
|
||||
void __iomem *regs;
|
||||
|
||||
/* protect concurrent irqmask accesses */
|
||||
@@ -1388,8 +1389,8 @@ static int airoha_fe_init(struct airoha_
|
||||
static int airoha_qdma_fill_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = q->qdma;
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0];
|
||||
int nframes = 0;
|
||||
|
||||
@@ -1457,8 +1458,8 @@ static int airoha_qdma_get_gdm_port(stru
|
||||
static int airoha_qdma_rx_process(struct airoha_queue *q, int budget)
|
||||
{
|
||||
enum dma_data_direction dir = page_pool_get_dma_dir(q->page_pool);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_qdma *qdma = q->qdma;
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0];
|
||||
int done = 0;
|
||||
|
||||
@@ -1521,7 +1522,6 @@ static int airoha_qdma_rx_process(struct
|
||||
static int airoha_qdma_rx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_queue *q = container_of(napi, struct airoha_queue, napi);
|
||||
- struct airoha_qdma *qdma = &q->eth->qdma[0];
|
||||
int cur, done = 0;
|
||||
|
||||
do {
|
||||
@@ -1530,14 +1530,13 @@ static int airoha_qdma_rx_napi_poll(stru
|
||||
} while (cur && done < budget);
|
||||
|
||||
if (done < budget && napi_complete(napi))
|
||||
- airoha_qdma_irq_enable(qdma, QDMA_INT_REG_IDX1,
|
||||
+ airoha_qdma_irq_enable(q->qdma, QDMA_INT_REG_IDX1,
|
||||
RX_DONE_INT_MASK);
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q,
|
||||
+static int airoha_qdma_init_rx_queue(struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int ndesc)
|
||||
{
|
||||
const struct page_pool_params pp_params = {
|
||||
@@ -1548,15 +1547,16 @@ static int airoha_qdma_init_rx_queue(str
|
||||
.dma_dir = DMA_FROM_DEVICE,
|
||||
.max_len = PAGE_SIZE,
|
||||
.nid = NUMA_NO_NODE,
|
||||
- .dev = eth->dev,
|
||||
+ .dev = qdma->eth->dev,
|
||||
.napi = &q->napi,
|
||||
};
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int qid = q - &qdma->q_rx[0], thr;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
q->buf_size = PAGE_SIZE / 2;
|
||||
q->ndesc = ndesc;
|
||||
- q->eth = eth;
|
||||
+ q->qdma = qdma;
|
||||
|
||||
q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry),
|
||||
GFP_KERNEL);
|
||||
@@ -1596,7 +1596,7 @@ static int airoha_qdma_init_rx_queue(str
|
||||
|
||||
static void airoha_qdma_cleanup_rx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_eth *eth = q->qdma->eth;
|
||||
|
||||
while (q->queued) {
|
||||
struct airoha_queue_entry *e = &q->entry[q->tail];
|
||||
@@ -1610,8 +1610,7 @@ static void airoha_qdma_cleanup_rx_queue
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_rx(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_rx(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1623,8 +1622,8 @@ static int airoha_qdma_init_rx(struct ai
|
||||
continue;
|
||||
}
|
||||
|
||||
- err = airoha_qdma_init_rx_queue(eth, &qdma->q_rx[i],
|
||||
- qdma, RX_DSCP_NUM(i));
|
||||
+ err = airoha_qdma_init_rx_queue(&qdma->q_rx[i], qdma,
|
||||
+ RX_DSCP_NUM(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1640,9 +1639,9 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
int id, done = 0;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
- eth = irq_q->eth;
|
||||
- qdma = ð->qdma[0];
|
||||
+ qdma = irq_q->qdma;
|
||||
id = irq_q - &qdma->q_tx_irq[0];
|
||||
+ eth = qdma->eth;
|
||||
|
||||
while (irq_q->queued > 0 && done < budget) {
|
||||
u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
@@ -1724,16 +1723,16 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
return done;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx_queue(struct airoha_eth *eth,
|
||||
- struct airoha_queue *q,
|
||||
+static int airoha_qdma_init_tx_queue(struct airoha_queue *q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
int i, qid = q - &qdma->q_tx[0];
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
spin_lock_init(&q->lock);
|
||||
q->ndesc = size;
|
||||
- q->eth = eth;
|
||||
+ q->qdma = qdma;
|
||||
q->free_thr = 1 + MAX_SKB_FRAGS;
|
||||
|
||||
q->entry = devm_kzalloc(eth->dev, q->ndesc * sizeof(*q->entry),
|
||||
@@ -1762,11 +1761,11 @@ static int airoha_qdma_init_tx_queue(str
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_tx_irq_init(struct airoha_eth *eth,
|
||||
- struct airoha_tx_irq_queue *irq_q,
|
||||
+static int airoha_qdma_tx_irq_init(struct airoha_tx_irq_queue *irq_q,
|
||||
struct airoha_qdma *qdma, int size)
|
||||
{
|
||||
int id = irq_q - &qdma->q_tx_irq[0];
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
dma_addr_t dma_addr;
|
||||
|
||||
netif_napi_add_tx(eth->napi_dev, &irq_q->napi,
|
||||
@@ -1778,7 +1777,7 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
|
||||
memset(irq_q->q, 0xff, size * sizeof(u32));
|
||||
irq_q->size = size;
|
||||
- irq_q->eth = eth;
|
||||
+ irq_q->qdma = qdma;
|
||||
|
||||
airoha_qdma_wr(qdma, REG_TX_IRQ_BASE(id), dma_addr);
|
||||
airoha_qdma_rmw(qdma, REG_TX_IRQ_CFG(id), TX_IRQ_DEPTH_MASK,
|
||||
@@ -1789,21 +1788,20 @@ static int airoha_qdma_tx_irq_init(struc
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_tx(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_tx(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i, err;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
- err = airoha_qdma_tx_irq_init(eth, &qdma->q_tx_irq[i],
|
||||
- qdma, IRQ_QUEUE_LEN(i));
|
||||
+ err = airoha_qdma_tx_irq_init(&qdma->q_tx_irq[i], qdma,
|
||||
+ IRQ_QUEUE_LEN(i));
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
- err = airoha_qdma_init_tx_queue(eth, &qdma->q_tx[i],
|
||||
- qdma, TX_DSCP_NUM);
|
||||
+ err = airoha_qdma_init_tx_queue(&qdma->q_tx[i], qdma,
|
||||
+ TX_DSCP_NUM);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
@@ -1813,7 +1811,7 @@ static int airoha_qdma_init_tx(struct ai
|
||||
|
||||
static void airoha_qdma_cleanup_tx_queue(struct airoha_queue *q)
|
||||
{
|
||||
- struct airoha_eth *eth = q->eth;
|
||||
+ struct airoha_eth *eth = q->qdma->eth;
|
||||
|
||||
spin_lock_bh(&q->lock);
|
||||
while (q->queued) {
|
||||
@@ -1830,9 +1828,9 @@ static void airoha_qdma_cleanup_tx_queue
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
||||
-static int airoha_qdma_init_hfwd_queues(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_init_hfwd_queues(struct airoha_qdma *qdma)
|
||||
{
|
||||
+ struct airoha_eth *eth = qdma->eth;
|
||||
dma_addr_t dma_addr;
|
||||
u32 status;
|
||||
int size;
|
||||
@@ -1870,8 +1868,7 @@ static int airoha_qdma_init_hfwd_queues(
|
||||
REG_LMGR_INIT_CFG);
|
||||
}
|
||||
|
||||
-static void airoha_qdma_init_qos(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static void airoha_qdma_init_qos(struct airoha_qdma *qdma)
|
||||
{
|
||||
airoha_qdma_clear(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_SCALE_MASK);
|
||||
airoha_qdma_set(qdma, REG_TXWRR_MODE_CFG, TWRR_WEIGHT_BASE_MASK);
|
||||
@@ -1921,8 +1918,7 @@ static void airoha_qdma_init_qos(struct
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
-static int airoha_qdma_hw_init(struct airoha_eth *eth,
|
||||
- struct airoha_qdma *qdma)
|
||||
+static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -1959,7 +1955,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
GLOBAL_CFG_TX_WB_DONE_MASK |
|
||||
FIELD_PREP(GLOBAL_CFG_MAX_ISSUE_NUM_MASK, 2));
|
||||
|
||||
- airoha_qdma_init_qos(eth, qdma);
|
||||
+ airoha_qdma_init_qos(qdma);
|
||||
|
||||
/* disable qdma rx delay interrupt */
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2035,6 +2031,8 @@ static int airoha_qdma_init(struct platf
|
||||
int err;
|
||||
|
||||
spin_lock_init(&qdma->irq_lock);
|
||||
+ qdma->eth = eth;
|
||||
+
|
||||
qdma->irq = platform_get_irq(pdev, 0);
|
||||
if (qdma->irq < 0)
|
||||
return qdma->irq;
|
||||
@@ -2044,19 +2042,19 @@ static int airoha_qdma_init(struct platf
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_rx(eth, qdma);
|
||||
+ err = airoha_qdma_init_rx(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_tx(eth, qdma);
|
||||
+ err = airoha_qdma_init_tx(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_init_hfwd_queues(eth, qdma);
|
||||
+ err = airoha_qdma_init_hfwd_queues(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(eth, qdma);
|
||||
+ err = airoha_qdma_hw_init(qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
@@ -1,45 +0,0 @@
|
||||
From e3d6bfdfc0aeb8c1d7965413b1050ec07f9761e5 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:07 +0200
|
||||
Subject: [PATCH 5/8] net: airoha: Use qdma pointer as private structure in
|
||||
airoha_irq_handler routine
|
||||
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/1e40c3cb973881c0eb3c3c247c78550da62054ab.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 7 +++----
|
||||
1 file changed, 3 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1974,8 +1974,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
|
||||
static irqreturn_t airoha_irq_handler(int irq, void *dev_instance)
|
||||
{
|
||||
- struct airoha_eth *eth = dev_instance;
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
+ struct airoha_qdma *qdma = dev_instance;
|
||||
u32 intr[ARRAY_SIZE(qdma->irqmask)];
|
||||
int i;
|
||||
|
||||
@@ -1985,7 +1984,7 @@ static irqreturn_t airoha_irq_handler(in
|
||||
airoha_qdma_wr(qdma, REG_INT_STATUS(i), intr[i]);
|
||||
}
|
||||
|
||||
- if (!test_bit(DEV_STATE_INITIALIZED, ð->state))
|
||||
+ if (!test_bit(DEV_STATE_INITIALIZED, &qdma->eth->state))
|
||||
return IRQ_NONE;
|
||||
|
||||
if (intr[1] & RX_DONE_INT_MASK) {
|
||||
@@ -2038,7 +2037,7 @@ static int airoha_qdma_init(struct platf
|
||||
return qdma->irq;
|
||||
|
||||
err = devm_request_irq(eth->dev, qdma->irq, airoha_irq_handler,
|
||||
- IRQF_SHARED, KBUILD_MODNAME, eth);
|
||||
+ IRQF_SHARED, KBUILD_MODNAME, qdma);
|
||||
if (err)
|
||||
return err;
|
||||
|
@@ -1,131 +0,0 @@
|
||||
From e618447cf492d04415007336eec025fae6e9a2ea Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:08 +0200
|
||||
Subject: [PATCH 6/8] net: airoha: Allow mapping IO region for multiple qdma
|
||||
controllers
|
||||
|
||||
Map MMIO regions of both qdma controllers available on EN7581 SoC.
|
||||
Run airoha_hw_cleanup routine for both QDMA controllers available on
|
||||
EN7581 SoC removing airoha_eth module or in airoha_probe error path.
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/a734ae608da14b67ae749b375d880dbbc70868ea.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 56 ++++++++++++----------
|
||||
1 file changed, 32 insertions(+), 24 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2024,15 +2024,25 @@ static irqreturn_t airoha_irq_handler(in
|
||||
}
|
||||
|
||||
static int airoha_qdma_init(struct platform_device *pdev,
|
||||
- struct airoha_eth *eth)
|
||||
+ struct airoha_eth *eth,
|
||||
+ struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
- int err;
|
||||
+ int err, id = qdma - ð->qdma[0];
|
||||
+ const char *res;
|
||||
|
||||
spin_lock_init(&qdma->irq_lock);
|
||||
qdma->eth = eth;
|
||||
|
||||
- qdma->irq = platform_get_irq(pdev, 0);
|
||||
+ res = devm_kasprintf(eth->dev, GFP_KERNEL, "qdma%d", id);
|
||||
+ if (!res)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ qdma->regs = devm_platform_ioremap_resource_byname(pdev, res);
|
||||
+ if (IS_ERR(qdma->regs))
|
||||
+ return dev_err_probe(eth->dev, PTR_ERR(qdma->regs),
|
||||
+ "failed to iomap qdma%d regs\n", id);
|
||||
+
|
||||
+ qdma->irq = platform_get_irq(pdev, 4 * id);
|
||||
if (qdma->irq < 0)
|
||||
return qdma->irq;
|
||||
|
||||
@@ -2053,19 +2063,13 @@ static int airoha_qdma_init(struct platf
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = airoha_qdma_hw_init(qdma);
|
||||
- if (err)
|
||||
- return err;
|
||||
-
|
||||
- set_bit(DEV_STATE_INITIALIZED, ð->state);
|
||||
-
|
||||
- return 0;
|
||||
+ return airoha_qdma_hw_init(qdma);
|
||||
}
|
||||
|
||||
static int airoha_hw_init(struct platform_device *pdev,
|
||||
struct airoha_eth *eth)
|
||||
{
|
||||
- int err;
|
||||
+ int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
|
||||
@@ -2079,12 +2083,19 @@ static int airoha_hw_init(struct platfor
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- return airoha_qdma_init(pdev, eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
|
||||
+ err = airoha_qdma_init(pdev, eth, ð->qdma[i]);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ set_bit(DEV_STATE_INITIALIZED, ð->state);
|
||||
+
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
-static void airoha_hw_cleanup(struct airoha_eth *eth)
|
||||
+static void airoha_hw_cleanup(struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
@@ -2645,13 +2656,6 @@ static int airoha_probe(struct platform_
|
||||
return dev_err_probe(eth->dev, PTR_ERR(eth->fe_regs),
|
||||
"failed to iomap fe regs\n");
|
||||
|
||||
- eth->qdma[0].regs = devm_platform_ioremap_resource_byname(pdev,
|
||||
- "qdma0");
|
||||
- if (IS_ERR(eth->qdma[0].regs))
|
||||
- return dev_err_probe(eth->dev,
|
||||
- PTR_ERR(eth->qdma[0].regs),
|
||||
- "failed to iomap qdma regs\n");
|
||||
-
|
||||
eth->rsts[0].id = "fe";
|
||||
eth->rsts[1].id = "pdma";
|
||||
eth->rsts[2].id = "qdma";
|
||||
@@ -2707,7 +2711,9 @@ static int airoha_probe(struct platform_
|
||||
return 0;
|
||||
|
||||
error:
|
||||
- airoha_hw_cleanup(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_hw_cleanup(ð->qdma[i]);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
||||
@@ -2725,7 +2731,9 @@ static void airoha_remove(struct platfor
|
||||
struct airoha_eth *eth = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
- airoha_hw_cleanup(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_hw_cleanup(ð->qdma[i]);
|
||||
+
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
@@ -1,38 +0,0 @@
|
||||
From 160231e34b8e9512ba20530f3e68fb0ac499af87 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:09 +0200
|
||||
Subject: [PATCH 7/8] net: airoha: Start all qdma NAPIs in airoha_probe()
|
||||
|
||||
This is a preliminary patch to support multi-QDMA controllers.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/b51cf69c94d8cbc81e0a0b35587f024d01e6d9c0.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 7 ++++---
|
||||
1 file changed, 4 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2122,9 +2122,8 @@ static void airoha_hw_cleanup(struct air
|
||||
}
|
||||
}
|
||||
|
||||
-static void airoha_qdma_start_napi(struct airoha_eth *eth)
|
||||
+static void airoha_qdma_start_napi(struct airoha_qdma *qdma)
|
||||
{
|
||||
- struct airoha_qdma *qdma = ð->qdma[0];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
@@ -2693,7 +2692,9 @@ static int airoha_probe(struct platform_
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
- airoha_qdma_start_napi(eth);
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_qdma_start_napi(ð->qdma[i]);
|
||||
+
|
||||
for_each_child_of_node(pdev->dev.of_node, np) {
|
||||
if (!of_device_is_compatible(np, "airoha,eth-mac"))
|
||||
continue;
|
@@ -1,174 +0,0 @@
|
||||
From 9304640f2f78147dddf97a5ea01502ae175e41d9 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 16:35:10 +0200
|
||||
Subject: [PATCH 8/8] net: airoha: Link the gdm port to the selected qdma
|
||||
controller
|
||||
|
||||
Link the running gdm port to the qdma controller used to connect with
|
||||
the CPU. Moreover, load all QDMA controllers available on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/95b515df34ba4727f7ae5b14a1d0462cceec84ff.1722522582.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 37 +++++++++++-----------
|
||||
1 file changed, 19 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
-#define AIROHA_MAX_NUM_QDMA 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 2
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -805,8 +805,8 @@ struct airoha_qdma {
|
||||
};
|
||||
|
||||
struct airoha_gdm_port {
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
- struct airoha_eth *eth;
|
||||
int id;
|
||||
|
||||
struct airoha_hw_stats stats;
|
||||
@@ -2139,7 +2139,7 @@ static void airoha_qdma_start_napi(struc
|
||||
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_port *port)
|
||||
{
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
u32 val, i = 0;
|
||||
|
||||
spin_lock(&port->stats.lock);
|
||||
@@ -2284,22 +2284,22 @@ static void airoha_update_hw_stats(struc
|
||||
static int airoha_dev_open(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
int err;
|
||||
|
||||
netif_tx_start_all_queues(dev);
|
||||
- err = airoha_set_gdm_ports(eth, true);
|
||||
+ err = airoha_set_gdm_ports(qdma->eth, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (netdev_uses_dsa(dev))
|
||||
- airoha_fe_set(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
+ airoha_fe_set(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
else
|
||||
- airoha_fe_clear(eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
+ airoha_fe_clear(qdma->eth, REG_GDM_INGRESS_CFG(port->id),
|
||||
GDM_STAG_EN_MASK);
|
||||
|
||||
- airoha_qdma_set(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
@@ -2309,15 +2309,15 @@ static int airoha_dev_open(struct net_de
|
||||
static int airoha_dev_stop(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
int err;
|
||||
|
||||
netif_tx_disable(dev);
|
||||
- err = airoha_set_gdm_ports(eth, false);
|
||||
+ err = airoha_set_gdm_ports(qdma->eth, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(ð->qdma[0], REG_QDMA_GLOBAL_CFG,
|
||||
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
@@ -2333,7 +2333,7 @@ static int airoha_dev_set_macaddr(struct
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_set_macaddr(port->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2342,7 +2342,7 @@ static int airoha_dev_init(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
|
||||
- airoha_set_macaddr(port->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2376,10 +2376,9 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
u32 msg0 = 0, msg1, len = skb_headlen(skb);
|
||||
int i, qid = skb_get_queue_mapping(skb);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_qdma *qdma = port->qdma;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
- struct airoha_qdma *qdma;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
u16 index;
|
||||
@@ -2407,7 +2406,6 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
|
||||
|
||||
- qdma = ð->qdma[0];
|
||||
q = &qdma->q_tx[qid];
|
||||
if (WARN_ON_ONCE(!q->ndesc))
|
||||
goto error;
|
||||
@@ -2490,7 +2488,7 @@ static void airoha_ethtool_get_drvinfo(s
|
||||
struct ethtool_drvinfo *info)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- struct airoha_eth *eth = port->eth;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
|
||||
strscpy(info->driver, eth->dev->driver->name, sizeof(info->driver));
|
||||
strscpy(info->bus_info, dev_name(eth->dev), sizeof(info->bus_info));
|
||||
@@ -2571,6 +2569,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
{
|
||||
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
|
||||
struct airoha_gdm_port *port;
|
||||
+ struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
int err, index;
|
||||
u32 id;
|
||||
@@ -2600,6 +2599,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
+ qdma = ð->qdma[index % AIROHA_MAX_NUM_QDMA];
|
||||
dev->netdev_ops = &airoha_netdev_ops;
|
||||
dev->ethtool_ops = &airoha_ethtool_ops;
|
||||
dev->max_mtu = AIROHA_MAX_MTU;
|
||||
@@ -2609,6 +2609,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
NETIF_F_SG | NETIF_F_TSO;
|
||||
dev->features |= dev->hw_features;
|
||||
dev->dev.of_node = np;
|
||||
+ dev->irq = qdma->irq;
|
||||
SET_NETDEV_DEV(dev, eth->dev);
|
||||
|
||||
err = of_get_ethdev_address(np, dev);
|
||||
@@ -2624,8 +2625,8 @@ static int airoha_alloc_gdm_port(struct
|
||||
port = netdev_priv(dev);
|
||||
u64_stats_init(&port->stats.syncp);
|
||||
spin_lock_init(&port->stats.lock);
|
||||
+ port->qdma = qdma;
|
||||
port->dev = dev;
|
||||
- port->eth = eth;
|
||||
port->id = id;
|
||||
eth->ports[index] = port;
|
||||
|
@@ -1,44 +0,0 @@
|
||||
From 63a796b4988c3dca83176a534890b510d44f105a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 3 Aug 2024 17:50:50 +0200
|
||||
Subject: [PATCH] net: airoha: honor reset return value in airoha_hw_init()
|
||||
|
||||
Take into account return value from reset_control_bulk_assert and
|
||||
reset_control_bulk_deassert routines in airoha_hw_init().
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/f49dc04a87653e0155f4fab3e3eb584785c8ad6a.1722699555.git.lorenzo@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 16 ++++++++++++----
|
||||
1 file changed, 12 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2072,13 +2072,21 @@ static int airoha_hw_init(struct platfor
|
||||
int err, i;
|
||||
|
||||
/* disable xsi */
|
||||
- reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
|
||||
+ err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts),
|
||||
+ eth->xsi_rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
- reset_control_bulk_assert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
- msleep(20);
|
||||
- reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
msleep(20);
|
||||
+ err = reset_control_bulk_deassert(ARRAY_SIZE(eth->rsts), eth->rsts);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
+ msleep(20);
|
||||
err = airoha_fe_init(eth);
|
||||
if (err)
|
||||
return err;
|
@@ -1,85 +0,0 @@
|
||||
From 812a2751e827fa1eb01f3bd268b4d74c23f4226a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 21 Aug 2024 09:30:14 +0200
|
||||
Subject: [PATCH] net: airoha: configure hw mac address according to the port
|
||||
id
|
||||
|
||||
GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
||||
GDM{2,3,4} can be used as wan port connected to an external
|
||||
phy module. Configure hw mac address registers according to the port id.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240821-airoha-eth-wan-mac-addr-v2-1-8706d0cd6cd5@kernel.org
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 32 ++++++++++++++++------
|
||||
1 file changed, 23 insertions(+), 9 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -67,9 +67,11 @@
|
||||
#define FE_RST_GDM3_MBI_ARB_MASK BIT(2)
|
||||
#define FE_RST_CORE_MASK BIT(0)
|
||||
|
||||
+#define REG_FE_WAN_MAC_H 0x0030
|
||||
#define REG_FE_LAN_MAC_H 0x0040
|
||||
-#define REG_FE_LAN_MAC_LMIN 0x0044
|
||||
-#define REG_FE_LAN_MAC_LMAX 0x0048
|
||||
+
|
||||
+#define REG_FE_MAC_LMIN(_n) ((_n) + 0x04)
|
||||
+#define REG_FE_MAC_LMAX(_n) ((_n) + 0x08)
|
||||
|
||||
#define REG_FE_CDM1_OQ_MAP0 0x0050
|
||||
#define REG_FE_CDM1_OQ_MAP1 0x0054
|
||||
@@ -900,16 +902,28 @@ static void airoha_qdma_irq_disable(stru
|
||||
airoha_qdma_set_irqmask(qdma, index, mask, 0);
|
||||
}
|
||||
|
||||
-static void airoha_set_macaddr(struct airoha_eth *eth, const u8 *addr)
|
||||
+static bool airhoa_is_lan_gdm_port(struct airoha_gdm_port *port)
|
||||
{
|
||||
- u32 val;
|
||||
+ /* GDM1 port on EN7581 SoC is connected to the lan dsa switch.
|
||||
+ * GDM{2,3,4} can be used as wan port connected to an external
|
||||
+ * phy module.
|
||||
+ */
|
||||
+ return port->id == 1;
|
||||
+}
|
||||
+
|
||||
+static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
|
||||
+{
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
+ u32 val, reg;
|
||||
|
||||
+ reg = airhoa_is_lan_gdm_port(port) ? REG_FE_LAN_MAC_H
|
||||
+ : REG_FE_WAN_MAC_H;
|
||||
val = (addr[0] << 16) | (addr[1] << 8) | addr[2];
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_H, val);
|
||||
+ airoha_fe_wr(eth, reg, val);
|
||||
|
||||
val = (addr[3] << 16) | (addr[4] << 8) | addr[5];
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_LMIN, val);
|
||||
- airoha_fe_wr(eth, REG_FE_LAN_MAC_LMAX, val);
|
||||
+ airoha_fe_wr(eth, REG_FE_MAC_LMIN(reg), val);
|
||||
+ airoha_fe_wr(eth, REG_FE_MAC_LMAX(reg), val);
|
||||
}
|
||||
|
||||
static void airoha_set_gdm_port_fwd_cfg(struct airoha_eth *eth, u32 addr,
|
||||
@@ -2341,7 +2355,7 @@ static int airoha_dev_set_macaddr(struct
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2350,7 +2364,7 @@ static int airoha_dev_init(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
|
||||
- airoha_set_macaddr(port->qdma->eth, dev->dev_addr);
|
||||
+ airoha_set_macaddr(port, dev->dev_addr);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
From 7d2bd8ac9d2494cf9b16c4b00df9424ad24ed18c Mon Sep 17 00:00:00 2001
|
||||
From: Liao Chen <liaochen4@huawei.com>
|
||||
Date: Mon, 26 Aug 2024 09:18:58 +0000
|
||||
Subject: [PATCH] net: airoha: fix module autoloading
|
||||
|
||||
Add MODULE_DEVICE_TABLE(), so modules could be properly autoloaded
|
||||
based on the alias from of_device_id table.
|
||||
|
||||
Signed-off-by: Liao Chen <liaochen4@huawei.com>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240826091858.369910-4-liaochen4@huawei.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 1 +
|
||||
1 file changed, 1 insertion(+)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2776,6 +2776,7 @@ static const struct of_device_id of_airo
|
||||
{ .compatible = "airoha,en7581-eth" },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
+MODULE_DEVICE_TABLE(of, of_airoha_match);
|
||||
|
||||
static struct platform_driver airoha_driver = {
|
||||
.probe = airoha_probe,
|
@@ -1,40 +0,0 @@
|
||||
From 8e38e08f2c560328a873c35aff1a0dbea6a7d084 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 1 Oct 2024 12:10:25 +0200
|
||||
Subject: [PATCH 2/2] net: airoha: fix PSE memory configuration in
|
||||
airoha_fe_pse_ports_init()
|
||||
|
||||
Align PSE memory configuration to vendor SDK. In particular, increase
|
||||
initial value of PSE reserved memory in airoha_fe_pse_ports_init()
|
||||
routine by the value used for the second Packet Processor Engine (PPE2)
|
||||
and do not overwrite the default value.
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support
|
||||
for EN7581 SoC")
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241001-airoha-eth-pse-fix-v2-2-9a56cdffd074@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 6 ++++--
|
||||
1 file changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1166,11 +1166,13 @@ static void airoha_fe_pse_ports_init(str
|
||||
[FE_PSE_PORT_GDM4] = 2,
|
||||
[FE_PSE_PORT_CDM5] = 2,
|
||||
};
|
||||
+ u32 all_rsv;
|
||||
int q;
|
||||
|
||||
+ all_rsv = airoha_fe_get_pse_all_rsv(eth);
|
||||
/* hw misses PPE2 oq rsv */
|
||||
- airoha_fe_set(eth, REG_FE_PSE_BUF_SET,
|
||||
- PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2]);
|
||||
+ all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2];
|
||||
+ airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv);
|
||||
|
||||
/* CMD1 */
|
||||
for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_CDM1]; q++)
|
@@ -1,52 +0,0 @@
|
||||
From 1f3e7ff4f296af1f4350f457d5bd82bc825e645a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 1 Oct 2024 12:10:24 +0200
|
||||
Subject: [PATCH 1/2] net: airoha: read default PSE reserved pages value before
|
||||
updating
|
||||
|
||||
Store the default value for the number of PSE reserved pages in orig_val
|
||||
at the beginning of airoha_fe_set_pse_oq_rsv routine, before updating it
|
||||
with airoha_fe_set_pse_queue_rsv_pages().
|
||||
Introduce airoha_fe_get_pse_all_rsv utility routine.
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support
|
||||
for EN7581 SoC")
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241001-airoha-eth-pse-fix-v2-1-9a56cdffd074@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 14 ++++++++++----
|
||||
1 file changed, 10 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1116,17 +1116,23 @@ static void airoha_fe_set_pse_queue_rsv_
|
||||
PSE_CFG_WR_EN_MASK | PSE_CFG_OQRSV_SEL_MASK);
|
||||
}
|
||||
|
||||
+static u32 airoha_fe_get_pse_all_rsv(struct airoha_eth *eth)
|
||||
+{
|
||||
+ u32 val = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
|
||||
+
|
||||
+ return FIELD_GET(PSE_ALLRSV_MASK, val);
|
||||
+}
|
||||
+
|
||||
static int airoha_fe_set_pse_oq_rsv(struct airoha_eth *eth,
|
||||
u32 port, u32 queue, u32 val)
|
||||
{
|
||||
- u32 orig_val, tmp, all_rsv, fq_limit;
|
||||
+ u32 orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue);
|
||||
+ u32 tmp, all_rsv, fq_limit;
|
||||
|
||||
airoha_fe_set_pse_queue_rsv_pages(eth, port, queue, val);
|
||||
|
||||
/* modify all rsv */
|
||||
- orig_val = airoha_fe_get_pse_queue_rsv_pages(eth, port, queue);
|
||||
- tmp = airoha_fe_rr(eth, REG_FE_PSE_BUF_SET);
|
||||
- all_rsv = FIELD_GET(PSE_ALLRSV_MASK, tmp);
|
||||
+ all_rsv = airoha_fe_get_pse_all_rsv(eth);
|
||||
all_rsv += (val - orig_val);
|
||||
airoha_fe_rmw(eth, REG_FE_PSE_BUF_SET, PSE_ALLRSV_MASK,
|
||||
FIELD_PREP(PSE_ALLRSV_MASK, all_rsv));
|
@@ -1,45 +0,0 @@
|
||||
From 3dc6e998d18bfba6e0dc979d3cc68eba98dfeef7 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 4 Oct 2024 15:51:26 +0200
|
||||
Subject: [PATCH] net: airoha: Update tx cpu dma ring idx at the end of xmit
|
||||
loop
|
||||
|
||||
Move the tx cpu dma ring index update out of transmit loop of
|
||||
airoha_dev_xmit routine in order to not start transmitting the packet
|
||||
before it is fully DMA mapped (e.g. fragmented skbs).
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Reported-by: Felix Fietkau <nbd@nbd.name>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241004-airoha-eth-7581-mapping-fix-v1-1-8e4279ab1812@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 9 +++++----
|
||||
1 file changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2480,10 +2480,6 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
e->dma_addr = addr;
|
||||
e->dma_len = len;
|
||||
|
||||
- airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
- TX_RING_CPU_IDX_MASK,
|
||||
- FIELD_PREP(TX_RING_CPU_IDX_MASK, index));
|
||||
-
|
||||
data = skb_frag_address(frag);
|
||||
len = skb_frag_size(frag);
|
||||
}
|
||||
@@ -2492,6 +2488,11 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
q->queued += i;
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
+ if (!netdev_xmit_more())
|
||||
+ airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
+ TX_RING_CPU_IDX_MASK,
|
||||
+ FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
||||
+
|
||||
if (q->ndesc - q->queued < q->free_thr)
|
||||
netif_tx_stop_queue(txq);
|
||||
|
@@ -1,33 +0,0 @@
|
||||
From 2518b119639162251b6cc7195aec394930c1d867 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 9 Oct 2024 00:21:47 +0200
|
||||
Subject: [PATCH] net: airoha: Fix EGRESS_RATE_METER_EN_MASK definition
|
||||
|
||||
Fix typo in EGRESS_RATE_METER_EN_MASK mask definition. This bus in not
|
||||
introducing any user visible problem since, even if we are setting
|
||||
EGRESS_RATE_METER_EN_MASK bit in REG_EGRESS_RATE_METER_CFG register,
|
||||
egress QoS metering is not supported yet since we are missing some other
|
||||
hw configurations (e.g token bucket rate, token bucket size).
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet support
|
||||
for EN7581 SoC")
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Link: https://patch.msgid.link/20241009-airoha-fixes-v2-1-18af63ec19bf@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -554,7 +554,7 @@
|
||||
#define FWD_DSCP_LOW_THR_MASK GENMASK(17, 0)
|
||||
|
||||
#define REG_EGRESS_RATE_METER_CFG 0x100c
|
||||
-#define EGRESS_RATE_METER_EN_MASK BIT(29)
|
||||
+#define EGRESS_RATE_METER_EN_MASK BIT(31)
|
||||
#define EGRESS_RATE_METER_EQ_RATE_EN_MASK BIT(17)
|
||||
#define EGRESS_RATE_METER_WINDOW_SZ_MASK GENMASK(16, 12)
|
||||
#define EGRESS_RATE_METER_TIMESLICE_MASK GENMASK(10, 0)
|
@@ -1,42 +0,0 @@
|
||||
From 1d304174106c93ce05f6088813ad7203b3eb381a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 12 Oct 2024 11:01:11 +0200
|
||||
Subject: [PATCH] net: airoha: Implement BQL support
|
||||
|
||||
Introduce BQL support in the airoha_eth driver reporting to the kernel
|
||||
info about tx hw DMA queues in order to avoid bufferbloat and keep the
|
||||
latency small.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20241012-en7581-bql-v2-1-4deb4efdb60b@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 8 ++++++--
|
||||
1 file changed, 6 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1710,9 +1710,11 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
WRITE_ONCE(desc->msg1, 0);
|
||||
|
||||
if (skb) {
|
||||
+ u16 queue = skb_get_queue_mapping(skb);
|
||||
struct netdev_queue *txq;
|
||||
|
||||
- txq = netdev_get_tx_queue(skb->dev, qid);
|
||||
+ txq = netdev_get_tx_queue(skb->dev, queue);
|
||||
+ netdev_tx_completed_queue(txq, 1, skb->len);
|
||||
if (netif_tx_queue_stopped(txq) &&
|
||||
q->ndesc - q->queued >= q->free_thr)
|
||||
netif_tx_wake_queue(txq);
|
||||
@@ -2488,7 +2490,9 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
q->queued += i;
|
||||
|
||||
skb_tx_timestamp(skb);
|
||||
- if (!netdev_xmit_more())
|
||||
+ netdev_tx_sent_queue(txq, skb->len);
|
||||
+
|
||||
+ if (netif_xmit_stopped(txq) || !netdev_xmit_more())
|
||||
airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid),
|
||||
TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
@@ -1,98 +0,0 @@
|
||||
From 457e74667f452d7f071ad2b2d9313ec62ebc4b02 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 6 Apr 2024 12:43:43 +0200
|
||||
Subject: [PATCH 1/2] clk: en7523: Add en_clk_soc_data data structure
|
||||
|
||||
Introduce en_clk_soc_data data structure in order to define multiple
|
||||
clk_ops for each supported SoC. This is a preliminary patch to
|
||||
introduce EN7581 clock support.
|
||||
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/562a0da8d7874a02a324687c152c87a1549924bd.1712399981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 34 +++++++++++++++++++++-------------
|
||||
1 file changed, 21 insertions(+), 13 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -3,8 +3,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
-#include <linux/of.h>
|
||||
#include <linux/platform_device.h>
|
||||
+#include <linux/property.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
@@ -48,6 +48,10 @@ struct en_clk_gate {
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
+struct en_clk_soc_data {
|
||||
+ const struct clk_ops pcie_ops;
|
||||
+};
|
||||
+
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
static const u32 emi_base[] = { 333000000, 400000000 };
|
||||
static const u32 bus_base[] = { 500000000, 540000000 };
|
||||
@@ -150,11 +154,6 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
-static const struct of_device_id of_match_clk_en7523[] = {
|
||||
- { .compatible = "airoha,en7523-scu", },
|
||||
- { /* sentinel */ }
|
||||
-};
|
||||
-
|
||||
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
{
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
@@ -252,14 +251,10 @@ static void en7523_pci_unprepare(struct
|
||||
static struct clk_hw *en7523_register_pcie_clk(struct device *dev,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
- static const struct clk_ops pcie_gate_ops = {
|
||||
- .is_enabled = en7523_pci_is_enabled,
|
||||
- .prepare = en7523_pci_prepare,
|
||||
- .unprepare = en7523_pci_unprepare,
|
||||
- };
|
||||
+ const struct en_clk_soc_data *soc_data = device_get_match_data(dev);
|
||||
struct clk_init_data init = {
|
||||
.name = "pcie",
|
||||
- .ops = &pcie_gate_ops,
|
||||
+ .ops = &soc_data->pcie_ops,
|
||||
};
|
||||
struct en_clk_gate *cg;
|
||||
|
||||
@@ -269,7 +264,7 @@ static struct clk_hw *en7523_register_pc
|
||||
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
- en7523_pci_unprepare(&cg->hw);
|
||||
+ init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
return NULL;
|
||||
@@ -338,6 +333,19 @@ static int en7523_clk_probe(struct platf
|
||||
return r;
|
||||
}
|
||||
|
||||
+static const struct en_clk_soc_data en7523_data = {
|
||||
+ .pcie_ops = {
|
||||
+ .is_enabled = en7523_pci_is_enabled,
|
||||
+ .prepare = en7523_pci_prepare,
|
||||
+ .unprepare = en7523_pci_unprepare,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id of_match_clk_en7523[] = {
|
||||
+ { .compatible = "airoha,en7523-scu", .data = &en7523_data },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+
|
||||
static struct platform_driver clk_en7523_drv = {
|
||||
.probe = en7523_clk_probe,
|
||||
.driver = {
|
@@ -1,248 +0,0 @@
|
||||
From 66bc47326ce2a319add7e933d9340215711236ac Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 6 Apr 2024 12:43:44 +0200
|
||||
Subject: [PATCH 2/2] clk: en7523: Add EN7581 support
|
||||
|
||||
Introduce EN7581 clock support to clk-en7523 driver.
|
||||
Add hw_init callback to en_clk_soc_data data structure.
|
||||
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/57b6e53ed4d2b2e38abff6a3ea56841bad6be8a9.1712399981.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 157 +++++++++++++++++++++++++++++++++++++--
|
||||
1 file changed, 152 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -10,7 +10,9 @@
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
|
||||
#define REG_PCI_CONTROL_PERSTOUT1 BIT(26)
|
||||
+#define REG_PCI_CONTROL_REFCLK_EN0 BIT(23)
|
||||
#define REG_PCI_CONTROL_REFCLK_EN1 BIT(22)
|
||||
+#define REG_PCI_CONTROL_PERSTOUT2 BIT(16)
|
||||
#define REG_GSW_CLK_DIV_SEL 0x1b4
|
||||
#define REG_EMI_CLK_DIV_SEL 0x1b8
|
||||
#define REG_BUS_CLK_DIV_SEL 0x1bc
|
||||
@@ -18,10 +20,25 @@
|
||||
#define REG_SPI_CLK_FREQ_SEL 0x1c8
|
||||
#define REG_NPU_CLK_DIV_SEL 0x1fc
|
||||
#define REG_CRYPTO_CLKSRC 0x200
|
||||
-#define REG_RESET_CONTROL 0x834
|
||||
+#define REG_RESET_CONTROL2 0x830
|
||||
+#define REG_RESET2_CONTROL_PCIE2 BIT(27)
|
||||
+#define REG_RESET_CONTROL1 0x834
|
||||
#define REG_RESET_CONTROL_PCIEHB BIT(29)
|
||||
#define REG_RESET_CONTROL_PCIE1 BIT(27)
|
||||
#define REG_RESET_CONTROL_PCIE2 BIT(26)
|
||||
+/* EN7581 */
|
||||
+#define REG_PCIE0_MEM 0x00
|
||||
+#define REG_PCIE0_MEM_MASK 0x04
|
||||
+#define REG_PCIE1_MEM 0x08
|
||||
+#define REG_PCIE1_MEM_MASK 0x0c
|
||||
+#define REG_PCIE2_MEM 0x10
|
||||
+#define REG_PCIE2_MEM_MASK 0x14
|
||||
+#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
|
||||
+#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
|
||||
+#define REG_NP_SCU_PCIC 0x88
|
||||
+#define REG_NP_SCU_SSTR 0x9c
|
||||
+#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
+#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
@@ -50,6 +67,8 @@ struct en_clk_gate {
|
||||
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
+ int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
+ void __iomem *np_base);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -216,14 +235,14 @@ static int en7523_pci_prepare(struct clk
|
||||
usleep_range(1000, 2000);
|
||||
|
||||
/* Reset to default */
|
||||
- val = readl(np_base + REG_RESET_CONTROL);
|
||||
+ 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_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
usleep_range(1000, 2000);
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
msleep(100);
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
usleep_range(5000, 10000);
|
||||
|
||||
/* Release device */
|
||||
@@ -264,6 +283,9 @@ static struct clk_hw *en7523_register_pc
|
||||
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
+
|
||||
+ if (init.ops->disable)
|
||||
+ init.ops->disable(&cg->hw);
|
||||
init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
@@ -272,6 +294,111 @@ static struct clk_hw *en7523_register_pc
|
||||
return &cg->hw;
|
||||
}
|
||||
|
||||
+static int en7581_pci_is_enabled(struct clk_hw *hw)
|
||||
+{
|
||||
+ struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
+ u32 val, mask;
|
||||
+
|
||||
+ mask = REG_PCI_CONTROL_REFCLK_EN0 | REG_PCI_CONTROL_REFCLK_EN1;
|
||||
+ val = readl(cg->base + REG_PCI_CONTROL);
|
||||
+ return (val & mask) == mask;
|
||||
+}
|
||||
+
|
||||
+static int en7581_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;
|
||||
+
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
+ REG_RESET_CONTROL_PCIEHB;
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
+ writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL2);
|
||||
+ writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
+ usleep_range(5000, 10000);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+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;
|
||||
+
|
||||
+ 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);
|
||||
+ msleep(250);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void en7581_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, mask;
|
||||
+
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
+ REG_RESET_CONTROL_PCIEHB;
|
||||
+ val = readl(np_base + REG_RESET_CONTROL1);
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
+ mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
|
||||
+ writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
+ val = readl(np_base + REG_RESET_CONTROL2);
|
||||
+ writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
+ msleep(100);
|
||||
+}
|
||||
+
|
||||
+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;
|
||||
+
|
||||
+ 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);
|
||||
+ usleep_range(1000, 2000);
|
||||
+}
|
||||
+
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ void __iomem *base,
|
||||
+ void __iomem *np_base)
|
||||
+{
|
||||
+ void __iomem *pb_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ pb_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(pb_base))
|
||||
+ return PTR_ERR(pb_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ writel(0x20000000, pb_base + REG_PCIE0_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
|
||||
+ writel(0x24000000, pb_base + REG_PCIE1_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
|
||||
+ writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
+ writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
+
|
||||
+ val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
+ writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
|
||||
+ base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
void __iomem *base, void __iomem *np_base)
|
||||
{
|
||||
@@ -304,6 +431,7 @@ static void en7523_register_clocks(struc
|
||||
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;
|
||||
void __iomem *base, *np_base;
|
||||
int r;
|
||||
@@ -316,6 +444,13 @@ static int en7523_clk_probe(struct platf
|
||||
if (IS_ERR(np_base))
|
||||
return PTR_ERR(np_base);
|
||||
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+ if (soc_data->hw_init) {
|
||||
+ r = soc_data->hw_init(pdev, base, np_base);
|
||||
+ if (r)
|
||||
+ return r;
|
||||
+ }
|
||||
+
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
@@ -341,8 +476,20 @@ static const struct en_clk_soc_data en75
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct en_clk_soc_data en7581_data = {
|
||||
+ .pcie_ops = {
|
||||
+ .is_enabled = en7581_pci_is_enabled,
|
||||
+ .prepare = en7581_pci_prepare,
|
||||
+ .enable = en7581_pci_enable,
|
||||
+ .unprepare = en7581_pci_unprepare,
|
||||
+ .disable = en7581_pci_disable,
|
||||
+ },
|
||||
+ .hw_init = en7581_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 },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
@@ -1,270 +0,0 @@
|
||||
From e0d8ea4ed5fa70fd085a54d0b574a044b9407c39 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:23 +0200
|
||||
Subject: [PATCH 1/4] clk: en7523: Add reset-controller support for EN7581 SoC
|
||||
|
||||
Introduce reset API support to EN7581 clock driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/4f735d17e549ea53769bf5a3f50406debb879a44.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 192 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 187 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -5,7 +5,11 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
+#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
+#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
+
|
||||
+#define RST_NR_PER_BANK 32
|
||||
|
||||
#define REG_PCI_CONTROL 0x88
|
||||
#define REG_PCI_CONTROL_PERSTOUT BIT(29)
|
||||
@@ -40,6 +44,9 @@
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
|
||||
+#define REG_RST_CTRL2 0x00
|
||||
+#define REG_RST_CTRL1 0x04
|
||||
+
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
const char *name;
|
||||
@@ -65,8 +72,20 @@ struct en_clk_gate {
|
||||
struct clk_hw hw;
|
||||
};
|
||||
|
||||
+struct en_rst_data {
|
||||
+ const u16 *bank_ofs;
|
||||
+ const u16 *idx_map;
|
||||
+ void __iomem *base;
|
||||
+ struct reset_controller_dev rcdev;
|
||||
+};
|
||||
+
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
+ struct {
|
||||
+ const u16 *bank_ofs;
|
||||
+ const u16 *idx_map;
|
||||
+ u16 idx_map_nr;
|
||||
+ } reset;
|
||||
int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
void __iomem *np_base);
|
||||
};
|
||||
@@ -173,6 +192,69 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
+static const u16 en7581_rst_ofs[] = {
|
||||
+ REG_RST_CTRL2,
|
||||
+ REG_RST_CTRL1,
|
||||
+};
|
||||
+
|
||||
+static const u16 en7581_rst_map[] = {
|
||||
+ /* RST_CTRL2 */
|
||||
+ [EN7581_XPON_PHY_RST] = 0,
|
||||
+ [EN7581_CPU_TIMER2_RST] = 2,
|
||||
+ [EN7581_HSUART_RST] = 3,
|
||||
+ [EN7581_UART4_RST] = 4,
|
||||
+ [EN7581_UART5_RST] = 5,
|
||||
+ [EN7581_I2C2_RST] = 6,
|
||||
+ [EN7581_XSI_MAC_RST] = 7,
|
||||
+ [EN7581_XSI_PHY_RST] = 8,
|
||||
+ [EN7581_NPU_RST] = 9,
|
||||
+ [EN7581_I2S_RST] = 10,
|
||||
+ [EN7581_TRNG_RST] = 11,
|
||||
+ [EN7581_TRNG_MSTART_RST] = 12,
|
||||
+ [EN7581_DUAL_HSI0_RST] = 13,
|
||||
+ [EN7581_DUAL_HSI1_RST] = 14,
|
||||
+ [EN7581_HSI_RST] = 15,
|
||||
+ [EN7581_DUAL_HSI0_MAC_RST] = 16,
|
||||
+ [EN7581_DUAL_HSI1_MAC_RST] = 17,
|
||||
+ [EN7581_HSI_MAC_RST] = 18,
|
||||
+ [EN7581_WDMA_RST] = 19,
|
||||
+ [EN7581_WOE0_RST] = 20,
|
||||
+ [EN7581_WOE1_RST] = 21,
|
||||
+ [EN7581_HSDMA_RST] = 22,
|
||||
+ [EN7581_TDMA_RST] = 24,
|
||||
+ [EN7581_EMMC_RST] = 25,
|
||||
+ [EN7581_SOE_RST] = 26,
|
||||
+ [EN7581_PCIE2_RST] = 27,
|
||||
+ [EN7581_XFP_MAC_RST] = 28,
|
||||
+ [EN7581_USB_HOST_P1_RST] = 29,
|
||||
+ [EN7581_USB_HOST_P1_U3_PHY_RST] = 30,
|
||||
+ /* RST_CTRL1 */
|
||||
+ [EN7581_PCM1_ZSI_ISI_RST] = RST_NR_PER_BANK + 0,
|
||||
+ [EN7581_FE_PDMA_RST] = RST_NR_PER_BANK + 1,
|
||||
+ [EN7581_FE_QDMA_RST] = RST_NR_PER_BANK + 2,
|
||||
+ [EN7581_PCM_SPIWP_RST] = RST_NR_PER_BANK + 4,
|
||||
+ [EN7581_CRYPTO_RST] = RST_NR_PER_BANK + 6,
|
||||
+ [EN7581_TIMER_RST] = RST_NR_PER_BANK + 8,
|
||||
+ [EN7581_PCM1_RST] = RST_NR_PER_BANK + 11,
|
||||
+ [EN7581_UART_RST] = RST_NR_PER_BANK + 12,
|
||||
+ [EN7581_GPIO_RST] = RST_NR_PER_BANK + 13,
|
||||
+ [EN7581_GDMA_RST] = RST_NR_PER_BANK + 14,
|
||||
+ [EN7581_I2C_MASTER_RST] = RST_NR_PER_BANK + 16,
|
||||
+ [EN7581_PCM2_ZSI_ISI_RST] = RST_NR_PER_BANK + 17,
|
||||
+ [EN7581_SFC_RST] = RST_NR_PER_BANK + 18,
|
||||
+ [EN7581_UART2_RST] = RST_NR_PER_BANK + 19,
|
||||
+ [EN7581_GDMP_RST] = RST_NR_PER_BANK + 20,
|
||||
+ [EN7581_FE_RST] = RST_NR_PER_BANK + 21,
|
||||
+ [EN7581_USB_HOST_P0_RST] = RST_NR_PER_BANK + 22,
|
||||
+ [EN7581_GSW_RST] = RST_NR_PER_BANK + 23,
|
||||
+ [EN7581_SFC2_PCM_RST] = RST_NR_PER_BANK + 25,
|
||||
+ [EN7581_PCIE0_RST] = RST_NR_PER_BANK + 26,
|
||||
+ [EN7581_PCIE1_RST] = RST_NR_PER_BANK + 27,
|
||||
+ [EN7581_CPU_TIMER_RST] = RST_NR_PER_BANK + 28,
|
||||
+ [EN7581_PCIE_HB_RST] = RST_NR_PER_BANK + 29,
|
||||
+ [EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
+};
|
||||
+
|
||||
static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
{
|
||||
const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
@@ -375,7 +457,7 @@ static int en7581_clk_hw_init(struct pla
|
||||
void __iomem *pb_base;
|
||||
u32 val;
|
||||
|
||||
- pb_base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ pb_base = devm_platform_ioremap_resource(pdev, 3);
|
||||
if (IS_ERR(pb_base))
|
||||
return PTR_ERR(pb_base);
|
||||
|
||||
@@ -428,6 +510,95 @@ static void en7523_register_clocks(struc
|
||||
clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
}
|
||||
|
||||
+static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
+ 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;
|
||||
+
|
||||
+ val = readl(addr);
|
||||
+ if (assert)
|
||||
+ val |= BIT(id % RST_NR_PER_BANK);
|
||||
+ else
|
||||
+ val &= ~BIT(id % RST_NR_PER_BANK);
|
||||
+ writel(val, addr);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_assert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return en7523_reset_update(rcdev, id, true);
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_deassert(struct reset_controller_dev *rcdev,
|
||||
+ unsigned long id)
|
||||
+{
|
||||
+ return en7523_reset_update(rcdev, id, false);
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_status(struct reset_controller_dev *rcdev,
|
||||
+ 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];
|
||||
+
|
||||
+ return !!(readl(addr) & BIT(id % RST_NR_PER_BANK));
|
||||
+}
|
||||
+
|
||||
+static int en7523_reset_xlate(struct reset_controller_dev *rcdev,
|
||||
+ const struct of_phandle_args *reset_spec)
|
||||
+{
|
||||
+ struct en_rst_data *rst_data = container_of(rcdev, struct en_rst_data, rcdev);
|
||||
+
|
||||
+ if (reset_spec->args[0] >= rcdev->nr_resets)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ return rst_data->idx_map[reset_spec->args[0]];
|
||||
+}
|
||||
+
|
||||
+static const struct reset_control_ops en7523_reset_ops = {
|
||||
+ .assert = en7523_reset_assert,
|
||||
+ .deassert = en7523_reset_deassert,
|
||||
+ .status = en7523_reset_status,
|
||||
+};
|
||||
+
|
||||
+static int en7523_reset_register(struct platform_device *pdev,
|
||||
+ const struct en_clk_soc_data *soc_data)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct en_rst_data *rst_data;
|
||||
+ void __iomem *base;
|
||||
+
|
||||
+ /* no reset lines available */
|
||||
+ if (!soc_data->reset.idx_map_nr)
|
||||
+ return 0;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
|
||||
+ if (!rst_data)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ rst_data->bank_ofs = soc_data->reset.bank_ofs;
|
||||
+ rst_data->idx_map = soc_data->reset.idx_map;
|
||||
+ rst_data->base = base;
|
||||
+
|
||||
+ rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
|
||||
+ rst_data->rcdev.of_xlate = en7523_reset_xlate;
|
||||
+ rst_data->rcdev.ops = &en7523_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 en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
@@ -461,11 +632,17 @@ static int en7523_clk_probe(struct platf
|
||||
|
||||
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
if (r)
|
||||
- dev_err(&pdev->dev,
|
||||
- "could not register clock provider: %s: %d\n",
|
||||
- pdev->name, r);
|
||||
+ return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
|
||||
+ pdev->name);
|
||||
+
|
||||
+ r = en7523_reset_register(pdev, soc_data);
|
||||
+ if (r) {
|
||||
+ of_clk_del_provider(node);
|
||||
+ return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
|
||||
+ pdev->name);
|
||||
+ }
|
||||
|
||||
- return r;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
static const struct en_clk_soc_data en7523_data = {
|
||||
@@ -484,6 +661,11 @@ static const struct en_clk_soc_data en75
|
||||
.unprepare = en7581_pci_unprepare,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
+ .reset = {
|
||||
+ .bank_ofs = en7581_rst_ofs,
|
||||
+ .idx_map = en7581_rst_map,
|
||||
+ .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
|
||||
+ },
|
||||
.hw_init = en7581_clk_hw_init,
|
||||
};
|
||||
|
@@ -1,91 +0,0 @@
|
||||
From db7a4a11e8be375b0a9c159f688e0cea49eacc5d Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:24 +0200
|
||||
Subject: [PATCH 2/4] clk: en7523: Remove pcie prepare/unpreare callbacks for
|
||||
EN7581 SoC
|
||||
|
||||
Get rid of prepare and unpreare callbacks for PCIe clock since they can
|
||||
be modeled as a reset line cosumed by the PCIe driver
|
||||
(pcie-mediatek-gen3)
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/16df149975514d3030499c48fc1c64f090093595.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 41 ++--------------------------------------
|
||||
1 file changed, 2 insertions(+), 39 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -366,9 +366,8 @@ static struct clk_hw *en7523_register_pc
|
||||
cg->base = np_base;
|
||||
cg->hw.init = &init;
|
||||
|
||||
- if (init.ops->disable)
|
||||
- init.ops->disable(&cg->hw);
|
||||
- init.ops->unprepare(&cg->hw);
|
||||
+ if (init.ops->unprepare)
|
||||
+ init.ops->unprepare(&cg->hw);
|
||||
|
||||
if (clk_hw_register(dev, &cg->hw))
|
||||
return NULL;
|
||||
@@ -386,23 +385,6 @@ static int en7581_pci_is_enabled(struct
|
||||
return (val & mask) == mask;
|
||||
}
|
||||
|
||||
-static int en7581_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;
|
||||
-
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
- REG_RESET_CONTROL_PCIEHB;
|
||||
- val = readl(np_base + REG_RESET_CONTROL1);
|
||||
- writel(val & ~mask, np_base + REG_RESET_CONTROL1);
|
||||
- val = readl(np_base + REG_RESET_CONTROL2);
|
||||
- writel(val & ~REG_RESET2_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
- usleep_range(5000, 10000);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int en7581_pci_enable(struct clk_hw *hw)
|
||||
{
|
||||
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
@@ -419,23 +401,6 @@ static int en7581_pci_enable(struct clk_
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void en7581_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, mask;
|
||||
-
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2 |
|
||||
- REG_RESET_CONTROL_PCIEHB;
|
||||
- val = readl(np_base + REG_RESET_CONTROL1);
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
- mask = REG_RESET_CONTROL_PCIE1 | REG_RESET_CONTROL_PCIE2;
|
||||
- writel(val | mask, np_base + REG_RESET_CONTROL1);
|
||||
- val = readl(np_base + REG_RESET_CONTROL2);
|
||||
- writel(val | REG_RESET_CONTROL_PCIE2, np_base + REG_RESET_CONTROL2);
|
||||
- msleep(100);
|
||||
-}
|
||||
-
|
||||
static void en7581_pci_disable(struct clk_hw *hw)
|
||||
{
|
||||
struct en_clk_gate *cg = container_of(hw, struct en_clk_gate, hw);
|
||||
@@ -656,9 +621,7 @@ static const struct en_clk_soc_data en75
|
||||
static const struct en_clk_soc_data en7581_data = {
|
||||
.pcie_ops = {
|
||||
.is_enabled = en7581_pci_is_enabled,
|
||||
- .prepare = en7581_pci_prepare,
|
||||
.enable = en7581_pci_enable,
|
||||
- .unprepare = en7581_pci_unprepare,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
.reset = {
|
@@ -1,65 +0,0 @@
|
||||
From bf288bd25d6232310abb81db417376ce460eb032 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:25 +0200
|
||||
Subject: [PATCH 3/4] clk: en7523: Remove PCIe reset open drain configuration
|
||||
for EN7581
|
||||
|
||||
PCIe reset open drain configuration will be managed by pinctrl driver.
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/43276af5f08a554b4ab2e52e8d437fff5c06a732.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 12 ++----------
|
||||
1 file changed, 2 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -37,8 +37,6 @@
|
||||
#define REG_PCIE1_MEM_MASK 0x0c
|
||||
#define REG_PCIE2_MEM 0x10
|
||||
#define REG_PCIE2_MEM_MASK 0x14
|
||||
-#define REG_PCIE_RESET_OPEN_DRAIN 0x018c
|
||||
-#define REG_PCIE_RESET_OPEN_DRAIN_MASK GENMASK(2, 0)
|
||||
#define REG_NP_SCU_PCIC 0x88
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
@@ -86,8 +84,7 @@ struct en_clk_soc_data {
|
||||
const u16 *idx_map;
|
||||
u16 idx_map_nr;
|
||||
} reset;
|
||||
- int (*hw_init)(struct platform_device *pdev, void __iomem *base,
|
||||
- void __iomem *np_base);
|
||||
+ int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -416,7 +413,6 @@ static void en7581_pci_disable(struct cl
|
||||
}
|
||||
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- void __iomem *base,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
void __iomem *pb_base;
|
||||
@@ -439,10 +435,6 @@ static int en7581_clk_hw_init(struct pla
|
||||
writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
|
||||
- val = readl(base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
- writel(val | REG_PCIE_RESET_OPEN_DRAIN_MASK,
|
||||
- base + REG_PCIE_RESET_OPEN_DRAIN);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -582,7 +574,7 @@ static int en7523_clk_probe(struct platf
|
||||
|
||||
soc_data = device_get_match_data(&pdev->dev);
|
||||
if (soc_data->hw_init) {
|
||||
- r = soc_data->hw_init(pdev, base, np_base);
|
||||
+ r = soc_data->hw_init(pdev, np_base);
|
||||
if (r)
|
||||
return r;
|
||||
}
|
@@ -1,93 +0,0 @@
|
||||
From 7aa291962f4c3b7afb9a12fa60b406b95e5eacb4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 27 Jun 2024 13:04:22 +0200
|
||||
Subject: [PATCH] dt-bindings: clock: airoha: Add reset support to EN7581 clock
|
||||
binding
|
||||
|
||||
Introduce reset capability to EN7581 device-tree clock binding
|
||||
documentation. Add reset register mapping between misc scu and pb scu
|
||||
ones in order to follow the memory order. This change is not
|
||||
introducing any backward compatibility issue since the EN7581 dts is not
|
||||
upstream yet.
|
||||
|
||||
Fixes: 0a382be005cf ("dt-bindings: clock: airoha: add EN7581 binding")
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/28fef3e83062d5d71e7b4be4b47583f851a15bf8.1719485847.git.lorenzo@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
.../bindings/clock/airoha,en7523-scu.yaml | 25 ++++++-
|
||||
.../dt-bindings/reset/airoha,en7581-reset.h | 66 +++++++++++++++++++
|
||||
2 files changed, 90 insertions(+), 1 deletion(-)
|
||||
create mode 100644 include/dt-bindings/reset/airoha,en7581-reset.h
|
||||
|
||||
--- /dev/null
|
||||
+++ b/include/dt-bindings/reset/airoha,en7581-reset.h
|
||||
@@ -0,0 +1,66 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2024 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#ifndef __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_
|
||||
+#define __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_
|
||||
+
|
||||
+/* RST_CTRL2 */
|
||||
+#define EN7581_XPON_PHY_RST 0
|
||||
+#define EN7581_CPU_TIMER2_RST 1
|
||||
+#define EN7581_HSUART_RST 2
|
||||
+#define EN7581_UART4_RST 3
|
||||
+#define EN7581_UART5_RST 4
|
||||
+#define EN7581_I2C2_RST 5
|
||||
+#define EN7581_XSI_MAC_RST 6
|
||||
+#define EN7581_XSI_PHY_RST 7
|
||||
+#define EN7581_NPU_RST 8
|
||||
+#define EN7581_I2S_RST 9
|
||||
+#define EN7581_TRNG_RST 10
|
||||
+#define EN7581_TRNG_MSTART_RST 11
|
||||
+#define EN7581_DUAL_HSI0_RST 12
|
||||
+#define EN7581_DUAL_HSI1_RST 13
|
||||
+#define EN7581_HSI_RST 14
|
||||
+#define EN7581_DUAL_HSI0_MAC_RST 15
|
||||
+#define EN7581_DUAL_HSI1_MAC_RST 16
|
||||
+#define EN7581_HSI_MAC_RST 17
|
||||
+#define EN7581_WDMA_RST 18
|
||||
+#define EN7581_WOE0_RST 19
|
||||
+#define EN7581_WOE1_RST 20
|
||||
+#define EN7581_HSDMA_RST 21
|
||||
+#define EN7581_TDMA_RST 22
|
||||
+#define EN7581_EMMC_RST 23
|
||||
+#define EN7581_SOE_RST 24
|
||||
+#define EN7581_PCIE2_RST 25
|
||||
+#define EN7581_XFP_MAC_RST 26
|
||||
+#define EN7581_USB_HOST_P1_RST 27
|
||||
+#define EN7581_USB_HOST_P1_U3_PHY_RST 28
|
||||
+/* RST_CTRL1 */
|
||||
+#define EN7581_PCM1_ZSI_ISI_RST 29
|
||||
+#define EN7581_FE_PDMA_RST 30
|
||||
+#define EN7581_FE_QDMA_RST 31
|
||||
+#define EN7581_PCM_SPIWP_RST 32
|
||||
+#define EN7581_CRYPTO_RST 33
|
||||
+#define EN7581_TIMER_RST 34
|
||||
+#define EN7581_PCM1_RST 35
|
||||
+#define EN7581_UART_RST 36
|
||||
+#define EN7581_GPIO_RST 37
|
||||
+#define EN7581_GDMA_RST 38
|
||||
+#define EN7581_I2C_MASTER_RST 39
|
||||
+#define EN7581_PCM2_ZSI_ISI_RST 40
|
||||
+#define EN7581_SFC_RST 41
|
||||
+#define EN7581_UART2_RST 42
|
||||
+#define EN7581_GDMP_RST 43
|
||||
+#define EN7581_FE_RST 44
|
||||
+#define EN7581_USB_HOST_P0_RST 45
|
||||
+#define EN7581_GSW_RST 46
|
||||
+#define EN7581_SFC2_PCM_RST 47
|
||||
+#define EN7581_PCIE0_RST 48
|
||||
+#define EN7581_PCIE1_RST 49
|
||||
+#define EN7581_CPU_TIMER_RST 50
|
||||
+#define EN7581_PCIE_HB_RST 51
|
||||
+#define EN7581_XPON_MAC_RST 52
|
||||
+
|
||||
+#endif /* __DT_BINDINGS_RESET_CONTROLLER_AIROHA_EN7581_H_ */
|
@@ -1,100 +0,0 @@
|
||||
From dc869a40d73ee6e9f47d683690ae507e30e56044 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:42 +0200
|
||||
Subject: [PATCH 1/3] PCI: mediatek-gen3: Add mtk_gen3_pcie_pdata data
|
||||
structure
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce mtk_gen3_pcie_pdata data structure in order to define
|
||||
multiple callbacks for each supported SoC.
|
||||
|
||||
This is a preliminary patch to introduce EN7581 PCIe support.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/c193d1a87505d045e2e0ef33317bce17012ee095.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 24 ++++++++++++++++++---
|
||||
1 file changed, 21 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -100,6 +100,16 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
+struct mtk_gen3_pcie;
|
||||
+
|
||||
+/**
|
||||
+ * struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
+ * @power_up: pcie power_up callback
|
||||
+ */
|
||||
+struct mtk_gen3_pcie_pdata {
|
||||
+ int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct mtk_msi_set - MSI information for each set
|
||||
* @base: IO mapped register base
|
||||
@@ -131,6 +141,7 @@ struct mtk_msi_set {
|
||||
* @msi_sets: MSI sets information
|
||||
* @lock: lock protecting IRQ bit map
|
||||
* @msi_irq_in_use: bit map for assigned MSI IRQ
|
||||
+ * @soc: pointer to SoC-dependent operations
|
||||
*/
|
||||
struct mtk_gen3_pcie {
|
||||
struct device *dev;
|
||||
@@ -151,6 +162,8 @@ struct mtk_gen3_pcie {
|
||||
struct mtk_msi_set msi_sets[PCIE_MSI_SET_NUM];
|
||||
struct mutex lock;
|
||||
DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_IRQS_NUM);
|
||||
+
|
||||
+ const struct mtk_gen3_pcie_pdata *soc;
|
||||
};
|
||||
|
||||
/* LTSSM state in PCIE_LTSSM_STATUS_REG bit[28:24] */
|
||||
@@ -904,7 +917,7 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
usleep_range(10, 20);
|
||||
|
||||
/* Don't touch the hardware registers before power up */
|
||||
- err = mtk_pcie_power_up(pcie);
|
||||
+ err = pcie->soc->power_up(pcie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -939,6 +952,7 @@ static int mtk_pcie_probe(struct platfor
|
||||
pcie = pci_host_bridge_priv(host);
|
||||
|
||||
pcie->dev = dev;
|
||||
+ pcie->soc = device_get_match_data(dev);
|
||||
platform_set_drvdata(pdev, pcie);
|
||||
|
||||
err = mtk_pcie_setup(pcie);
|
||||
@@ -1054,7 +1068,7 @@ static int mtk_pcie_resume_noirq(struct
|
||||
struct mtk_gen3_pcie *pcie = dev_get_drvdata(dev);
|
||||
int err;
|
||||
|
||||
- err = mtk_pcie_power_up(pcie);
|
||||
+ err = pcie->soc->power_up(pcie);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1074,8 +1088,12 @@ static const struct dev_pm_ops mtk_pcie_
|
||||
mtk_pcie_resume_noirq)
|
||||
};
|
||||
|
||||
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
||||
+ .power_up = mtk_pcie_power_up,
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
- { .compatible = "mediatek,mt8192-pcie" },
|
||||
+ { .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mtk_pcie_of_match);
|
@@ -1,155 +0,0 @@
|
||||
From ee9eabbe3f0f0c7458d89840add97e54d4e0bccf Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:43 +0200
|
||||
Subject: [PATCH 2/3] PCI: mediatek-gen3: Rely on reset_bulk APIs for PHY reset
|
||||
lines
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Use reset_bulk APIs to manage PHY reset lines.
|
||||
|
||||
This is a preliminary patch in order to add Airoha EN7581 PCIe support.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/3ceb83bc0defbcf868521f8df4b9100e55ec2614.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 45 +++++++++++++++------
|
||||
1 file changed, 33 insertions(+), 12 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -100,14 +100,21 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
+#define MAX_NUM_PHY_RESETS 1
|
||||
+
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
/**
|
||||
* struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
* @power_up: pcie power_up callback
|
||||
+ * @phy_resets: phy reset lines SoC data.
|
||||
*/
|
||||
struct mtk_gen3_pcie_pdata {
|
||||
int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
+ struct {
|
||||
+ const char *id[MAX_NUM_PHY_RESETS];
|
||||
+ int num_resets;
|
||||
+ } phy_resets;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -128,7 +135,7 @@ struct mtk_msi_set {
|
||||
* @base: IO mapped register base
|
||||
* @reg_base: physical register base
|
||||
* @mac_reset: MAC reset control
|
||||
- * @phy_reset: PHY reset control
|
||||
+ * @phy_resets: PHY reset controllers
|
||||
* @phy: PHY controller block
|
||||
* @clks: PCIe clocks
|
||||
* @num_clks: PCIe clocks count for this port
|
||||
@@ -148,7 +155,7 @@ struct mtk_gen3_pcie {
|
||||
void __iomem *base;
|
||||
phys_addr_t reg_base;
|
||||
struct reset_control *mac_reset;
|
||||
- struct reset_control *phy_reset;
|
||||
+ struct reset_control_bulk_data phy_resets[MAX_NUM_PHY_RESETS];
|
||||
struct phy *phy;
|
||||
struct clk_bulk_data *clks;
|
||||
int num_clks;
|
||||
@@ -788,10 +795,10 @@ static int mtk_pcie_setup_irq(struct mtk
|
||||
|
||||
static int mtk_pcie_parse_port(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
+ int i, ret, num_resets = pcie->soc->phy_resets.num_resets;
|
||||
struct device *dev = pcie->dev;
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
struct resource *regs;
|
||||
- int ret;
|
||||
|
||||
regs = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pcie-mac");
|
||||
if (!regs)
|
||||
@@ -804,12 +811,12 @@ static int mtk_pcie_parse_port(struct mt
|
||||
|
||||
pcie->reg_base = regs->start;
|
||||
|
||||
- pcie->phy_reset = devm_reset_control_get_optional_exclusive(dev, "phy");
|
||||
- if (IS_ERR(pcie->phy_reset)) {
|
||||
- ret = PTR_ERR(pcie->phy_reset);
|
||||
- if (ret != -EPROBE_DEFER)
|
||||
- dev_err(dev, "failed to get PHY reset\n");
|
||||
+ for (i = 0; i < num_resets; i++)
|
||||
+ pcie->phy_resets[i].id = pcie->soc->phy_resets.id[i];
|
||||
|
||||
+ ret = devm_reset_control_bulk_get_optional_shared(dev, num_resets, pcie->phy_resets);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to get PHY bulk reset\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -846,7 +853,11 @@ static int mtk_pcie_power_up(struct mtk_
|
||||
int err;
|
||||
|
||||
/* PHY power on and enable pipe clock */
|
||||
- reset_control_deassert(pcie->phy_reset);
|
||||
+ err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to deassert PHYs\n");
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
err = phy_init(pcie->phy);
|
||||
if (err) {
|
||||
@@ -882,7 +893,7 @@ err_clk_init:
|
||||
err_phy_on:
|
||||
phy_exit(pcie->phy);
|
||||
err_phy_init:
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -897,7 +908,7 @@ static void mtk_pcie_power_down(struct m
|
||||
|
||||
phy_power_off(pcie->phy);
|
||||
phy_exit(pcie->phy);
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
}
|
||||
|
||||
static int mtk_pcie_setup(struct mtk_gen3_pcie *pcie)
|
||||
@@ -909,10 +920,16 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
return err;
|
||||
|
||||
/*
|
||||
+ * Deassert the line in order to avoid unbalance in deassert_count
|
||||
+ * counter since the bulk is shared.
|
||||
+ */
|
||||
+ reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ /*
|
||||
* The controller may have been left out of reset by the bootloader
|
||||
* so make sure that we get a clean start by asserting resets here.
|
||||
*/
|
||||
- reset_control_assert(pcie->phy_reset);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+
|
||||
reset_control_assert(pcie->mac_reset);
|
||||
usleep_range(10, 20);
|
||||
|
||||
@@ -1090,6 +1107,10 @@ static const struct dev_pm_ops mtk_pcie_
|
||||
|
||||
static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_mt8192 = {
|
||||
.power_up = mtk_pcie_power_up,
|
||||
+ .phy_resets = {
|
||||
+ .id[0] = "phy",
|
||||
+ .num_resets = 1,
|
||||
+ },
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
@@ -1,199 +0,0 @@
|
||||
From f6ab898356dd70f267c49045a79d28ea5cf5e43e Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 3 Jul 2024 18:12:44 +0200
|
||||
Subject: [PATCH 3/3] PCI: mediatek-gen3: Add Airoha EN7581 support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce support for Airoha EN7581 PCIe controller to mediatek-gen3
|
||||
PCIe controller driver.
|
||||
|
||||
Link: https://lore.kernel.org/linux-pci/aca00bd672ee576ad96d279414fc0835ff31f637.1720022580.git.lorenzo@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Tested-by: Zhengping Zhang <zhengping.zhang@airoha.com>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Acked-by: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
---
|
||||
drivers/pci/controller/Kconfig | 2 +-
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 113 +++++++++++++++++++-
|
||||
2 files changed, 113 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/Kconfig
|
||||
+++ b/drivers/pci/controller/Kconfig
|
||||
@@ -196,7 +196,7 @@ config PCIE_MEDIATEK
|
||||
|
||||
config PCIE_MEDIATEK_GEN3
|
||||
tristate "MediaTek Gen3 PCIe controller"
|
||||
- depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
+ depends on ARCH_AIROHA || ARCH_MEDIATEK || COMPILE_TEST
|
||||
depends on PCI_MSI
|
||||
help
|
||||
Adds support for PCIe Gen3 MAC controller for MediaTek SoCs.
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -6,7 +6,9 @@
|
||||
* Author: Jianjun Wang <jianjun.wang@mediatek.com>
|
||||
*/
|
||||
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/clk.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/irq.h>
|
||||
@@ -15,6 +17,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
+#include <linux/of_device.h>
|
||||
+#include <linux/of_pci.h>
|
||||
#include <linux/pci.h>
|
||||
#include <linux/phy/phy.h>
|
||||
#include <linux/platform_device.h>
|
||||
@@ -29,6 +33,12 @@
|
||||
#define PCI_CLASS(class) (class << 8)
|
||||
#define PCIE_RC_MODE BIT(0)
|
||||
|
||||
+#define PCIE_EQ_PRESET_01_REG 0x100
|
||||
+#define PCIE_VAL_LN0_DOWNSTREAM GENMASK(6, 0)
|
||||
+#define PCIE_VAL_LN0_UPSTREAM GENMASK(14, 8)
|
||||
+#define PCIE_VAL_LN1_DOWNSTREAM GENMASK(22, 16)
|
||||
+#define PCIE_VAL_LN1_UPSTREAM GENMASK(30, 24)
|
||||
+
|
||||
#define PCIE_CFGNUM_REG 0x140
|
||||
#define PCIE_CFG_DEVFN(devfn) ((devfn) & GENMASK(7, 0))
|
||||
#define PCIE_CFG_BUS(bus) (((bus) << 8) & GENMASK(15, 8))
|
||||
@@ -68,6 +78,14 @@
|
||||
#define PCIE_MSI_SET_ENABLE_REG 0x190
|
||||
#define PCIE_MSI_SET_ENABLE GENMASK(PCIE_MSI_SET_NUM - 1, 0)
|
||||
|
||||
+#define PCIE_PIPE4_PIE8_REG 0x338
|
||||
+#define PCIE_K_FINETUNE_MAX GENMASK(5, 0)
|
||||
+#define PCIE_K_FINETUNE_ERR GENMASK(7, 6)
|
||||
+#define PCIE_K_PRESET_TO_USE GENMASK(18, 8)
|
||||
+#define PCIE_K_PHYPARAM_QUERY BIT(19)
|
||||
+#define PCIE_K_QUERY_TIMEOUT BIT(20)
|
||||
+#define PCIE_K_PRESET_TO_USE_16G GENMASK(31, 21)
|
||||
+
|
||||
#define PCIE_MSI_SET_BASE_REG 0xc00
|
||||
#define PCIE_MSI_SET_OFFSET 0x10
|
||||
#define PCIE_MSI_SET_STATUS_OFFSET 0x04
|
||||
@@ -100,7 +118,10 @@
|
||||
#define PCIE_ATR_TLP_TYPE_MEM PCIE_ATR_TLP_TYPE(0)
|
||||
#define PCIE_ATR_TLP_TYPE_IO PCIE_ATR_TLP_TYPE(2)
|
||||
|
||||
-#define MAX_NUM_PHY_RESETS 1
|
||||
+#define MAX_NUM_PHY_RESETS 3
|
||||
+
|
||||
+/* Time in ms needed to complete PCIe reset on EN7581 SoC */
|
||||
+#define PCIE_EN7581_RESET_TIME_MS 100
|
||||
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
@@ -847,6 +868,85 @@ static int mtk_pcie_parse_port(struct mt
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
|
||||
+{
|
||||
+ struct device *dev = pcie->dev;
|
||||
+ int err;
|
||||
+ u32 val;
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for the time needed to complete the bulk assert in
|
||||
+ * mtk_pcie_setup for EN7581 SoC.
|
||||
+ */
|
||||
+ mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+
|
||||
+ err = phy_init(pcie->phy);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to initialize PHY\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ err = phy_power_on(pcie->phy);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to power on PHY\n");
|
||||
+ goto err_phy_on;
|
||||
+ }
|
||||
+
|
||||
+ err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to deassert PHYs\n");
|
||||
+ goto err_phy_deassert;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Wait for the time needed to complete the bulk de-assert above.
|
||||
+ * This time is specific for EN7581 SoC.
|
||||
+ */
|
||||
+ mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+
|
||||
+ pm_runtime_enable(dev);
|
||||
+ pm_runtime_get_sync(dev);
|
||||
+
|
||||
+ err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to prepare clock\n");
|
||||
+ goto err_clk_prepare;
|
||||
+ }
|
||||
+
|
||||
+ val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
|
||||
+ FIELD_PREP(PCIE_VAL_LN1_UPSTREAM, 0x41);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_EQ_PRESET_01_REG);
|
||||
+
|
||||
+ val = PCIE_K_PHYPARAM_QUERY | PCIE_K_QUERY_TIMEOUT |
|
||||
+ FIELD_PREP(PCIE_K_PRESET_TO_USE_16G, 0x80) |
|
||||
+ FIELD_PREP(PCIE_K_PRESET_TO_USE, 0x2) |
|
||||
+ FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
|
||||
+
|
||||
+ err = clk_bulk_enable(pcie->num_clks, pcie->clks);
|
||||
+ if (err) {
|
||||
+ dev_err(dev, "failed to prepare clock\n");
|
||||
+ goto err_clk_enable;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_clk_enable:
|
||||
+ clk_bulk_unprepare(pcie->num_clks, pcie->clks);
|
||||
+err_clk_prepare:
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ pm_runtime_disable(dev);
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
+err_phy_deassert:
|
||||
+ phy_power_off(pcie->phy);
|
||||
+err_phy_on:
|
||||
+ phy_exit(pcie->phy);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
static int mtk_pcie_power_up(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
struct device *dev = pcie->dev;
|
||||
@@ -1113,7 +1213,18 @@ static const struct mtk_gen3_pcie_pdata
|
||||
},
|
||||
};
|
||||
|
||||
+static const struct mtk_gen3_pcie_pdata mtk_pcie_soc_en7581 = {
|
||||
+ .power_up = mtk_pcie_en7581_power_up,
|
||||
+ .phy_resets = {
|
||||
+ .id[0] = "phy-lane0",
|
||||
+ .id[1] = "phy-lane1",
|
||||
+ .id[2] = "phy-lane2",
|
||||
+ .num_resets = 3,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-pcie", .data = &mtk_pcie_soc_en7581 },
|
||||
{ .compatible = "mediatek,mt8192-pcie", .data = &mtk_pcie_soc_mt8192 },
|
||||
{},
|
||||
};
|
File diff suppressed because it is too large
Load Diff
@@ -1,112 +0,0 @@
|
||||
From 2a011c3c12e8de461fb1fdce85fa38d308c4eb8b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 29 Jun 2024 19:51:49 +0200
|
||||
Subject: [PATCH] phy: airoha: Add dtime and Rx AEQ IO registers
|
||||
|
||||
Introduce Tx-Rx detection Time and Rx AEQ training mappings to
|
||||
phy-airoha-pcie driver. This is a preliminary patch to introduce PCIe
|
||||
support to En7581 SoC through the mediatek-gen3 PCIe driver.
|
||||
This change is not introducing any backward compatibility issue since
|
||||
the EN7581 dts is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Link: https://lore.kernel.org/r/edf3b28926177166c65256604d69f2f576cb6fb3.1719682943.git.lorenzo@kernel.org
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie-regs.h | 17 +++++++++++++
|
||||
drivers/phy/phy-airoha-pcie.c | 38 ++++++++++++++++++++++++++++++
|
||||
2 files changed, 55 insertions(+)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie-regs.h
|
||||
+++ b/drivers/phy/phy-airoha-pcie-regs.h
|
||||
@@ -474,4 +474,21 @@
|
||||
#define REG_PCIE_PMA_DIG_RESERVE_27 0x0908
|
||||
#define REG_PCIE_PMA_DIG_RESERVE_30 0x0914
|
||||
|
||||
+/* DTIME */
|
||||
+#define REG_PCIE_PEXTP_DIG_GLB44 0x00
|
||||
+#define PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL GENMASK(7, 0)
|
||||
+#define PCIE_XTP_RXDET_EN_STB_T_SEL GENMASK(15, 8)
|
||||
+#define PCIE_XTP_RXDET_FINISH_STB_T_SEL GENMASK(23, 16)
|
||||
+#define PCIE_XTP_TXPD_TX_DATA_EN_DLY GENMASK(27, 24)
|
||||
+#define PCIE_XTP_TXPD_RXDET_DONE_CDT BIT(28)
|
||||
+#define PCIE_XTP_RXDET_LATCH_STB_T_SEL GENMASK(31, 29)
|
||||
+
|
||||
+/* RX AEQ */
|
||||
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P0 0x0000
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT GENMASK(7, 0)
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_T2RLB_DIG_EN BIT(8)
|
||||
+#define PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT GENMASK(31, 16)
|
||||
+
|
||||
+#define REG_PCIE_PEXTP_DIG_LN_RX30_P1 0x0100
|
||||
+
|
||||
#endif /* _PHY_AIROHA_PCIE_H */
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -31,6 +31,9 @@ enum airoha_pcie_port_gen {
|
||||
* @csr_2l: Analogic lane IO mapped register base address
|
||||
* @pma0: IO mapped register base address of PMA0-PCIe
|
||||
* @pma1: IO mapped register base address of PMA1-PCIe
|
||||
+ * @p0_xr_dtime: IO mapped register base address of port0 Tx-Rx detection time
|
||||
+ * @p1_xr_dtime: IO mapped register base address of port1 Tx-Rx detection time
|
||||
+ * @rx_aeq: IO mapped register base address of Rx AEQ training
|
||||
*/
|
||||
struct airoha_pcie_phy {
|
||||
struct device *dev;
|
||||
@@ -38,6 +41,9 @@ struct airoha_pcie_phy {
|
||||
void __iomem *csr_2l;
|
||||
void __iomem *pma0;
|
||||
void __iomem *pma1;
|
||||
+ void __iomem *p0_xr_dtime;
|
||||
+ void __iomem *p1_xr_dtime;
|
||||
+ void __iomem *rx_aeq;
|
||||
};
|
||||
|
||||
static void airoha_phy_clear_bits(void __iomem *reg, u32 mask)
|
||||
@@ -1101,6 +1107,21 @@ static void airoha_pcie_phy_load_kflow(s
|
||||
static int airoha_pcie_phy_init(struct phy *phy)
|
||||
{
|
||||
struct airoha_pcie_phy *pcie_phy = phy_get_drvdata(phy);
|
||||
+ u32 val;
|
||||
+
|
||||
+ /* Setup Tx-Rx detection time */
|
||||
+ val = FIELD_PREP(PCIE_XTP_RXDET_VCM_OFF_STB_T_SEL, 0x33) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_EN_STB_T_SEL, 0x1) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_FINISH_STB_T_SEL, 0x2) |
|
||||
+ FIELD_PREP(PCIE_XTP_TXPD_TX_DATA_EN_DLY, 0x3) |
|
||||
+ FIELD_PREP(PCIE_XTP_RXDET_LATCH_STB_T_SEL, 0x1);
|
||||
+ writel(val, pcie_phy->p0_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
|
||||
+ writel(val, pcie_phy->p1_xr_dtime + REG_PCIE_PEXTP_DIG_GLB44);
|
||||
+ /* Setup Rx AEQ training time */
|
||||
+ val = FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_L1P2_EXIT_WAIT, 0x32) |
|
||||
+ FIELD_PREP(PCIE_XTP_LN_RX_PDOWN_E0_AEQEN_WAIT, 0x5050);
|
||||
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P0);
|
||||
+ writel(val, pcie_phy->rx_aeq + REG_PCIE_PEXTP_DIG_LN_RX30_P1);
|
||||
|
||||
/* enable load FLL-K flow */
|
||||
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_DIG_RESERVE_14,
|
||||
@@ -1217,6 +1238,23 @@ static int airoha_pcie_phy_probe(struct
|
||||
return dev_err_probe(dev, PTR_ERR(pcie_phy->phy),
|
||||
"Failed to create PCIe phy\n");
|
||||
|
||||
+ pcie_phy->p0_xr_dtime =
|
||||
+ devm_platform_ioremap_resource_byname(pdev, "p0-xr-dtime");
|
||||
+ if (IS_ERR(pcie_phy->p0_xr_dtime))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p0_xr_dtime),
|
||||
+ "Failed to map P0 Tx-Rx dtime base\n");
|
||||
+
|
||||
+ pcie_phy->p1_xr_dtime =
|
||||
+ devm_platform_ioremap_resource_byname(pdev, "p1-xr-dtime");
|
||||
+ if (IS_ERR(pcie_phy->p1_xr_dtime))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->p1_xr_dtime),
|
||||
+ "Failed to map P1 Tx-Rx dtime base\n");
|
||||
+
|
||||
+ pcie_phy->rx_aeq = devm_platform_ioremap_resource_byname(pdev, "rx-aeq");
|
||||
+ if (IS_ERR(pcie_phy->rx_aeq))
|
||||
+ return dev_err_probe(dev, PTR_ERR(pcie_phy->rx_aeq),
|
||||
+ "Failed to map Rx AEQ base\n");
|
||||
+
|
||||
pcie_phy->dev = dev;
|
||||
phy_set_drvdata(pcie_phy->phy, pcie_phy);
|
||||
|
@@ -1,40 +0,0 @@
|
||||
From 7f7315db3d262298ab33d198d3f0b09cabfa7b6b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 6 Aug 2024 17:55:48 +0200
|
||||
Subject: [PATCH] phy: airoha: adjust initialization delay in
|
||||
airoha_pcie_phy_init()
|
||||
|
||||
Align phy-pcie initialization delay to the vendor sdk in
|
||||
airoha_pcie_phy_init routine and allow the hw to complete required
|
||||
configuration before proceeding
|
||||
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/8af6f27857619f1e0dd227f08b8584ae8fb22fb2.1722959625.git.lorenzo@kernel.org
|
||||
Signed-off-by: Vinod Koul <vkoul@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -18,6 +18,9 @@
|
||||
#define LEQ_LEN_CTRL_MAX_VAL 7
|
||||
#define FREQ_LOCK_MAX_ATTEMPT 10
|
||||
|
||||
+/* PCIe-PHY initialization time in ms needed by the hw to complete */
|
||||
+#define PHY_HW_INIT_TIME_MS 30
|
||||
+
|
||||
enum airoha_pcie_port_gen {
|
||||
PCIE_PORT_GEN1 = 1,
|
||||
PCIE_PORT_GEN2,
|
||||
@@ -1181,7 +1184,8 @@ static int airoha_pcie_phy_init(struct p
|
||||
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_SS_DA_XPON_PWDB0,
|
||||
PCIE_DA_XPON_CDR_PR_PWDB);
|
||||
|
||||
- usleep_range(100, 200);
|
||||
+ /* Wait for the PCIe PHY to complete initialization before returning */
|
||||
+ msleep(PHY_HW_INIT_TIME_MS);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,26 +0,0 @@
|
||||
From ca9afde0563a80200eab856a53d7eab28c8fdd90 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:52 +0200
|
||||
Subject: [PATCH 1/4] phy: airoha: Fix REG_CSR_2L_PLL_CMN_RESERVE0 config in
|
||||
airoha_pcie_phy_init_clk_out()
|
||||
|
||||
Fix typo configuring REG_CSR_2L_PLL_CMN_RESERVE0 register in
|
||||
airoha_pcie_phy_init_clk_out routine.
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -459,7 +459,7 @@ static void airoha_pcie_phy_init_clk_out
|
||||
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_CLKTX1_OFFSET,
|
||||
CSR_2L_PXP_CLKTX1_SR);
|
||||
airoha_phy_csr_2l_update_field(pcie_phy, REG_CSR_2L_PLL_CMN_RESERVE0,
|
||||
- CSR_2L_PXP_PLL_RESERVE_MASK, 0xdd);
|
||||
+ CSR_2L_PXP_PLL_RESERVE_MASK, 0xd0d);
|
||||
}
|
||||
|
||||
static void airoha_pcie_phy_init_csr_2l(struct airoha_pcie_phy *pcie_phy)
|
@@ -1,29 +0,0 @@
|
||||
From 2c2313c84ad7c0e5e39fbd98559d40f6b9ec1f83 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:53 +0200
|
||||
Subject: [PATCH 2/4] phy: airoha: Fix REG_PCIE_PMA_TX_RESET config in
|
||||
airoha_pcie_phy_init_csr_2l()
|
||||
|
||||
Fix typos configuring REG_PCIE_PMA_TX_RESET register in
|
||||
airoha_pcie_phy_init_csr_2l routine for lane0 and lane1
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -471,9 +471,9 @@ static void airoha_pcie_phy_init_csr_2l(
|
||||
PCIE_SW_XFI_RXPCS_RST | PCIE_SW_REF_RST |
|
||||
PCIE_SW_RX_RST);
|
||||
airoha_phy_pma0_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
|
||||
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
|
||||
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
|
||||
airoha_phy_pma1_set_bits(pcie_phy, REG_PCIE_PMA_TX_RESET,
|
||||
- PCIE_TX_TOP_RST | REG_PCIE_PMA_TX_RESET);
|
||||
+ PCIE_TX_TOP_RST | PCIE_TX_CAL_RST);
|
||||
}
|
||||
|
||||
static void airoha_pcie_phy_init_rx(struct airoha_pcie_phy *pcie_phy)
|
@@ -1,26 +0,0 @@
|
||||
From 6e0c349a8a59959c3d3571b5f6776bc2d2ca62bc Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:54 +0200
|
||||
Subject: [PATCH 3/4] phy: airoha: Fix REG_CSR_2L_JCPLL_SDM_HREN config in
|
||||
airoha_pcie_phy_init_ssc_jcpll()
|
||||
|
||||
Fix typo configuring REG_CSR_2L_JCPLL_SDM_HREN register in
|
||||
airoha_pcie_phy_init_ssc_jcpll routine.
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie.c | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie.c
|
||||
+++ b/drivers/phy/phy-airoha-pcie.c
|
||||
@@ -802,7 +802,7 @@ static void airoha_pcie_phy_init_ssc_jcp
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_IFM,
|
||||
CSR_2L_PXP_JCPLL_SDM_IFM);
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SDM_HREN,
|
||||
- REG_CSR_2L_JCPLL_SDM_HREN);
|
||||
+ CSR_2L_PXP_JCPLL_SDM_HREN);
|
||||
airoha_phy_csr_2l_clear_bits(pcie_phy, REG_CSR_2L_JCPLL_RST_DLY,
|
||||
CSR_2L_PXP_JCPLL_SDM_DI_EN);
|
||||
airoha_phy_csr_2l_set_bits(pcie_phy, REG_CSR_2L_JCPLL_SSC,
|
@@ -1,32 +0,0 @@
|
||||
From bc1bb265f504ea19ce611a1aec1a40dec409cd15 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 18 Sep 2024 15:32:55 +0200
|
||||
Subject: [PATCH 4/4] phy: airoha: Fix REG_CSR_2L_RX{0,1}_REV0 definitions
|
||||
|
||||
Fix the following register definitions for REG_CSR_2L_RX{0,1}_REV0
|
||||
registers:
|
||||
- CSR_2L_PXP_VOS_PNINV
|
||||
- CSR_2L_PXP_FE_GAIN_NORMAL_MODE
|
||||
- CSR_2L_PXP_FE_GAIN_TRAIN_MODE
|
||||
|
||||
Fixes: d7d2818b9383 ("phy: airoha: Add PCIe PHY driver for EN7581 SoC.")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
---
|
||||
drivers/phy/phy-airoha-pcie-regs.h | 6 +++---
|
||||
1 file changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
--- a/drivers/phy/phy-airoha-pcie-regs.h
|
||||
+++ b/drivers/phy/phy-airoha-pcie-regs.h
|
||||
@@ -197,9 +197,9 @@
|
||||
#define CSR_2L_PXP_TX1_MULTLANE_EN BIT(0)
|
||||
|
||||
#define REG_CSR_2L_RX0_REV0 0x00fc
|
||||
-#define CSR_2L_PXP_VOS_PNINV GENMASK(3, 2)
|
||||
-#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(6, 4)
|
||||
-#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(10, 8)
|
||||
+#define CSR_2L_PXP_VOS_PNINV GENMASK(19, 18)
|
||||
+#define CSR_2L_PXP_FE_GAIN_NORMAL_MODE GENMASK(22, 20)
|
||||
+#define CSR_2L_PXP_FE_GAIN_TRAIN_MODE GENMASK(26, 24)
|
||||
|
||||
#define REG_CSR_2L_RX0_PHYCK_DIV 0x0100
|
||||
#define CSR_2L_PXP_RX0_PHYCK_SEL GENMASK(9, 8)
|
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
From 2e6bbfe7b0c0607001b784082c2685b134174fac Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 13 Sep 2024 23:07:13 +0200
|
||||
Subject: [PATCH 1/2] spi: airoha: fix dirmap_{read,write} operations
|
||||
|
||||
SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end of
|
||||
dirmap_read operation even if it is already set.
|
||||
In the same way, SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the
|
||||
end of dirmap_write operation even if it is already set.
|
||||
For this reason use regmap_write_bits() instead of regmap_set_bits().
|
||||
This patch fixes mtd_pagetest kernel module test.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240913-airoha-spi-fixes-v1-1-de2e74ed4664@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 18 ++++++++++++++----
|
||||
1 file changed, 14 insertions(+), 4 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -739,8 +739,13 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
- SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
+ /*
|
||||
+ * SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
|
||||
+ * of dirmap_read operation even if it is already set.
|
||||
+ */
|
||||
+ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
+ SPI_NFI_READ_FROM_CACHE_DONE,
|
||||
+ SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -870,8 +875,13 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
- SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
+ /*
|
||||
+ * SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
|
||||
+ * of dirmap_write operation even if it is already set.
|
||||
+ */
|
||||
+ err = regmap_write_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_STA_CTL1,
|
||||
+ SPI_NFI_LOAD_TO_CACHE_DONE,
|
||||
+ SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
if (err)
|
||||
return err;
|
||||
|
@@ -1,39 +0,0 @@
|
||||
From 0e58637eb968c636725dcd6c7055249b4e5326fb Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 13 Sep 2024 23:07:14 +0200
|
||||
Subject: [PATCH 2/2] spi: airoha: fix airoha_snand_{write,read}_data data_len
|
||||
estimation
|
||||
|
||||
Fix data length written and read in airoha_snand_write_data and
|
||||
airoha_snand_read_data routines respectively if it is bigger than
|
||||
SPI_MAX_TRANSFER_SIZE.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240913-airoha-spi-fixes-v1-2-de2e74ed4664@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -405,7 +405,7 @@ static int airoha_snand_write_data(struc
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
- data_len = min(len, SPI_MAX_TRANSFER_SIZE);
|
||||
+ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, cmd, data_len);
|
||||
if (err)
|
||||
return err;
|
||||
@@ -427,7 +427,7 @@ static int airoha_snand_read_data(struct
|
||||
for (i = 0; i < len; i += data_len) {
|
||||
int err;
|
||||
|
||||
- data_len = min(len, SPI_MAX_TRANSFER_SIZE);
|
||||
+ data_len = min(len - i, SPI_MAX_TRANSFER_SIZE);
|
||||
err = airoha_snand_set_fifo_op(as_ctrl, 0xc, data_len);
|
||||
if (err)
|
||||
return err;
|
@@ -1,116 +0,0 @@
|
||||
From fffca269e4f31c3633c6d810833ba1b184407915 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 19 Sep 2024 18:57:16 +0200
|
||||
Subject: [PATCH] spi: airoha: remove read cache in airoha_snand_dirmap_read()
|
||||
|
||||
Current upstream driver reports errors running mtd_oobtest kernel module
|
||||
test:
|
||||
|
||||
root@OpenWrt:/# insmod mtd_test.ko
|
||||
root@OpenWrt:/# insmod mtd_oobtest.ko dev=5
|
||||
[ 7023.730584] =================================================
|
||||
[ 7023.736399] mtd_oobtest: MTD device: 5
|
||||
[ 7023.740160] mtd_oobtest: MTD device size 3670016, eraseblock size 131072, page size 2048, count of eraseblocks 28, pages per eraseblock 64, OOB size 128
|
||||
[ 7023.753837] mtd_test: scanning for bad eraseblocks
|
||||
[ 7023.758636] mtd_test: scanned 28 eraseblocks, 0 are bad
|
||||
[ 7023.763861] mtd_oobtest: test 1 of 5
|
||||
[ 7024.042076] mtd_oobtest: writing OOBs of whole device
|
||||
[ 7024.682069] mtd_oobtest: written up to eraseblock 0
|
||||
[ 7041.962077] mtd_oobtest: written 28 eraseblocks
|
||||
[ 7041.966626] mtd_oobtest: verifying all eraseblocks
|
||||
[ 7041.972276] mtd_oobtest: error @addr[0x0:0x0] 0xff -> 0xe diff 0xf1
|
||||
[ 7041.978550] mtd_oobtest: error @addr[0x0:0x1] 0xff -> 0x10 diff 0xef
|
||||
[ 7041.984932] mtd_oobtest: error @addr[0x0:0x2] 0xff -> 0x82 diff 0x7d
|
||||
[ 7041.991293] mtd_oobtest: error @addr[0x0:0x3] 0xff -> 0x10 diff 0xef
|
||||
[ 7041.997659] mtd_oobtest: error @addr[0x0:0x4] 0xff -> 0x0 diff 0xff
|
||||
[ 7042.003942] mtd_oobtest: error @addr[0x0:0x5] 0xff -> 0x8a diff 0x75
|
||||
[ 7042.010294] mtd_oobtest: error @addr[0x0:0x6] 0xff -> 0x20 diff 0xdf
|
||||
[ 7042.016659] mtd_oobtest: error @addr[0x0:0x7] 0xff -> 0x1 diff 0xfe
|
||||
[ 7042.022935] mtd_oobtest: error @addr[0x0:0x8] 0xff -> 0x2e diff 0xd1
|
||||
[ 7042.029295] mtd_oobtest: error @addr[0x0:0x9] 0xff -> 0x40 diff 0xbf
|
||||
[ 7042.035661] mtd_oobtest: error @addr[0x0:0xa] 0xff -> 0x0 diff 0xff
|
||||
[ 7042.041935] mtd_oobtest: error @addr[0x0:0xb] 0xff -> 0x89 diff 0x76
|
||||
[ 7042.048300] mtd_oobtest: error @addr[0x0:0xc] 0xff -> 0x82 diff 0x7d
|
||||
[ 7042.054662] mtd_oobtest: error @addr[0x0:0xd] 0xff -> 0x15 diff 0xea
|
||||
[ 7042.061014] mtd_oobtest: error @addr[0x0:0xe] 0xff -> 0x90 diff 0x6f
|
||||
[ 7042.067380] mtd_oobtest: error @addr[0x0:0xf] 0xff -> 0x0 diff 0xff
|
||||
....
|
||||
[ 7432.421369] mtd_oobtest: error @addr[0x237800:0x36] 0xff -> 0x5f diff 0xa0
|
||||
[ 7432.428242] mtd_oobtest: error @addr[0x237800:0x37] 0xff -> 0x21 diff 0xde
|
||||
[ 7432.435118] mtd_oobtest: error: verify failed at 0x237800
|
||||
[ 7432.440510] mtd_oobtest: error: too many errors
|
||||
[ 7432.445053] mtd_oobtest: error -1 occurred
|
||||
|
||||
The above errors are due to the buggy logic in the 'read cache' available
|
||||
in airoha_snand_dirmap_read() routine since there are some corner cases
|
||||
where we are missing data updates. Since we do not get any read/write speed
|
||||
improvement using the cache (according to the mtd_speedtest kernel
|
||||
module test), in order to fix the mtd_oobtest test, remove the 'read cache'
|
||||
in airoha_snand_dirmap_read routine. Now the driver is passing all the
|
||||
tests available in mtd_test suite.
|
||||
|
||||
Fixes: a403997c1201 ("spi: airoha: add SPI-NAND Flash controller driver")
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240919-airoha-spi-fixes-v2-1-cb0f0ed9920a@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 21 ---------------------
|
||||
1 file changed, 21 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -211,9 +211,6 @@ struct airoha_snand_dev {
|
||||
|
||||
u8 *txrx_buf;
|
||||
dma_addr_t dma_addr;
|
||||
-
|
||||
- u64 cur_page_num;
|
||||
- bool data_need_update;
|
||||
};
|
||||
|
||||
struct airoha_snand_ctrl {
|
||||
@@ -644,11 +641,6 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
- if (!as_dev->data_need_update)
|
||||
- return len;
|
||||
-
|
||||
- as_dev->data_need_update = false;
|
||||
-
|
||||
switch (op->cmd.opcode) {
|
||||
case SPI_NAND_OP_READ_FROM_CACHE_DUAL:
|
||||
rd_mode = 1;
|
||||
@@ -895,23 +887,11 @@ static ssize_t airoha_snand_dirmap_write
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
const struct spi_mem_op *op)
|
||||
{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(mem->spi);
|
||||
u8 data[8], cmd, opcode = op->cmd.opcode;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
int i, err;
|
||||
|
||||
as_ctrl = spi_controller_get_devdata(mem->spi->controller);
|
||||
- if (opcode == SPI_NAND_OP_PROGRAM_EXECUTE &&
|
||||
- op->addr.val == as_dev->cur_page_num) {
|
||||
- as_dev->data_need_update = true;
|
||||
- } else if (opcode == SPI_NAND_OP_PAGE_READ) {
|
||||
- if (!as_dev->data_need_update &&
|
||||
- op->addr.val == as_dev->cur_page_num)
|
||||
- return 0;
|
||||
-
|
||||
- as_dev->data_need_update = true;
|
||||
- as_dev->cur_page_num = op->addr.val;
|
||||
- }
|
||||
|
||||
/* switch to manual mode */
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
@@ -996,7 +976,6 @@ static int airoha_snand_setup(struct spi
|
||||
if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
|
||||
return -ENOMEM;
|
||||
|
||||
- as_dev->data_need_update = true;
|
||||
spi_set_ctldata(spi, as_dev);
|
||||
|
||||
return 0;
|
@@ -1,435 +0,0 @@
|
||||
From 7a4b3ebf1d60349587fee21872536e7bd6a4cf39 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sun, 22 Sep 2024 19:38:30 +0200
|
||||
Subject: [PATCH] spi: airoha: do not keep {tx,rx} dma buffer always mapped
|
||||
|
||||
DMA map txrx_buf on demand in airoha_snand_dirmap_read and
|
||||
airoha_snand_dirmap_write routines and do not keep it always mapped.
|
||||
This patch is not fixing any bug or introducing any functional change
|
||||
to the driver, it just simplifies the code and improve code readability
|
||||
without introducing any performance degradation according to the results
|
||||
obtained from the mtd_speedtest kernel module test.
|
||||
|
||||
root@OpenWrt:# insmod mtd_test.ko
|
||||
root@OpenWrt:# insmod mtd_speedtest.ko dev=5
|
||||
[ 49.849869] =================================================
|
||||
[ 49.855659] mtd_speedtest: MTD device: 5
|
||||
[ 49.859583] mtd_speedtest: MTD device size 8388608, eraseblock size 131072, page size 2048, count of eraseblocks 64, pages per eraseblock 64, OOB size 128
|
||||
[ 49.874622] mtd_test: scanning for bad eraseblocks
|
||||
[ 49.879433] mtd_test: scanned 64 eraseblocks, 0 are bad
|
||||
[ 50.106372] mtd_speedtest: testing eraseblock write speed
|
||||
[ 53.083380] mtd_speedtest: eraseblock write speed is 2756 KiB/s
|
||||
[ 53.089322] mtd_speedtest: testing eraseblock read speed
|
||||
[ 54.143360] mtd_speedtest: eraseblock read speed is 7811 KiB/s
|
||||
[ 54.370365] mtd_speedtest: testing page write speed
|
||||
[ 57.349480] mtd_speedtest: page write speed is 2754 KiB/s
|
||||
[ 57.354895] mtd_speedtest: testing page read speed
|
||||
[ 58.410431] mtd_speedtest: page read speed is 7796 KiB/s
|
||||
[ 58.636805] mtd_speedtest: testing 2 page write speed
|
||||
[ 61.612427] mtd_speedtest: 2 page write speed is 2757 KiB/s
|
||||
[ 61.618021] mtd_speedtest: testing 2 page read speed
|
||||
[ 62.672653] mtd_speedtest: 2 page read speed is 7804 KiB/s
|
||||
[ 62.678159] mtd_speedtest: Testing erase speed
|
||||
[ 62.903617] mtd_speedtest: erase speed is 37063 KiB/s
|
||||
[ 62.908678] mtd_speedtest: Testing 2x multi-block erase speed
|
||||
[ 63.134083] mtd_speedtest: 2x multi-block erase speed is 37292 KiB/s
|
||||
[ 63.140442] mtd_speedtest: Testing 4x multi-block erase speed
|
||||
[ 63.364262] mtd_speedtest: 4x multi-block erase speed is 37566 KiB/s
|
||||
[ 63.370632] mtd_speedtest: Testing 8x multi-block erase speed
|
||||
[ 63.595740] mtd_speedtest: 8x multi-block erase speed is 37344 KiB/s
|
||||
[ 63.602089] mtd_speedtest: Testing 16x multi-block erase speed
|
||||
[ 63.827426] mtd_speedtest: 16x multi-block erase speed is 37320 KiB/s
|
||||
[ 63.833860] mtd_speedtest: Testing 32x multi-block erase speed
|
||||
[ 64.059389] mtd_speedtest: 32x multi-block erase speed is 37288 KiB/s
|
||||
[ 64.065833] mtd_speedtest: Testing 64x multi-block erase speed
|
||||
[ 64.290609] mtd_speedtest: 64x multi-block erase speed is 37415 KiB/s
|
||||
[ 64.297063] mtd_speedtest: finished
|
||||
[ 64.300555] =================================================
|
||||
|
||||
Tested-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20240922-airoha-spi-fixes-v3-1-f958802b3d68@kernel.org
|
||||
Signed-off-by: Mark Brown <broonie@kernel.org>
|
||||
---
|
||||
drivers/spi/spi-airoha-snfi.c | 154 ++++++++++++++++------------------
|
||||
1 file changed, 71 insertions(+), 83 deletions(-)
|
||||
|
||||
--- a/drivers/spi/spi-airoha-snfi.c
|
||||
+++ b/drivers/spi/spi-airoha-snfi.c
|
||||
@@ -206,13 +206,6 @@ enum airoha_snand_cs {
|
||||
SPI_CHIP_SEL_LOW,
|
||||
};
|
||||
|
||||
-struct airoha_snand_dev {
|
||||
- size_t buf_len;
|
||||
-
|
||||
- u8 *txrx_buf;
|
||||
- dma_addr_t dma_addr;
|
||||
-};
|
||||
-
|
||||
struct airoha_snand_ctrl {
|
||||
struct device *dev;
|
||||
struct regmap *regmap_ctrl;
|
||||
@@ -617,9 +610,9 @@ static bool airoha_snand_supports_op(str
|
||||
|
||||
static int airoha_snand_dirmap_create(struct spi_mem_dirmap_desc *desc)
|
||||
{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(desc->mem->spi);
|
||||
+ u8 *txrx_buf = spi_get_ctldata(desc->mem->spi);
|
||||
|
||||
- if (!as_dev->txrx_buf)
|
||||
+ if (!txrx_buf)
|
||||
return -EINVAL;
|
||||
|
||||
if (desc->info.offset + desc->info.length > U32_MAX)
|
||||
@@ -634,10 +627,11 @@ static int airoha_snand_dirmap_create(st
|
||||
static ssize_t airoha_snand_dirmap_read(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, void *buf)
|
||||
{
|
||||
- struct spi_device *spi = desc->mem->spi;
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
+ struct spi_device *spi = desc->mem->spi;
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
+ u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
+ dma_addr_t dma_addr;
|
||||
u32 val, rd_mode;
|
||||
int err;
|
||||
|
||||
@@ -662,14 +656,17 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_FROM_DEVICE);
|
||||
+ err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
/* set dma addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
- as_dev->dma_addr);
|
||||
+ dma_addr);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set cust sec size */
|
||||
val = as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num;
|
||||
@@ -678,58 +675,58 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
REG_SPI_NFI_SNF_MISC_CTL2,
|
||||
SPI_NFI_READ_DATA_BYTE_NUM, val);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set read command */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL2,
|
||||
op->cmd.opcode);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set read mode */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, rd_mode));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set read addr */
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_RD_CTL3, 0x0);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* set nfi read */
|
||||
err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_OPMODE,
|
||||
FIELD_PREP(SPI_NFI_OPMODE, 6));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_READ_MODE | SPI_NFI_DMA_MODE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x0);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* trigger dma start read */
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_RD_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
|
||||
REG_SPI_NFI_SNF_STA_CTL1, val,
|
||||
(val & SPI_NFI_READ_FROM_CACHE_DONE),
|
||||
0, 1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/*
|
||||
* SPI_NFI_READ_FROM_CACHE_DONE bit must be written at the end
|
||||
@@ -739,35 +736,41 @@ static ssize_t airoha_snand_dirmap_read(
|
||||
SPI_NFI_READ_FROM_CACHE_DONE,
|
||||
SPI_NFI_READ_FROM_CACHE_DONE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
|
||||
val, (val & SPI_NFI_AHB_DONE), 0,
|
||||
1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/* DMA read need delay for data ready from controller to DRAM */
|
||||
udelay(1);
|
||||
|
||||
- dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_FROM_DEVICE);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- memcpy(buf, as_dev->txrx_buf + offs, len);
|
||||
+ memcpy(buf, txrx_buf + offs, len);
|
||||
|
||||
return len;
|
||||
+
|
||||
+error_dma_unmap:
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_FROM_DEVICE);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static ssize_t airoha_snand_dirmap_write(struct spi_mem_dirmap_desc *desc,
|
||||
u64 offs, size_t len, const void *buf)
|
||||
{
|
||||
- struct spi_device *spi = desc->mem->spi;
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
struct spi_mem_op *op = &desc->info.op_tmpl;
|
||||
+ struct spi_device *spi = desc->mem->spi;
|
||||
+ u8 *txrx_buf = spi_get_ctldata(spi);
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
+ dma_addr_t dma_addr;
|
||||
u32 wr_mode, val;
|
||||
int err;
|
||||
|
||||
@@ -776,19 +779,20 @@ static ssize_t airoha_snand_dirmap_write
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
- dma_sync_single_for_cpu(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
- memcpy(as_dev->txrx_buf + offs, buf, len);
|
||||
- dma_sync_single_for_device(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
+ memcpy(txrx_buf + offs, buf, len);
|
||||
+ dma_addr = dma_map_single(as_ctrl->dev, txrx_buf, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
+ err = dma_mapping_error(as_ctrl->dev, dma_addr);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_DMA);
|
||||
if (err < 0)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = airoha_snand_nfi_config(as_ctrl);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
if (op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_QUAD ||
|
||||
op->cmd.opcode == SPI_NAND_OP_PROGRAM_LOAD_RAMDON_QUAD)
|
||||
@@ -797,9 +801,9 @@ static ssize_t airoha_snand_dirmap_write
|
||||
wr_mode = 0;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_STRADDR,
|
||||
- as_dev->dma_addr);
|
||||
+ dma_addr);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
val = FIELD_PREP(SPI_NFI_PROG_LOAD_BYTE_NUM,
|
||||
as_ctrl->nfi_cfg.sec_size * as_ctrl->nfi_cfg.sec_num);
|
||||
@@ -807,65 +811,65 @@ static ssize_t airoha_snand_dirmap_write
|
||||
REG_SPI_NFI_SNF_MISC_CTL2,
|
||||
SPI_NFI_PROG_LOAD_BYTE_NUM, val);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL1,
|
||||
FIELD_PREP(SPI_NFI_PG_LOAD_CMD,
|
||||
op->cmd.opcode));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_SNF_MISC_CTL,
|
||||
FIELD_PREP(SPI_NFI_DATA_READ_WR_MODE, wr_mode));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_PG_CTL2, 0x0);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_READ_MODE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_update_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_OPMODE,
|
||||
FIELD_PREP(SPI_NFI_OPMODE, 3));
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CNFG,
|
||||
SPI_NFI_DMA_MODE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_write(as_ctrl->regmap_nfi, REG_SPI_NFI_CMD, 0x80);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_clear_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_set_bits(as_ctrl->regmap_nfi, REG_SPI_NFI_CON,
|
||||
SPI_NFI_WR_TRIG);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi, REG_SPI_NFI_INTR,
|
||||
val, (val & SPI_NFI_AHB_DONE), 0,
|
||||
1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
err = regmap_read_poll_timeout(as_ctrl->regmap_nfi,
|
||||
REG_SPI_NFI_SNF_STA_CTL1, val,
|
||||
(val & SPI_NFI_LOAD_TO_CACHE_DONE),
|
||||
0, 1 * USEC_PER_SEC);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
/*
|
||||
* SPI_NFI_LOAD_TO_CACHE_DONE bit must be written at the end
|
||||
@@ -875,13 +879,20 @@ static ssize_t airoha_snand_dirmap_write
|
||||
SPI_NFI_LOAD_TO_CACHE_DONE,
|
||||
SPI_NFI_LOAD_TO_CACHE_DONE);
|
||||
if (err)
|
||||
- return err;
|
||||
+ goto error_dma_unmap;
|
||||
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
err = airoha_snand_set_mode(as_ctrl, SPI_MODE_MANUAL);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return len;
|
||||
+
|
||||
+error_dma_unmap:
|
||||
+ dma_unmap_single(as_ctrl->dev, dma_addr, SPI_NAND_CACHE_SIZE,
|
||||
+ DMA_TO_DEVICE);
|
||||
+ return err;
|
||||
}
|
||||
|
||||
static int airoha_snand_exec_op(struct spi_mem *mem,
|
||||
@@ -956,42 +967,20 @@ static const struct spi_controller_mem_o
|
||||
static int airoha_snand_setup(struct spi_device *spi)
|
||||
{
|
||||
struct airoha_snand_ctrl *as_ctrl;
|
||||
- struct airoha_snand_dev *as_dev;
|
||||
-
|
||||
- as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
-
|
||||
- as_dev = devm_kzalloc(as_ctrl->dev, sizeof(*as_dev), GFP_KERNEL);
|
||||
- if (!as_dev)
|
||||
- return -ENOMEM;
|
||||
+ u8 *txrx_buf;
|
||||
|
||||
/* prepare device buffer */
|
||||
- as_dev->buf_len = SPI_NAND_CACHE_SIZE;
|
||||
- as_dev->txrx_buf = devm_kzalloc(as_ctrl->dev, as_dev->buf_len,
|
||||
- GFP_KERNEL);
|
||||
- if (!as_dev->txrx_buf)
|
||||
- return -ENOMEM;
|
||||
-
|
||||
- as_dev->dma_addr = dma_map_single(as_ctrl->dev, as_dev->txrx_buf,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
- if (dma_mapping_error(as_ctrl->dev, as_dev->dma_addr))
|
||||
+ as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
+ txrx_buf = devm_kzalloc(as_ctrl->dev, SPI_NAND_CACHE_SIZE,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!txrx_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
- spi_set_ctldata(spi, as_dev);
|
||||
+ spi_set_ctldata(spi, txrx_buf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static void airoha_snand_cleanup(struct spi_device *spi)
|
||||
-{
|
||||
- struct airoha_snand_dev *as_dev = spi_get_ctldata(spi);
|
||||
- struct airoha_snand_ctrl *as_ctrl;
|
||||
-
|
||||
- as_ctrl = spi_controller_get_devdata(spi->controller);
|
||||
- dma_unmap_single(as_ctrl->dev, as_dev->dma_addr,
|
||||
- as_dev->buf_len, DMA_BIDIRECTIONAL);
|
||||
- spi_set_ctldata(spi, NULL);
|
||||
-}
|
||||
-
|
||||
static int airoha_snand_nfi_setup(struct airoha_snand_ctrl *as_ctrl)
|
||||
{
|
||||
u32 val, sec_size, sec_num;
|
||||
@@ -1093,7 +1082,6 @@ static int airoha_snand_probe(struct pla
|
||||
ctrl->bits_per_word_mask = SPI_BPW_MASK(8);
|
||||
ctrl->mode_bits = SPI_RX_DUAL;
|
||||
ctrl->setup = airoha_snand_setup;
|
||||
- ctrl->cleanup = airoha_snand_cleanup;
|
||||
device_set_node(&ctrl->dev, dev_fwnode(dev));
|
||||
|
||||
err = airoha_snand_nfi_setup(as_ctrl);
|
@@ -1,184 +0,0 @@
|
||||
From 2b0229f67932e4b9e2f458bf286903582bd30740 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 1 Aug 2024 09:35:12 +0200
|
||||
Subject: [PATCH] net: dsa: mt7530: Add EN7581 support
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Introduce support for the DSA built-in switch available on the EN7581
|
||||
development board. EN7581 support is similar to MT7988 one except
|
||||
it requires to set MT7530_FORCE_MODE bit in MT753X_PMCR_P register
|
||||
for on cpu port.
|
||||
|
||||
Tested-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Arınç ÜNAL <arinc.unal@arinc9.com>
|
||||
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
|
||||
Signed-off-by: David S. Miller <davem@davemloft.net>
|
||||
---
|
||||
drivers/net/dsa/mt7530-mmio.c | 1 +
|
||||
drivers/net/dsa/mt7530.c | 49 ++++++++++++++++++++++++++++++-----
|
||||
drivers/net/dsa/mt7530.h | 20 ++++++++++----
|
||||
3 files changed, 59 insertions(+), 11 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,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
|
||||
@@ -1152,7 +1152,8 @@ mt753x_cpu_port_enable(struct dsa_switch
|
||||
* the MT7988 SoC. Trapped frames will be forwarded to the CPU port that
|
||||
* is affine to the inbound user port.
|
||||
*/
|
||||
- if (priv->id == ID_MT7531 || priv->id == ID_MT7988)
|
||||
+ if (priv->id == ID_MT7531 || priv->id == ID_MT7988 ||
|
||||
+ priv->id == ID_EN7581)
|
||||
mt7530_set(priv, MT7531_CFC, MT7531_CPU_PMAP(BIT(port)));
|
||||
|
||||
/* CPU port gets connected to all user ports of
|
||||
@@ -2207,7 +2208,7 @@ mt7530_setup_irq(struct mt7530_priv *pri
|
||||
return priv->irq ? : -EINVAL;
|
||||
}
|
||||
|
||||
- if (priv->id == ID_MT7988)
|
||||
+ if (priv->id == ID_MT7988 || priv->id == ID_EN7581)
|
||||
priv->irq_domain = irq_domain_add_linear(np, MT7530_NUM_PHYS,
|
||||
&mt7988_irq_domain_ops,
|
||||
priv);
|
||||
@@ -2438,8 +2439,10 @@ mt7530_setup(struct dsa_switch *ds)
|
||||
/* Clear link settings and enable force mode to force link down
|
||||
* on all ports until they're enabled later.
|
||||
*/
|
||||
- mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
|
||||
- MT7530_FORCE_MODE, MT7530_FORCE_MODE);
|
||||
+ mt7530_rmw(priv, MT753X_PMCR_P(i),
|
||||
+ PMCR_LINK_SETTINGS_MASK |
|
||||
+ MT753X_FORCE_MODE(priv->id),
|
||||
+ MT753X_FORCE_MODE(priv->id));
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
|
||||
@@ -2553,8 +2556,10 @@ mt7531_setup_common(struct dsa_switch *d
|
||||
/* Clear link settings and enable force mode to force link down
|
||||
* on all ports until they're enabled later.
|
||||
*/
|
||||
- mt7530_rmw(priv, MT753X_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
|
||||
- MT7531_FORCE_MODE_MASK, MT7531_FORCE_MODE_MASK);
|
||||
+ mt7530_rmw(priv, MT753X_PMCR_P(i),
|
||||
+ PMCR_LINK_SETTINGS_MASK |
|
||||
+ MT753X_FORCE_MODE(priv->id),
|
||||
+ MT753X_FORCE_MODE(priv->id));
|
||||
|
||||
/* Disable forwarding by default on all ports */
|
||||
mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
|
||||
@@ -2779,6 +2784,28 @@ static void mt7988_mac_port_get_caps(str
|
||||
}
|
||||
}
|
||||
|
||||
+static void en7581_mac_port_get_caps(struct dsa_switch *ds, int port,
|
||||
+ struct phylink_config *config)
|
||||
+{
|
||||
+ switch (port) {
|
||||
+ /* Ports which are connected to switch PHYs. There is no MII pinout. */
|
||||
+ case 0 ... 4:
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ config->supported_interfaces);
|
||||
+
|
||||
+ config->mac_capabilities |= MAC_10 | MAC_100 | MAC_1000FD;
|
||||
+ break;
|
||||
+
|
||||
+ /* Port 6 is connected to SoC's XGMII MAC. There is no MII pinout. */
|
||||
+ case 6:
|
||||
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
|
||||
+ config->supported_interfaces);
|
||||
+
|
||||
+ config->mac_capabilities |= MAC_10000FD;
|
||||
+ break;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void
|
||||
mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
|
||||
phy_interface_t interface)
|
||||
@@ -3216,6 +3243,16 @@ const struct mt753x_info mt753x_table[]
|
||||
.phy_write_c45 = mt7531_ind_c45_phy_write,
|
||||
.mac_port_get_caps = mt7988_mac_port_get_caps,
|
||||
},
|
||||
+ [ID_EN7581] = {
|
||||
+ .id = ID_EN7581,
|
||||
+ .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,
|
||||
+ },
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(mt753x_table);
|
||||
|
||||
--- a/drivers/net/dsa/mt7530.h
|
||||
+++ b/drivers/net/dsa/mt7530.h
|
||||
@@ -19,6 +19,7 @@ enum mt753x_id {
|
||||
ID_MT7621 = 1,
|
||||
ID_MT7531 = 2,
|
||||
ID_MT7988 = 3,
|
||||
+ ID_EN7581 = 4,
|
||||
};
|
||||
|
||||
#define NUM_TRGMII_CTRL 5
|
||||
@@ -64,25 +65,30 @@ enum mt753x_id {
|
||||
#define MT7531_CPU_PMAP(x) FIELD_PREP(MT7531_CPU_PMAP_MASK, x)
|
||||
|
||||
#define MT753X_MIRROR_REG(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_CFC : MT753X_MFC)
|
||||
|
||||
#define MT753X_MIRROR_EN(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_EN : MT7530_MIRROR_EN)
|
||||
|
||||
#define MT753X_MIRROR_PORT_MASK(id) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_MASK : \
|
||||
MT7530_MIRROR_PORT_MASK)
|
||||
|
||||
#define MT753X_MIRROR_PORT_GET(id, val) ((id == ID_MT7531 || \
|
||||
- id == ID_MT7988) ? \
|
||||
+ id == ID_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
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_MT7988 || \
|
||||
+ id == ID_EN7581) ? \
|
||||
MT7531_MIRROR_PORT_SET(val) : \
|
||||
MT7530_MIRROR_PORT_SET(val))
|
||||
|
||||
@@ -355,6 +361,10 @@ enum mt7530_vlan_port_acc_frm {
|
||||
MT7531_FORCE_MODE_TX_FC | \
|
||||
MT7531_FORCE_MODE_EEE100 | \
|
||||
MT7531_FORCE_MODE_EEE1G)
|
||||
+#define MT753X_FORCE_MODE(id) ((id == ID_MT7531 || \
|
||||
+ id == ID_MT7988) ? \
|
||||
+ MT7531_FORCE_MODE_MASK : \
|
||||
+ MT7530_FORCE_MODE)
|
||||
#define PMCR_LINK_SETTINGS_MASK (PMCR_MAC_TX_EN | PMCR_MAC_RX_EN | \
|
||||
PMCR_FORCE_EEE1G | \
|
||||
PMCR_FORCE_EEE100 | \
|
@@ -1,306 +0,0 @@
|
||||
From 5c5db81bff81a0fcd9ad998543d4241cbfe4742f Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 17 Oct 2024 14:44:38 +0200
|
||||
Subject: [PATCH 2/2] hwrng: airoha - add support for Airoha EN7581 TRNG
|
||||
|
||||
Add support for Airoha TRNG. The Airoha SoC provide a True RNG module
|
||||
that can output 4 bytes of raw data at times.
|
||||
|
||||
The module makes use of various noise source to provide True Random
|
||||
Number Generation.
|
||||
|
||||
On probe the module is reset to operate Health Test and verify correct
|
||||
execution of it.
|
||||
|
||||
The module can also provide DRBG function but the execution mode is
|
||||
mutually exclusive, running as TRNG doesn't permit to also run it as
|
||||
DRBG.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Martin Kaiser <martin@kaiser.cx>
|
||||
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
|
||||
---
|
||||
drivers/char/hw_random/Kconfig | 13 ++
|
||||
drivers/char/hw_random/Makefile | 1 +
|
||||
drivers/char/hw_random/airoha-trng.c | 243 +++++++++++++++++++++++++++
|
||||
3 files changed, 257 insertions(+)
|
||||
create mode 100644 drivers/char/hw_random/airoha-trng.c
|
||||
|
||||
--- a/drivers/char/hw_random/Kconfig
|
||||
+++ b/drivers/char/hw_random/Kconfig
|
||||
@@ -62,6 +62,19 @@ config HW_RANDOM_AMD
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
+config HW_RANDOM_AIROHA
|
||||
+ tristate "Airoha True HW Random Number Generator support"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ default HW_RANDOM
|
||||
+ help
|
||||
+ This driver provides kernel-side support for the True Random Number
|
||||
+ Generator hardware found on Airoha SoC.
|
||||
+
|
||||
+ To compile this driver as a module, choose M here: the
|
||||
+ module will be called airoha-rng.
|
||||
+
|
||||
+ If unsure, say Y.
|
||||
+
|
||||
config HW_RANDOM_ATMEL
|
||||
tristate "Atmel Random Number Generator support"
|
||||
depends on (ARCH_AT91 || COMPILE_TEST)
|
||||
--- a/drivers/char/hw_random/Makefile
|
||||
+++ b/drivers/char/hw_random/Makefile
|
||||
@@ -8,6 +8,7 @@ rng-core-y := core.o
|
||||
obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
|
||||
+obj-$(CONFIG_HW_RANDOM_AIROHA) += airoha-trng.o
|
||||
obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_BA431) += ba431-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/char/hw_random/airoha-trng.c
|
||||
@@ -0,0 +1,243 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/* Copyright (C) 2024 Christian Marangi */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/mod_devicetable.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/hw_random.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#define TRNG_IP_RDY 0x800
|
||||
+#define CNT_TRANS GENMASK(15, 8)
|
||||
+#define SAMPLE_RDY BIT(0)
|
||||
+#define TRNG_NS_SEK_AND_DAT_EN 0x804
|
||||
+#define RNG_EN BIT(31) /* referenced as ring_en */
|
||||
+#define RAW_DATA_EN BIT(16)
|
||||
+#define TRNG_HEALTH_TEST_SW_RST 0x808
|
||||
+#define SW_RST BIT(0) /* Active High */
|
||||
+#define TRNG_INTR_EN 0x818
|
||||
+#define INTR_MASK BIT(16)
|
||||
+#define CONTINUOUS_HEALTH_INITR_EN BIT(2)
|
||||
+#define SW_STARTUP_INITR_EN BIT(1)
|
||||
+#define RST_STARTUP_INITR_EN BIT(0)
|
||||
+/* Notice that Health Test are done only out of Reset and with RNG_EN */
|
||||
+#define TRNG_HEALTH_TEST_STATUS 0x824
|
||||
+#define CONTINUOUS_HEALTH_AP_TEST_FAIL BIT(23)
|
||||
+#define CONTINUOUS_HEALTH_RC_TEST_FAIL BIT(22)
|
||||
+#define SW_STARTUP_TEST_DONE BIT(21)
|
||||
+#define SW_STARTUP_AP_TEST_FAIL BIT(20)
|
||||
+#define SW_STARTUP_RC_TEST_FAIL BIT(19)
|
||||
+#define RST_STARTUP_TEST_DONE BIT(18)
|
||||
+#define RST_STARTUP_AP_TEST_FAIL BIT(17)
|
||||
+#define RST_STARTUP_RC_TEST_FAIL BIT(16)
|
||||
+#define RAW_DATA_VALID BIT(7)
|
||||
+
|
||||
+#define TRNG_RAW_DATA_OUT 0x828
|
||||
+
|
||||
+#define TRNG_CNT_TRANS_VALID 0x80
|
||||
+#define BUSY_LOOP_SLEEP 10
|
||||
+#define BUSY_LOOP_TIMEOUT (BUSY_LOOP_SLEEP * 10000)
|
||||
+
|
||||
+struct airoha_trng {
|
||||
+ void __iomem *base;
|
||||
+ struct hwrng rng;
|
||||
+ struct device *dev;
|
||||
+
|
||||
+ struct completion rng_op_done;
|
||||
+};
|
||||
+
|
||||
+static int airoha_trng_irq_mask(struct airoha_trng *trng)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_INTR_EN);
|
||||
+ val |= INTR_MASK;
|
||||
+ writel(val, trng->base + TRNG_INTR_EN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_irq_unmask(struct airoha_trng *trng)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_INTR_EN);
|
||||
+ val &= ~INTR_MASK;
|
||||
+ writel(val, trng->base + TRNG_INTR_EN);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_init(struct hwrng *rng)
|
||||
+{
|
||||
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
|
||||
+ int ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+ val |= RNG_EN;
|
||||
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+
|
||||
+ /* Set out of SW Reset */
|
||||
+ airoha_trng_irq_unmask(trng);
|
||||
+ writel(0, trng->base + TRNG_HEALTH_TEST_SW_RST);
|
||||
+
|
||||
+ ret = wait_for_completion_timeout(&trng->rng_op_done, BUSY_LOOP_TIMEOUT);
|
||||
+ if (ret <= 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for Health Check\n");
|
||||
+ airoha_trng_irq_mask(trng);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Check if Health Test Failed */
|
||||
+ val = readl(trng->base + TRNG_HEALTH_TEST_STATUS);
|
||||
+ if (val & (RST_STARTUP_AP_TEST_FAIL | RST_STARTUP_RC_TEST_FAIL)) {
|
||||
+ dev_err(trng->dev, "Health Check fail: %s test fail\n",
|
||||
+ val & RST_STARTUP_AP_TEST_FAIL ? "AP" : "RC");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* Check if IP is ready */
|
||||
+ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val,
|
||||
+ val & SAMPLE_RDY, 10, 1000);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for IP ready");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ /* CNT_TRANS must be 0x80 for IP to be considered ready */
|
||||
+ ret = readl_poll_timeout(trng->base + TRNG_IP_RDY, val,
|
||||
+ FIELD_GET(CNT_TRANS, val) == TRNG_CNT_TRANS_VALID,
|
||||
+ 10, 1000);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for IP ready");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_trng_cleanup(struct hwrng *rng)
|
||||
+{
|
||||
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+ val &= ~RNG_EN;
|
||||
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+
|
||||
+ /* Put it in SW Reset */
|
||||
+ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST);
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
|
||||
+{
|
||||
+ struct airoha_trng *trng = container_of(rng, struct airoha_trng, rng);
|
||||
+ u32 *data = buf;
|
||||
+ u32 status;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = readl_poll_timeout(trng->base + TRNG_HEALTH_TEST_STATUS, status,
|
||||
+ status & RAW_DATA_VALID, 10, 1000);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(trng->dev, "Timeout waiting for TRNG RAW Data valid\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ *data = readl(trng->base + TRNG_RAW_DATA_OUT);
|
||||
+
|
||||
+ return 4;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t airoha_trng_irq(int irq, void *priv)
|
||||
+{
|
||||
+ struct airoha_trng *trng = (struct airoha_trng *)priv;
|
||||
+
|
||||
+ airoha_trng_irq_mask(trng);
|
||||
+ /* Just complete the task, we will read the value later */
|
||||
+ complete(&trng->rng_op_done);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int airoha_trng_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct airoha_trng *trng;
|
||||
+ int irq, ret;
|
||||
+ u32 val;
|
||||
+
|
||||
+ trng = devm_kzalloc(dev, sizeof(*trng), GFP_KERNEL);
|
||||
+ if (!trng)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ trng->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(trng->base))
|
||||
+ return PTR_ERR(trng->base);
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ airoha_trng_irq_mask(trng);
|
||||
+ ret = devm_request_irq(&pdev->dev, irq, airoha_trng_irq, 0,
|
||||
+ pdev->name, (void *)trng);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "Can't get interrupt working.\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ init_completion(&trng->rng_op_done);
|
||||
+
|
||||
+ /* Enable interrupt for SW reset Health Check */
|
||||
+ val = readl(trng->base + TRNG_INTR_EN);
|
||||
+ val |= RST_STARTUP_INITR_EN;
|
||||
+ writel(val, trng->base + TRNG_INTR_EN);
|
||||
+
|
||||
+ /* Set output to raw data */
|
||||
+ val = readl(trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+ val |= RAW_DATA_EN;
|
||||
+ writel(val, trng->base + TRNG_NS_SEK_AND_DAT_EN);
|
||||
+
|
||||
+ /* Put it in SW Reset */
|
||||
+ writel(SW_RST, trng->base + TRNG_HEALTH_TEST_SW_RST);
|
||||
+
|
||||
+ trng->dev = dev;
|
||||
+ trng->rng.name = pdev->name;
|
||||
+ trng->rng.init = airoha_trng_init;
|
||||
+ trng->rng.cleanup = airoha_trng_cleanup;
|
||||
+ trng->rng.read = airoha_trng_read;
|
||||
+
|
||||
+ ret = devm_hwrng_register(dev, &trng->rng);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to register rng device: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_trng_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-trng", },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_trng_of_match);
|
||||
+
|
||||
+static struct platform_driver airoha_trng_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "airoha-trng",
|
||||
+ .of_match_table = airoha_trng_of_match,
|
||||
+ },
|
||||
+ .probe = airoha_trng_probe,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(airoha_trng_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Airoha True Random Number Generator driver");
|
@@ -1,92 +0,0 @@
|
||||
From 3affa310de523d63e52ea8e2efb3c476df29e414 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 29 Oct 2024 13:17:09 +0100
|
||||
Subject: [PATCH 1/2] net: airoha: Read completion queue data in
|
||||
airoha_qdma_tx_napi_poll()
|
||||
|
||||
In order to avoid any possible race, read completion queue head and
|
||||
pending entry in airoha_qdma_tx_napi_poll routine instead of doing it in
|
||||
airoha_irq_handler. Remove unused airoha_tx_irq_queue unused fields.
|
||||
This is a preliminary patch to add Qdisc offload for airoha_eth driver.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20241029-airoha-en7581-tx-napi-work-v1-1-96ad1686b946@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 31 +++++++++-------------
|
||||
1 file changed, 13 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -752,11 +752,9 @@ struct airoha_tx_irq_queue {
|
||||
struct airoha_qdma *qdma;
|
||||
|
||||
struct napi_struct napi;
|
||||
- u32 *q;
|
||||
|
||||
int size;
|
||||
- int queued;
|
||||
- u16 head;
|
||||
+ u32 *q;
|
||||
};
|
||||
|
||||
struct airoha_hw_stats {
|
||||
@@ -1656,25 +1654,31 @@ static int airoha_qdma_init_rx(struct ai
|
||||
static int airoha_qdma_tx_napi_poll(struct napi_struct *napi, int budget)
|
||||
{
|
||||
struct airoha_tx_irq_queue *irq_q;
|
||||
+ int id, done = 0, irq_queued;
|
||||
struct airoha_qdma *qdma;
|
||||
struct airoha_eth *eth;
|
||||
- int id, done = 0;
|
||||
+ u32 status, head;
|
||||
|
||||
irq_q = container_of(napi, struct airoha_tx_irq_queue, napi);
|
||||
qdma = irq_q->qdma;
|
||||
id = irq_q - &qdma->q_tx_irq[0];
|
||||
eth = qdma->eth;
|
||||
|
||||
- while (irq_q->queued > 0 && done < budget) {
|
||||
- u32 qid, last, val = irq_q->q[irq_q->head];
|
||||
+ status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(id));
|
||||
+ head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||||
+ head = head % irq_q->size;
|
||||
+ irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
+
|
||||
+ while (irq_queued > 0 && done < budget) {
|
||||
+ u32 qid, last, val = irq_q->q[head];
|
||||
struct airoha_queue *q;
|
||||
|
||||
if (val == 0xff)
|
||||
break;
|
||||
|
||||
- irq_q->q[irq_q->head] = 0xff; /* mark as done */
|
||||
- irq_q->head = (irq_q->head + 1) % irq_q->size;
|
||||
- irq_q->queued--;
|
||||
+ irq_q->q[head] = 0xff; /* mark as done */
|
||||
+ head = (head + 1) % irq_q->size;
|
||||
+ irq_queued--;
|
||||
done++;
|
||||
|
||||
last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||||
@@ -2026,20 +2030,11 @@ static irqreturn_t airoha_irq_handler(in
|
||||
|
||||
if (intr[0] & INT_TX_MASK) {
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
- struct airoha_tx_irq_queue *irq_q = &qdma->q_tx_irq[i];
|
||||
- u32 status, head;
|
||||
-
|
||||
if (!(intr[0] & TX_DONE_INT_MASK(i)))
|
||||
continue;
|
||||
|
||||
airoha_qdma_irq_disable(qdma, QDMA_INT_REG_IDX0,
|
||||
TX_DONE_INT_MASK(i));
|
||||
-
|
||||
- status = airoha_qdma_rr(qdma, REG_IRQ_STATUS(i));
|
||||
- head = FIELD_GET(IRQ_HEAD_IDX_MASK, status);
|
||||
- irq_q->head = head % irq_q->size;
|
||||
- irq_q->queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
-
|
||||
napi_schedule(&qdma->q_tx_irq[i].napi);
|
||||
}
|
||||
}
|
@@ -1,130 +0,0 @@
|
||||
From 0c729f53b8c33b9e5eadc2d5e673759e3510501e Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 29 Oct 2024 13:17:10 +0100
|
||||
Subject: [PATCH 2/2] net: airoha: Simplify Tx napi logic
|
||||
|
||||
Simplify Tx napi logic relying just on the packet index provided by
|
||||
completion queue indicating the completed packet that can be removed
|
||||
from the Tx DMA ring.
|
||||
This is a preliminary patch to add Qdisc offload for airoha_eth driver.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20241029-airoha-en7581-tx-napi-work-v1-2-96ad1686b946@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 73 ++++++++++++----------
|
||||
1 file changed, 41 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1670,8 +1670,12 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
irq_queued = FIELD_GET(IRQ_ENTRY_LEN_MASK, status);
|
||||
|
||||
while (irq_queued > 0 && done < budget) {
|
||||
- u32 qid, last, val = irq_q->q[head];
|
||||
+ u32 qid, val = irq_q->q[head];
|
||||
+ struct airoha_qdma_desc *desc;
|
||||
+ struct airoha_queue_entry *e;
|
||||
struct airoha_queue *q;
|
||||
+ u32 index, desc_ctrl;
|
||||
+ struct sk_buff *skb;
|
||||
|
||||
if (val == 0xff)
|
||||
break;
|
||||
@@ -1681,9 +1685,7 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
irq_queued--;
|
||||
done++;
|
||||
|
||||
- last = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||||
qid = FIELD_GET(IRQ_RING_IDX_MASK, val);
|
||||
-
|
||||
if (qid >= ARRAY_SIZE(qdma->q_tx))
|
||||
continue;
|
||||
|
||||
@@ -1691,46 +1693,53 @@ static int airoha_qdma_tx_napi_poll(stru
|
||||
if (!q->ndesc)
|
||||
continue;
|
||||
|
||||
+ index = FIELD_GET(IRQ_DESC_IDX_MASK, val);
|
||||
+ if (index >= q->ndesc)
|
||||
+ continue;
|
||||
+
|
||||
spin_lock_bh(&q->lock);
|
||||
|
||||
- while (q->queued > 0) {
|
||||
- struct airoha_qdma_desc *desc = &q->desc[q->tail];
|
||||
- struct airoha_queue_entry *e = &q->entry[q->tail];
|
||||
- u32 desc_ctrl = le32_to_cpu(desc->ctrl);
|
||||
- struct sk_buff *skb = e->skb;
|
||||
- u16 index = q->tail;
|
||||
-
|
||||
- if (!(desc_ctrl & QDMA_DESC_DONE_MASK) &&
|
||||
- !(desc_ctrl & QDMA_DESC_DROP_MASK))
|
||||
- break;
|
||||
+ if (!q->queued)
|
||||
+ goto unlock;
|
||||
|
||||
- q->tail = (q->tail + 1) % q->ndesc;
|
||||
- q->queued--;
|
||||
+ desc = &q->desc[index];
|
||||
+ desc_ctrl = le32_to_cpu(desc->ctrl);
|
||||
|
||||
- dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
|
||||
- DMA_TO_DEVICE);
|
||||
-
|
||||
- WRITE_ONCE(desc->msg0, 0);
|
||||
- WRITE_ONCE(desc->msg1, 0);
|
||||
+ if (!(desc_ctrl & QDMA_DESC_DONE_MASK) &&
|
||||
+ !(desc_ctrl & QDMA_DESC_DROP_MASK))
|
||||
+ goto unlock;
|
||||
+
|
||||
+ e = &q->entry[index];
|
||||
+ skb = e->skb;
|
||||
+
|
||||
+ dma_unmap_single(eth->dev, e->dma_addr, e->dma_len,
|
||||
+ DMA_TO_DEVICE);
|
||||
+ memset(e, 0, sizeof(*e));
|
||||
+ WRITE_ONCE(desc->msg0, 0);
|
||||
+ WRITE_ONCE(desc->msg1, 0);
|
||||
+ q->queued--;
|
||||
+
|
||||
+ /* completion ring can report out-of-order indexes if hw QoS
|
||||
+ * is enabled and packets with different priority are queued
|
||||
+ * to same DMA ring. Take into account possible out-of-order
|
||||
+ * reports incrementing DMA ring tail pointer
|
||||
+ */
|
||||
+ while (q->tail != q->head && !q->entry[q->tail].dma_addr)
|
||||
+ q->tail = (q->tail + 1) % q->ndesc;
|
||||
|
||||
- if (skb) {
|
||||
- u16 queue = skb_get_queue_mapping(skb);
|
||||
- struct netdev_queue *txq;
|
||||
-
|
||||
- txq = netdev_get_tx_queue(skb->dev, queue);
|
||||
- netdev_tx_completed_queue(txq, 1, skb->len);
|
||||
- if (netif_tx_queue_stopped(txq) &&
|
||||
- q->ndesc - q->queued >= q->free_thr)
|
||||
- netif_tx_wake_queue(txq);
|
||||
-
|
||||
- dev_kfree_skb_any(skb);
|
||||
- e->skb = NULL;
|
||||
- }
|
||||
+ if (skb) {
|
||||
+ u16 queue = skb_get_queue_mapping(skb);
|
||||
+ struct netdev_queue *txq;
|
||||
+
|
||||
+ txq = netdev_get_tx_queue(skb->dev, queue);
|
||||
+ netdev_tx_completed_queue(txq, 1, skb->len);
|
||||
+ if (netif_tx_queue_stopped(txq) &&
|
||||
+ q->ndesc - q->queued >= q->free_thr)
|
||||
+ netif_tx_wake_queue(txq);
|
||||
|
||||
- if (index == last)
|
||||
- break;
|
||||
+ dev_kfree_skb_any(skb);
|
||||
}
|
||||
-
|
||||
+unlock:
|
||||
spin_unlock_bh(&q->lock);
|
||||
}
|
||||
|
@@ -1,267 +0,0 @@
|
||||
From 3cf67f3769b8227ca75ca7102180a2e270ee01aa Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Fri, 11 Oct 2024 12:43:53 +0200
|
||||
Subject: [PATCH] watchdog: Add support for Airoha EN7851 watchdog
|
||||
|
||||
Add support for Airoha EN7851 watchdog. This is a very basic watchdog
|
||||
with no pretimeout support, max timeout is 28 seconds and it ticks based
|
||||
on half the SoC BUS clock.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
|
||||
Link: https://lore.kernel.org/r/20241011104411.28659-2-ansuelsmth@gmail.com
|
||||
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
|
||||
Signed-off-by: Wim Van Sebroeck <wim@linux-watchdog.org>
|
||||
---
|
||||
drivers/watchdog/Kconfig | 8 ++
|
||||
drivers/watchdog/Makefile | 1 +
|
||||
drivers/watchdog/airoha_wdt.c | 216 ++++++++++++++++++++++++++++++++++
|
||||
3 files changed, 225 insertions(+)
|
||||
create mode 100644 drivers/watchdog/airoha_wdt.c
|
||||
|
||||
--- a/drivers/watchdog/Kconfig
|
||||
+++ b/drivers/watchdog/Kconfig
|
||||
@@ -372,6 +372,14 @@ config SL28CPLD_WATCHDOG
|
||||
|
||||
# ARM Architecture
|
||||
|
||||
+config AIROHA_WATCHDOG
|
||||
+ tristate "Airoha EN7581 Watchdog"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ select WATCHDOG_CORE
|
||||
+ help
|
||||
+ Watchdog timer embedded into Airoha SoC. This will reboot your
|
||||
+ system when the timeout is reached.
|
||||
+
|
||||
config ARM_SP805_WATCHDOG
|
||||
tristate "ARM SP805 Watchdog"
|
||||
depends on (ARM || ARM64 || COMPILE_TEST) && ARM_AMBA
|
||||
--- a/drivers/watchdog/Makefile
|
||||
+++ b/drivers/watchdog/Makefile
|
||||
@@ -40,6 +40,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.
|
||||
obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
|
||||
obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
|
||||
obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
|
||||
+obj-$(CONFIG_AIROHA_WATCHDOG) += airoha_wdt.o
|
||||
obj-$(CONFIG_ASM9260_WATCHDOG) += asm9260_wdt.o
|
||||
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
|
||||
obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/watchdog/airoha_wdt.c
|
||||
@@ -0,0 +1,216 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+/*
|
||||
+ * Airoha Watchdog Driver
|
||||
+ *
|
||||
+ * Copyright (c) 2024, AIROHA All rights reserved.
|
||||
+ *
|
||||
+ * Mayur Kumar <mayur.kumar@airoha.com>
|
||||
+ * Christian Marangi <ansuelsmth@gmail.com>
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/moduleparam.h>
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/math.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/watchdog.h>
|
||||
+
|
||||
+/* Base address of timer and watchdog registers */
|
||||
+#define TIMER_CTRL 0x0
|
||||
+#define WDT_ENABLE BIT(25)
|
||||
+#define WDT_TIMER_INTERRUPT BIT(21)
|
||||
+/* Timer3 is used as Watchdog Timer */
|
||||
+#define WDT_TIMER_ENABLE BIT(5)
|
||||
+#define WDT_TIMER_LOAD_VALUE 0x2c
|
||||
+#define WDT_TIMER_CUR_VALUE 0x30
|
||||
+#define WDT_TIMER_VAL GENMASK(31, 0)
|
||||
+#define WDT_RELOAD 0x38
|
||||
+#define WDT_RLD BIT(0)
|
||||
+
|
||||
+/* Airoha watchdog structure description */
|
||||
+struct airoha_wdt_desc {
|
||||
+ struct watchdog_device wdog_dev;
|
||||
+ unsigned int wdt_freq;
|
||||
+ void __iomem *base;
|
||||
+};
|
||||
+
|
||||
+#define WDT_HEARTBEAT 24
|
||||
+static int heartbeat = WDT_HEARTBEAT;
|
||||
+module_param(heartbeat, int, 0);
|
||||
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. (default="
|
||||
+ __MODULE_STRING(WDT_HEARTBEAT) ")");
|
||||
+
|
||||
+static bool nowayout = WATCHDOG_NOWAYOUT;
|
||||
+module_param(nowayout, bool, 0);
|
||||
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
|
||||
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
+
|
||||
+static int airoha_wdt_start(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + TIMER_CTRL);
|
||||
+ val |= (WDT_TIMER_ENABLE | WDT_ENABLE | WDT_TIMER_INTERRUPT);
|
||||
+ writel(val, airoha_wdt->base + TIMER_CTRL);
|
||||
+ val = wdog_dev->timeout * airoha_wdt->wdt_freq;
|
||||
+ writel(val, airoha_wdt->base + WDT_TIMER_LOAD_VALUE);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_stop(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + TIMER_CTRL);
|
||||
+ val &= (~WDT_ENABLE & ~WDT_TIMER_ENABLE);
|
||||
+ writel(val, airoha_wdt->base + TIMER_CTRL);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_ping(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + WDT_RELOAD);
|
||||
+ val |= WDT_RLD;
|
||||
+ writel(val, airoha_wdt->base + WDT_RELOAD);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_set_timeout(struct watchdog_device *wdog_dev, unsigned int timeout)
|
||||
+{
|
||||
+ wdog_dev->timeout = timeout;
|
||||
+
|
||||
+ if (watchdog_active(wdog_dev)) {
|
||||
+ airoha_wdt_stop(wdog_dev);
|
||||
+ return airoha_wdt_start(wdog_dev);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int airoha_wdt_get_timeleft(struct watchdog_device *wdog_dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
|
||||
+ u32 val;
|
||||
+
|
||||
+ val = readl(airoha_wdt->base + WDT_TIMER_CUR_VALUE);
|
||||
+ return DIV_ROUND_UP(val, airoha_wdt->wdt_freq);
|
||||
+}
|
||||
+
|
||||
+static const struct watchdog_info airoha_wdt_info = {
|
||||
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
|
||||
+ .identity = "Airoha Watchdog",
|
||||
+};
|
||||
+
|
||||
+static const struct watchdog_ops airoha_wdt_ops = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .start = airoha_wdt_start,
|
||||
+ .stop = airoha_wdt_stop,
|
||||
+ .ping = airoha_wdt_ping,
|
||||
+ .set_timeout = airoha_wdt_set_timeout,
|
||||
+ .get_timeleft = airoha_wdt_get_timeleft,
|
||||
+};
|
||||
+
|
||||
+static int airoha_wdt_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt;
|
||||
+ struct watchdog_device *wdog_dev;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct clk *bus_clk;
|
||||
+ int ret;
|
||||
+
|
||||
+ airoha_wdt = devm_kzalloc(dev, sizeof(*airoha_wdt), GFP_KERNEL);
|
||||
+ if (!airoha_wdt)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ airoha_wdt->base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(airoha_wdt->base))
|
||||
+ return PTR_ERR(airoha_wdt->base);
|
||||
+
|
||||
+ bus_clk = devm_clk_get_enabled(dev, "bus");
|
||||
+ if (IS_ERR(bus_clk))
|
||||
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
|
||||
+ "failed to enable bus clock\n");
|
||||
+
|
||||
+ /* Watchdog ticks at half the bus rate */
|
||||
+ airoha_wdt->wdt_freq = clk_get_rate(bus_clk) / 2;
|
||||
+
|
||||
+ /* Initialize struct watchdog device */
|
||||
+ wdog_dev = &airoha_wdt->wdog_dev;
|
||||
+ wdog_dev->timeout = heartbeat;
|
||||
+ wdog_dev->info = &airoha_wdt_info;
|
||||
+ wdog_dev->ops = &airoha_wdt_ops;
|
||||
+ /* Bus 300MHz, watchdog 150MHz, 28 seconds */
|
||||
+ wdog_dev->max_timeout = FIELD_MAX(WDT_TIMER_VAL) / airoha_wdt->wdt_freq;
|
||||
+ wdog_dev->parent = dev;
|
||||
+
|
||||
+ watchdog_set_drvdata(wdog_dev, airoha_wdt);
|
||||
+ watchdog_set_nowayout(wdog_dev, nowayout);
|
||||
+ watchdog_stop_on_unregister(wdog_dev);
|
||||
+
|
||||
+ ret = devm_watchdog_register_device(dev, wdog_dev);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, airoha_wdt);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (watchdog_active(&airoha_wdt->wdog_dev))
|
||||
+ airoha_wdt_stop(&airoha_wdt->wdog_dev);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_wdt_resume(struct device *dev)
|
||||
+{
|
||||
+ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev);
|
||||
+
|
||||
+ if (watchdog_active(&airoha_wdt->wdog_dev)) {
|
||||
+ airoha_wdt_start(&airoha_wdt->wdog_dev);
|
||||
+ airoha_wdt_ping(&airoha_wdt->wdog_dev);
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_wdt_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-wdt", },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+MODULE_DEVICE_TABLE(of, airoha_wdt_of_match);
|
||||
+
|
||||
+static DEFINE_SIMPLE_DEV_PM_OPS(airoha_wdt_pm_ops, airoha_wdt_suspend, airoha_wdt_resume);
|
||||
+
|
||||
+static struct platform_driver airoha_wdt_driver = {
|
||||
+ .probe = airoha_wdt_probe,
|
||||
+ .driver = {
|
||||
+ .name = "airoha-wdt",
|
||||
+ .pm = pm_sleep_ptr(&airoha_wdt_pm_ops),
|
||||
+ .of_match_table = airoha_wdt_of_match,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(airoha_wdt_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Mayur Kumar <mayur.kumar@airoha.com>");
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Airoha EN7581 Watchdog Driver");
|
||||
+MODULE_LICENSE("GPL");
|
@@ -1,62 +0,0 @@
|
||||
From c31d1cdd7bff1d2c13d435bb9d0c76bfaa332097 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:49 +0100
|
||||
Subject: [PATCH 1/6] clk: en7523: remove REG_PCIE*_{MEM,MEM_MASK}
|
||||
configuration
|
||||
|
||||
REG_PCIE*_MEM and REG_PCIE*_MEM_MASK regs (PBUS_CSR memory region) are not
|
||||
part of the scu block on the EN7581 SoC and they are used to select the
|
||||
PCIE ports on the PBUS, so remove this configuration from the clock driver
|
||||
and set these registers in the PCIE host driver instead.
|
||||
This patch does not introduce any backward incompatibility since the dts
|
||||
for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-2-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 18 ------------------
|
||||
1 file changed, 18 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -31,12 +31,6 @@
|
||||
#define REG_RESET_CONTROL_PCIE1 BIT(27)
|
||||
#define REG_RESET_CONTROL_PCIE2 BIT(26)
|
||||
/* EN7581 */
|
||||
-#define REG_PCIE0_MEM 0x00
|
||||
-#define REG_PCIE0_MEM_MASK 0x04
|
||||
-#define REG_PCIE1_MEM 0x08
|
||||
-#define REG_PCIE1_MEM_MASK 0x0c
|
||||
-#define REG_PCIE2_MEM 0x10
|
||||
-#define REG_PCIE2_MEM_MASK 0x14
|
||||
#define REG_NP_SCU_PCIC 0x88
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
@@ -415,26 +409,14 @@ static void en7581_pci_disable(struct cl
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
void __iomem *np_base)
|
||||
{
|
||||
- void __iomem *pb_base;
|
||||
u32 val;
|
||||
|
||||
- pb_base = devm_platform_ioremap_resource(pdev, 3);
|
||||
- if (IS_ERR(pb_base))
|
||||
- return PTR_ERR(pb_base);
|
||||
-
|
||||
val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
|
||||
- writel(0x20000000, pb_base + REG_PCIE0_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE0_MEM_MASK);
|
||||
- writel(0x24000000, pb_base + REG_PCIE1_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE1_MEM_MASK);
|
||||
- writel(0x28000000, pb_base + REG_PCIE2_MEM);
|
||||
- writel(0xfc000000, pb_base + REG_PCIE2_MEM_MASK);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,146 +0,0 @@
|
||||
From b8bdfc666bc5f58caf46e67b615132fccbaca3d4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:50 +0100
|
||||
Subject: [PATCH 2/6] clk: en7523: move clock_register in hw_init callback
|
||||
|
||||
Move en7523_register_clocks routine in hw_init callback.
|
||||
Introduce en7523_clk_hw_init callback for EN7523 SoC.
|
||||
This is a preliminary patch to differentiate IO mapped region between
|
||||
EN7523 and EN7581 SoCs in order to access chip-scu IO region
|
||||
<0x1fa20000 0x384> on EN7581 SoC as syscon device since it contains
|
||||
miscellaneous registers needed by multiple devices (clock, pinctrl ..).
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-3-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 82 ++++++++++++++++++++++++----------------
|
||||
1 file changed, 50 insertions(+), 32 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -78,7 +78,8 @@ struct en_clk_soc_data {
|
||||
const u16 *idx_map;
|
||||
u16 idx_map_nr;
|
||||
} reset;
|
||||
- int (*hw_init)(struct platform_device *pdev, void __iomem *np_base);
|
||||
+ int (*hw_init)(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data);
|
||||
};
|
||||
|
||||
static const u32 gsw_base[] = { 400000000, 500000000 };
|
||||
@@ -406,20 +407,6 @@ static void en7581_pci_disable(struct cl
|
||||
usleep_range(1000, 2000);
|
||||
}
|
||||
|
||||
-static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- void __iomem *np_base)
|
||||
-{
|
||||
- u32 val;
|
||||
-
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
void __iomem *base, void __iomem *np_base)
|
||||
{
|
||||
@@ -449,6 +436,49 @@ static void en7523_register_clocks(struc
|
||||
clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
}
|
||||
|
||||
+static int en7523_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *base, *np_base;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *base, *np_base;
|
||||
+ u32 val;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ 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);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
@@ -543,31 +573,18 @@ static int en7523_clk_probe(struct platf
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
const struct en_clk_soc_data *soc_data;
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
- void __iomem *base, *np_base;
|
||||
int r;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
-
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
-
|
||||
- soc_data = device_get_match_data(&pdev->dev);
|
||||
- if (soc_data->hw_init) {
|
||||
- r = soc_data->hw_init(pdev, np_base);
|
||||
- if (r)
|
||||
- return r;
|
||||
- }
|
||||
-
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+ r = soc_data->hw_init(pdev, clk_data);
|
||||
+ if (r)
|
||||
+ return r;
|
||||
|
||||
r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
if (r)
|
||||
@@ -590,6 +607,7 @@ static const struct en_clk_soc_data en75
|
||||
.prepare = en7523_pci_prepare,
|
||||
.unprepare = en7523_pci_unprepare,
|
||||
},
|
||||
+ .hw_init = en7523_clk_hw_init,
|
||||
};
|
||||
|
||||
static const struct en_clk_soc_data en7581_data = {
|
@@ -1,162 +0,0 @@
|
||||
From f72fc22038dd544fa4d39c06e8c81c09c0041ed4 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:51 +0100
|
||||
Subject: [PATCH 3/6] clk: en7523: introduce chip_scu regmap
|
||||
|
||||
Introduce chip_scu regmap pointer since EN7581 SoC will access chip-scu
|
||||
memory area via a syscon node. Remove first memory region mapping
|
||||
for EN7581 SoC. This patch does not introduce any backward incompatibility
|
||||
since the dts for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-4-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 81 ++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 61 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -3,8 +3,10 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/reset-controller.h>
|
||||
#include <dt-bindings/clock/en7523-clk.h>
|
||||
#include <dt-bindings/reset/airoha,en7581-reset.h>
|
||||
@@ -247,15 +249,11 @@ static const u16 en7581_rst_map[] = {
|
||||
[EN7581_XPON_MAC_RST] = RST_NR_PER_BANK + 31,
|
||||
};
|
||||
|
||||
-static unsigned int en7523_get_base_rate(void __iomem *base, unsigned int i)
|
||||
+static u32 en7523_get_base_rate(const struct en_clk_desc *desc, u32 val)
|
||||
{
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
- u32 val;
|
||||
-
|
||||
if (!desc->base_bits)
|
||||
return desc->base_value;
|
||||
|
||||
- val = readl(base + desc->base_reg);
|
||||
val >>= desc->base_shift;
|
||||
val &= (1 << desc->base_bits) - 1;
|
||||
|
||||
@@ -265,16 +263,11 @@ static unsigned int en7523_get_base_rate
|
||||
return desc->base_values[val];
|
||||
}
|
||||
|
||||
-static u32 en7523_get_div(void __iomem *base, int i)
|
||||
+static u32 en7523_get_div(const struct en_clk_desc *desc, u32 val)
|
||||
{
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[i];
|
||||
- u32 reg, val;
|
||||
-
|
||||
if (!desc->div_bits)
|
||||
return 1;
|
||||
|
||||
- reg = desc->div_reg ? desc->div_reg : desc->base_reg;
|
||||
- val = readl(base + reg);
|
||||
val >>= desc->div_shift;
|
||||
val &= (1 << desc->div_bits) - 1;
|
||||
|
||||
@@ -418,9 +411,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);
|
||||
|
||||
- rate = en7523_get_base_rate(base, i);
|
||||
- rate /= en7523_get_div(base, i);
|
||||
+ rate = en7523_get_base_rate(desc, val);
|
||||
+ val = readl(base + reg);
|
||||
+ rate /= en7523_get_div(desc, val);
|
||||
|
||||
hw = clk_hw_register_fixed_rate(dev, desc->name, NULL, 0, rate);
|
||||
if (IS_ERR(hw)) {
|
||||
@@ -454,21 +450,66 @@ static int en7523_clk_hw_init(struct pla
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void en7581_register_clocks(struct device *dev, struct clk_hw_onecell_data *clk_data,
|
||||
+ struct regmap *map, void __iomem *base)
|
||||
+{
|
||||
+ 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 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, base);
|
||||
+ clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
+
|
||||
+ clk_data->num = EN7523_NUM_CLOCKS;
|
||||
+}
|
||||
+
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
- void __iomem *base, *np_base;
|
||||
+ void __iomem *np_base;
|
||||
+ struct regmap *map;
|
||||
u32 val;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
+ if (IS_ERR(map))
|
||||
+ return PTR_ERR(map);
|
||||
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 1);
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
if (IS_ERR(np_base))
|
||||
return PTR_ERR(np_base);
|
||||
|
||||
- en7523_register_clocks(&pdev->dev, clk_data, base, np_base);
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
|
||||
val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
@@ -545,7 +586,7 @@ static int en7523_reset_register(struct
|
||||
if (!soc_data->reset.idx_map_nr)
|
||||
return 0;
|
||||
|
||||
- base = devm_platform_ioremap_resource(pdev, 2);
|
||||
+ base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
|
@@ -1,152 +0,0 @@
|
||||
From f98eded9e9ab048c88ff59c5523e703a6ced5523 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:52 +0100
|
||||
Subject: [PATCH 4/6] clk: en7523: fix estimation of fixed rate for EN7581
|
||||
|
||||
Introduce en7581_base_clks array in order to define per-SoC fixed-rate
|
||||
clock parameters and fix wrong parameters for emi, npu and crypto EN7581
|
||||
clocks
|
||||
|
||||
Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-5-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 105 ++++++++++++++++++++++++++++++++++++++-
|
||||
1 file changed, 103 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -37,6 +37,7 @@
|
||||
#define REG_NP_SCU_SSTR 0x9c
|
||||
#define REG_PCIE_XSI0_SEL_MASK GENMASK(14, 13)
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
+#define REG_CRYPTO_CLKSRC2 0x20c
|
||||
|
||||
#define REG_RST_CTRL2 0x00
|
||||
#define REG_RST_CTRL1 0x04
|
||||
@@ -89,6 +90,10 @@ static const u32 emi_base[] = { 33300000
|
||||
static const u32 bus_base[] = { 500000000, 540000000 };
|
||||
static const u32 slic_base[] = { 100000000, 3125000 };
|
||||
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
|
||||
+/* EN7581 */
|
||||
+static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
|
||||
+static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
+static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
|
||||
static const struct en_clk_desc en7523_base_clks[] = {
|
||||
{
|
||||
@@ -186,6 +191,102 @@ static const struct en_clk_desc en7523_b
|
||||
}
|
||||
};
|
||||
|
||||
+static const struct en_clk_desc en7581_base_clks[] = {
|
||||
+ {
|
||||
+ .id = EN7523_CLK_GSW,
|
||||
+ .name = "gsw",
|
||||
+
|
||||
+ .base_reg = REG_GSW_CLK_DIV_SEL,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = gsw_base,
|
||||
+ .n_base_values = ARRAY_SIZE(gsw_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 = emi7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(emi7581_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 = 1,
|
||||
+ .base_shift = 8,
|
||||
+ .base_values = bus_base,
|
||||
+ .n_base_values = ARRAY_SIZE(bus_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_DIV_SEL,
|
||||
+
|
||||
+ .base_value = 400000000,
|
||||
+
|
||||
+ .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 = 8,
|
||||
+ .base_values = npu7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(npu7581_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 = crypto_base,
|
||||
+ .n_base_values = ARRAY_SIZE(crypto_base),
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
static const u16 en7581_rst_ofs[] = {
|
||||
REG_RST_CTRL2,
|
||||
REG_RST_CTRL1,
|
||||
@@ -457,8 +558,8 @@ static void en7581_register_clocks(struc
|
||||
u32 rate;
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
|
||||
- const struct en_clk_desc *desc = &en7523_base_clks[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;
|
||||
|
@@ -1,174 +0,0 @@
|
||||
From 82e6bf912d5846646892becea659b39d178d79e3 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:53 +0100
|
||||
Subject: [PATCH 5/6] clk: en7523: move en7581_reset_register() in
|
||||
en7581_clk_hw_init()
|
||||
|
||||
Move en7581_reset_register routine in en7581_clk_hw_init() since reset
|
||||
feature is supported just by EN7581 SoC.
|
||||
Get rid of reset struct in en_clk_soc_data data struct.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-6-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 93 ++++++++++++++--------------------------
|
||||
1 file changed, 33 insertions(+), 60 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -76,11 +76,6 @@ struct en_rst_data {
|
||||
|
||||
struct en_clk_soc_data {
|
||||
const struct clk_ops pcie_ops;
|
||||
- struct {
|
||||
- const u16 *bank_ofs;
|
||||
- const u16 *idx_map;
|
||||
- u16 idx_map_nr;
|
||||
- } reset;
|
||||
int (*hw_init)(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data);
|
||||
};
|
||||
@@ -595,32 +590,6 @@ static void en7581_register_clocks(struc
|
||||
clk_data->num = EN7523_NUM_CLOCKS;
|
||||
}
|
||||
|
||||
-static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
- struct clk_hw_onecell_data *clk_data)
|
||||
-{
|
||||
- void __iomem *np_base;
|
||||
- struct regmap *map;
|
||||
- u32 val;
|
||||
-
|
||||
- map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
- if (IS_ERR(map))
|
||||
- return PTR_ERR(map);
|
||||
-
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
-
|
||||
- en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
-
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
- val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
unsigned long id, bool assert)
|
||||
{
|
||||
@@ -670,23 +639,18 @@ static int en7523_reset_xlate(struct res
|
||||
return rst_data->idx_map[reset_spec->args[0]];
|
||||
}
|
||||
|
||||
-static const struct reset_control_ops en7523_reset_ops = {
|
||||
+static const struct reset_control_ops en7581_reset_ops = {
|
||||
.assert = en7523_reset_assert,
|
||||
.deassert = en7523_reset_deassert,
|
||||
.status = en7523_reset_status,
|
||||
};
|
||||
|
||||
-static int en7523_reset_register(struct platform_device *pdev,
|
||||
- const struct en_clk_soc_data *soc_data)
|
||||
+static int en7581_reset_register(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct en_rst_data *rst_data;
|
||||
void __iomem *base;
|
||||
|
||||
- /* no reset lines available */
|
||||
- if (!soc_data->reset.idx_map_nr)
|
||||
- return 0;
|
||||
-
|
||||
base = devm_platform_ioremap_resource(pdev, 1);
|
||||
if (IS_ERR(base))
|
||||
return PTR_ERR(base);
|
||||
@@ -695,13 +659,13 @@ static int en7523_reset_register(struct
|
||||
if (!rst_data)
|
||||
return -ENOMEM;
|
||||
|
||||
- rst_data->bank_ofs = soc_data->reset.bank_ofs;
|
||||
- rst_data->idx_map = soc_data->reset.idx_map;
|
||||
+ rst_data->bank_ofs = en7581_rst_ofs;
|
||||
+ rst_data->idx_map = en7581_rst_map;
|
||||
rst_data->base = base;
|
||||
|
||||
- rst_data->rcdev.nr_resets = soc_data->reset.idx_map_nr;
|
||||
+ rst_data->rcdev.nr_resets = ARRAY_SIZE(en7581_rst_map);
|
||||
rst_data->rcdev.of_xlate = en7523_reset_xlate;
|
||||
- rst_data->rcdev.ops = &en7523_reset_ops;
|
||||
+ 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;
|
||||
@@ -710,6 +674,32 @@ static int en7523_reset_register(struct
|
||||
return devm_reset_controller_register(dev, &rst_data->rcdev);
|
||||
}
|
||||
|
||||
+static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
+ struct clk_hw_onecell_data *clk_data)
|
||||
+{
|
||||
+ void __iomem *np_base;
|
||||
+ struct regmap *map;
|
||||
+ u32 val;
|
||||
+
|
||||
+ map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
+ if (IS_ERR(map))
|
||||
+ return PTR_ERR(map);
|
||||
+
|
||||
+ np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(np_base))
|
||||
+ return PTR_ERR(np_base);
|
||||
+
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
+
|
||||
+ val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
+ writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+
|
||||
+ return en7581_reset_register(pdev);
|
||||
+}
|
||||
+
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
@@ -728,19 +718,7 @@ static int en7523_clk_probe(struct platf
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
- r = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
- if (r)
|
||||
- return dev_err_probe(&pdev->dev, r, "Could not register clock provider: %s\n",
|
||||
- pdev->name);
|
||||
-
|
||||
- r = en7523_reset_register(pdev, soc_data);
|
||||
- if (r) {
|
||||
- of_clk_del_provider(node);
|
||||
- return dev_err_probe(&pdev->dev, r, "Could not register reset controller: %s\n",
|
||||
- pdev->name);
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
+ return of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data);
|
||||
}
|
||||
|
||||
static const struct en_clk_soc_data en7523_data = {
|
||||
@@ -758,11 +736,6 @@ static const struct en_clk_soc_data en75
|
||||
.enable = en7581_pci_enable,
|
||||
.disable = en7581_pci_disable,
|
||||
},
|
||||
- .reset = {
|
||||
- .bank_ofs = en7581_rst_ofs,
|
||||
- .idx_map = en7581_rst_map,
|
||||
- .idx_map_nr = ARRAY_SIZE(en7581_rst_map),
|
||||
- },
|
||||
.hw_init = en7581_clk_hw_init,
|
||||
};
|
||||
|
@@ -1,84 +0,0 @@
|
||||
From a9eaf305017a5ebe73ab34e85bd5414055a88f29 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 12 Nov 2024 01:08:54 +0100
|
||||
Subject: [PATCH 6/6] clk: en7523: map io region in a single block
|
||||
|
||||
Map all clock-controller memory region in a single block.
|
||||
This patch does not introduce any backward incompatibility since the dts
|
||||
for EN7581 SoC is not upstream yet.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20241112-clk-en7581-syscon-v2-7-8ada5e394ae4@kernel.org
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 32 +++++++++++++-------------------
|
||||
1 file changed, 13 insertions(+), 19 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -39,8 +39,8 @@
|
||||
#define REG_PCIE_XSI1_SEL_MASK GENMASK(12, 11)
|
||||
#define REG_CRYPTO_CLKSRC2 0x20c
|
||||
|
||||
-#define REG_RST_CTRL2 0x00
|
||||
-#define REG_RST_CTRL1 0x04
|
||||
+#define REG_RST_CTRL2 0x830
|
||||
+#define REG_RST_CTRL1 0x834
|
||||
|
||||
struct en_clk_desc {
|
||||
int id;
|
||||
@@ -645,15 +645,9 @@ static const struct reset_control_ops en
|
||||
.status = en7523_reset_status,
|
||||
};
|
||||
|
||||
-static int en7581_reset_register(struct platform_device *pdev)
|
||||
+static int en7581_reset_register(struct device *dev, void __iomem *base)
|
||||
{
|
||||
- struct device *dev = &pdev->dev;
|
||||
struct en_rst_data *rst_data;
|
||||
- void __iomem *base;
|
||||
-
|
||||
- base = devm_platform_ioremap_resource(pdev, 1);
|
||||
- if (IS_ERR(base))
|
||||
- return PTR_ERR(base);
|
||||
|
||||
rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL);
|
||||
if (!rst_data)
|
||||
@@ -677,27 +671,27 @@ static int en7581_reset_register(struct
|
||||
static int en7581_clk_hw_init(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data)
|
||||
{
|
||||
- void __iomem *np_base;
|
||||
struct regmap *map;
|
||||
+ void __iomem *base;
|
||||
u32 val;
|
||||
|
||||
map = syscon_regmap_lookup_by_compatible("airoha,en7581-chip-scu");
|
||||
if (IS_ERR(map))
|
||||
return PTR_ERR(map);
|
||||
|
||||
- np_base = devm_platform_ioremap_resource(pdev, 0);
|
||||
- if (IS_ERR(np_base))
|
||||
- return PTR_ERR(np_base);
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
|
||||
- en7581_register_clocks(&pdev->dev, clk_data, map, np_base);
|
||||
+ en7581_register_clocks(&pdev->dev, clk_data, map, base);
|
||||
|
||||
- val = readl(np_base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(base + REG_NP_SCU_SSTR);
|
||||
val &= ~(REG_PCIE_XSI0_SEL_MASK | REG_PCIE_XSI1_SEL_MASK);
|
||||
- writel(val, np_base + REG_NP_SCU_SSTR);
|
||||
- val = readl(np_base + REG_NP_SCU_PCIC);
|
||||
- writel(val | 3, np_base + REG_NP_SCU_PCIC);
|
||||
+ writel(val, base + REG_NP_SCU_SSTR);
|
||||
+ val = readl(base + REG_NP_SCU_PCIC);
|
||||
+ writel(val | 3, base + REG_NP_SCU_PCIC);
|
||||
|
||||
- return en7581_reset_register(pdev);
|
||||
+ return en7581_reset_register(&pdev->dev, base);
|
||||
}
|
||||
|
||||
static int en7523_clk_probe(struct platform_device *pdev)
|
File diff suppressed because it is too large
Load Diff
@@ -1,48 +0,0 @@
|
||||
From 2eb75f86d52565367211c51334d15fe672633085 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sat, 16 Nov 2024 11:56:53 +0100
|
||||
Subject: [PATCH] clk: en7523: Fix wrong BUS clock for EN7581
|
||||
|
||||
The Documentation for EN7581 had a typo and still referenced the EN7523
|
||||
BUS base source frequency. This was in conflict with a different page in
|
||||
the Documentration that state that the BUS runs at 300MHz (600MHz source
|
||||
with divisor set to 2) and the actual watchdog that tick at half the BUS
|
||||
clock (150MHz). This was verified with the watchdog by timing the
|
||||
seconds that the system takes to reboot (due too watchdog) and by
|
||||
operating on different values of the BUS divisor.
|
||||
|
||||
The correct values for source of BUS clock are 600MHz and 540MHz.
|
||||
|
||||
This was also confirmed by Airoha.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 66bc47326ce2 ("clk: en7523: Add EN7581 support")
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20241116105710.19748-1-ansuelsmth@gmail.com
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 5 +++--
|
||||
1 file changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -87,6 +87,7 @@ static const u32 slic_base[] = { 1000000
|
||||
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
|
||||
/* EN7581 */
|
||||
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
|
||||
+static const u32 bus7581_base[] = { 600000000, 540000000 };
|
||||
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
|
||||
@@ -222,8 +223,8 @@ static const struct en_clk_desc en7581_b
|
||||
.base_reg = REG_BUS_CLK_DIV_SEL,
|
||||
.base_bits = 1,
|
||||
.base_shift = 8,
|
||||
- .base_values = bus_base,
|
||||
- .n_base_values = ARRAY_SIZE(bus_base),
|
||||
+ .base_values = bus7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(bus7581_base),
|
||||
|
||||
.div_bits = 3,
|
||||
.div_shift = 0,
|
@@ -1,35 +0,0 @@
|
||||
From 30d9d8f6a2d7e44a9f91737dd409dbc87ac6f6b7 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 15 Oct 2024 09:58:09 +0200
|
||||
Subject: [PATCH] net: airoha: Fix typo in REG_CDM2_FWD_CFG configuration
|
||||
|
||||
Fix typo in airoha_fe_init routine configuring CDM2_OAM_QSEL_MASK field
|
||||
of REG_CDM2_FWD_CFG register.
|
||||
This bug is not introducing any user visible problem since Frame Engine
|
||||
CDM2 port is used just by the second QDMA block and we currently enable
|
||||
just QDMA1 block connected to the MT7530 dsa switch via CDM1 port.
|
||||
|
||||
Introduced by commit 23020f049327 ("net: airoha: Introduce ethernet
|
||||
support for EN7581 SoC")
|
||||
|
||||
Reported-by: ChihWei Cheng <chihwei.cheng@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Simon Horman <horms@kernel.org>
|
||||
Message-ID: <20241015-airoha-eth-cdm2-fixes-v1-1-9dc6993286c3@kernel.org>
|
||||
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 3 ++-
|
||||
1 file changed, 2 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1369,7 +1369,8 @@ static int airoha_fe_init(struct airoha_
|
||||
airoha_fe_set(eth, REG_GDM_MISC_CFG,
|
||||
GDM2_RDM_ACK_WAIT_PREF_MASK |
|
||||
GDM2_CHN_VLD_MODE_MASK);
|
||||
- airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK, 15);
|
||||
+ airoha_fe_rmw(eth, REG_CDM2_FWD_CFG, CDM2_OAM_QSEL_MASK,
|
||||
+ FIELD_PREP(CDM2_OAM_QSEL_MASK, 15));
|
||||
|
||||
/* init fragment and assemble Force Port */
|
||||
/* NPU Core-3, NPU Bridge Channel-3 */
|
@@ -1,102 +0,0 @@
|
||||
From 0c7469ee718e1dd929f52bfb142a7f6fb68f0765 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Mon, 16 Dec 2024 18:47:33 +0100
|
||||
Subject: [PATCH] net: airoha: Fix error path in airoha_probe()
|
||||
|
||||
Do not run napi_disable() if airoha_hw_init() fails since Tx/Rx napi
|
||||
has not been started yet. In order to fix the issue, introduce
|
||||
airoha_qdma_stop_napi routine and remove napi_disable in
|
||||
airoha_hw_cleanup().
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Reviewed-by: Michal Swiatkowski <michal.swiatkowski@linux.intel.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20241216-airoha_probe-error-path-fix-v2-1-6b10e04e9a5c@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 33 ++++++++++++++++------
|
||||
1 file changed, 25 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2139,17 +2139,14 @@ static void airoha_hw_cleanup(struct air
|
||||
if (!qdma->q_rx[i].ndesc)
|
||||
continue;
|
||||
|
||||
- napi_disable(&qdma->q_rx[i].napi);
|
||||
netif_napi_del(&qdma->q_rx[i].napi);
|
||||
airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
|
||||
if (qdma->q_rx[i].page_pool)
|
||||
page_pool_destroy(qdma->q_rx[i].page_pool);
|
||||
}
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
|
||||
- napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
netif_napi_del(&qdma->q_tx_irq[i].napi);
|
||||
- }
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
if (!qdma->q_tx[i].ndesc)
|
||||
@@ -2174,6 +2171,21 @@ static void airoha_qdma_start_napi(struc
|
||||
}
|
||||
}
|
||||
|
||||
+static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
|
||||
+ napi_disable(&qdma->q_tx_irq[i].napi);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
|
||||
+ if (!qdma->q_rx[i].ndesc)
|
||||
+ continue;
|
||||
+
|
||||
+ napi_disable(&qdma->q_rx[i].napi);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static void airoha_update_hw_stats(struct airoha_gdm_port *port)
|
||||
{
|
||||
struct airoha_eth *eth = port->qdma->eth;
|
||||
@@ -2731,7 +2743,7 @@ static int airoha_probe(struct platform_
|
||||
|
||||
err = airoha_hw_init(pdev, eth);
|
||||
if (err)
|
||||
- goto error;
|
||||
+ goto error_hw_cleanup;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
airoha_qdma_start_napi(ð->qdma[i]);
|
||||
@@ -2746,13 +2758,16 @@ static int airoha_probe(struct platform_
|
||||
err = airoha_alloc_gdm_port(eth, np);
|
||||
if (err) {
|
||||
of_node_put(np);
|
||||
- goto error;
|
||||
+ goto error_napi_stop;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
-error:
|
||||
+error_napi_stop:
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ airoha_qdma_stop_napi(ð->qdma[i]);
|
||||
+error_hw_cleanup:
|
||||
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
airoha_hw_cleanup(ð->qdma[i]);
|
||||
|
||||
@@ -2773,8 +2788,10 @@ static void airoha_remove(struct platfor
|
||||
struct airoha_eth *eth = platform_get_drvdata(pdev);
|
||||
int i;
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
|
||||
+ airoha_qdma_stop_napi(ð->qdma[i]);
|
||||
airoha_hw_cleanup(ð->qdma[i]);
|
||||
+ }
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
@@ -1,27 +0,0 @@
|
||||
From 5f795590380476f1c9b7ed0ac945c9b0269dc23a Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 3 Jan 2025 13:17:02 +0100
|
||||
Subject: [PATCH 1/4] net: airoha: Enable Tx drop capability for each Tx DMA
|
||||
ring
|
||||
|
||||
This is a preliminary patch in order to enable hw Qdisc offloading.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -1790,6 +1790,10 @@ static int airoha_qdma_init_tx_queue(str
|
||||
WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val));
|
||||
}
|
||||
|
||||
+ /* xmit ring drop default setting */
|
||||
+ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid),
|
||||
+ TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK);
|
||||
+
|
||||
airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr);
|
||||
airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
|
||||
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
|
@@ -1,86 +0,0 @@
|
||||
From 2b288b81560b94958cd68bbe54673e55a1730c95 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 3 Jan 2025 13:17:03 +0100
|
||||
Subject: [PATCH 2/4] net: airoha: Introduce ndo_select_queue callback
|
||||
|
||||
Airoha EN7581 SoC supports 32 Tx DMA rings used to feed packets to QoS
|
||||
channels. Each channels supports 8 QoS queues where the user can apply
|
||||
QoS scheduling policies. In a similar way, the user can configure hw
|
||||
rate shaping for each QoS channel.
|
||||
Introduce ndo_select_queue callback in order to select the tx queue
|
||||
based on QoS channel and QoS queue. In particular, for dsa device select
|
||||
QoS channel according to the dsa user port index, rely on port id
|
||||
otherwise. Select QoS queue based on the skb priority.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 30 ++++++++++++++++++++--
|
||||
1 file changed, 28 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -23,6 +23,8 @@
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
#define AIROHA_MAX_PACKET_SIZE 2048
|
||||
+#define AIROHA_NUM_QOS_CHANNELS 4
|
||||
+#define AIROHA_NUM_QOS_QUEUES 8
|
||||
#define AIROHA_NUM_TX_RING 32
|
||||
#define AIROHA_NUM_RX_RING 32
|
||||
#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
|
||||
@@ -2422,21 +2424,44 @@ static void airoha_dev_get_stats64(struc
|
||||
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
|
||||
}
|
||||
|
||||
+static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
|
||||
+ struct net_device *sb_dev)
|
||||
+{
|
||||
+ struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
+ int queue, channel;
|
||||
+
|
||||
+ /* For dsa device select QoS channel according to the dsa user port
|
||||
+ * index, rely on port id otherwise. Select QoS queue based on the
|
||||
+ * skb priority.
|
||||
+ */
|
||||
+ channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
|
||||
+ channel = channel % AIROHA_NUM_QOS_CHANNELS;
|
||||
+ queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
|
||||
+ queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
|
||||
+
|
||||
+ return queue < dev->num_tx_queues ? queue : 0;
|
||||
+}
|
||||
+
|
||||
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct skb_shared_info *sinfo = skb_shinfo(skb);
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- u32 msg0 = 0, msg1, len = skb_headlen(skb);
|
||||
- int i, qid = skb_get_queue_mapping(skb);
|
||||
+ u32 msg0, msg1, len = skb_headlen(skb);
|
||||
struct airoha_qdma *qdma = port->qdma;
|
||||
u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
+ int i, qid;
|
||||
u16 index;
|
||||
u8 fport;
|
||||
|
||||
+ qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx);
|
||||
+ msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK,
|
||||
+ qid / AIROHA_NUM_QOS_QUEUES) |
|
||||
+ FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK,
|
||||
+ qid % AIROHA_NUM_QOS_QUEUES);
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) |
|
||||
@@ -2610,6 +2635,7 @@ static const struct net_device_ops airoh
|
||||
.ndo_init = airoha_dev_init,
|
||||
.ndo_open = airoha_dev_open,
|
||||
.ndo_stop = airoha_dev_stop,
|
||||
+ .ndo_select_queue = airoha_dev_select_queue,
|
||||
.ndo_start_xmit = airoha_dev_xmit,
|
||||
.ndo_get_stats64 = airoha_dev_get_stats64,
|
||||
.ndo_set_mac_address = airoha_dev_set_macaddr,
|
@@ -1,292 +0,0 @@
|
||||
From 20bf7d07c956e5c7a22d3076c599cbb7a6054917 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 3 Jan 2025 13:17:04 +0100
|
||||
Subject: [PATCH 3/4] net: airoha: Add sched ETS offload support
|
||||
|
||||
Introduce support for ETS Qdisc offload available on the Airoha EN7581
|
||||
ethernet controller. In order to be effective, ETS Qdisc must configured
|
||||
as leaf of a HTB Qdisc (HTB Qdisc offload will be added in the following
|
||||
patch). ETS Qdisc available on EN7581 ethernet controller supports at
|
||||
most 8 concurrent bands (QoS queues). We can enable an ETS Qdisc for
|
||||
each available QoS channel.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 196 ++++++++++++++++++++-
|
||||
1 file changed, 195 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <net/dsa.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
+#include <net/pkt_cls.h>
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
@@ -543,9 +544,24 @@
|
||||
#define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16)
|
||||
#define INGRESS_FAST_TICK_MASK GENMASK(15, 0)
|
||||
|
||||
+#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc))
|
||||
+#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3))
|
||||
+
|
||||
#define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0)
|
||||
#define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2)
|
||||
|
||||
+#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3))
|
||||
+#define CNTR_EN_MASK BIT(31)
|
||||
+#define CNTR_ALL_CHAN_EN_MASK BIT(30)
|
||||
+#define CNTR_ALL_QUEUE_EN_MASK BIT(29)
|
||||
+#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28)
|
||||
+#define CNTR_SRC_MASK GENMASK(27, 24)
|
||||
+#define CNTR_DSCP_RING_MASK GENMASK(20, 16)
|
||||
+#define CNTR_CHAN_MASK GENMASK(7, 3)
|
||||
+#define CNTR_QUEUE_MASK GENMASK(2, 0)
|
||||
+
|
||||
+#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3))
|
||||
+
|
||||
#define REG_LMGR_INIT_CFG 0x1000
|
||||
#define LMGR_INIT_START BIT(31)
|
||||
#define LMGR_SRAM_MODE_MASK BIT(30)
|
||||
@@ -571,9 +587,19 @@
|
||||
#define TWRR_WEIGHT_SCALE_MASK BIT(31)
|
||||
#define TWRR_WEIGHT_BASE_MASK BIT(3)
|
||||
|
||||
+#define REG_TXWRR_WEIGHT_CFG 0x1024
|
||||
+#define TWRR_RW_CMD_MASK BIT(31)
|
||||
+#define TWRR_RW_CMD_DONE BIT(30)
|
||||
+#define TWRR_CHAN_IDX_MASK GENMASK(23, 19)
|
||||
+#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16)
|
||||
+#define TWRR_VALUE_MASK GENMASK(15, 0)
|
||||
+
|
||||
#define REG_PSE_BUF_USAGE_CFG 0x1028
|
||||
#define PSE_BUF_ESTIMATE_EN_MASK BIT(29)
|
||||
|
||||
+#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2))
|
||||
+#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2)
|
||||
+
|
||||
#define REG_GLB_TRTCM_CFG 0x1080
|
||||
#define GLB_TRTCM_EN_MASK BIT(31)
|
||||
#define GLB_TRTCM_MODE_MASK BIT(30)
|
||||
@@ -722,6 +748,17 @@ enum {
|
||||
FE_PSE_PORT_DROP = 0xf,
|
||||
};
|
||||
|
||||
+enum tx_sched_mode {
|
||||
+ TC_SCH_WRR8,
|
||||
+ TC_SCH_SP,
|
||||
+ TC_SCH_WRR7,
|
||||
+ TC_SCH_WRR6,
|
||||
+ TC_SCH_WRR5,
|
||||
+ TC_SCH_WRR4,
|
||||
+ TC_SCH_WRR3,
|
||||
+ TC_SCH_WRR2,
|
||||
+};
|
||||
+
|
||||
struct airoha_queue_entry {
|
||||
union {
|
||||
void *buf;
|
||||
@@ -812,6 +849,10 @@ struct airoha_gdm_port {
|
||||
int id;
|
||||
|
||||
struct airoha_hw_stats stats;
|
||||
+
|
||||
+ /* qos stats counters */
|
||||
+ u64 cpu_tx_packets;
|
||||
+ u64 fwd_tx_packets;
|
||||
};
|
||||
|
||||
struct airoha_eth {
|
||||
@@ -1962,6 +2003,27 @@ static void airoha_qdma_init_qos(struct
|
||||
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
|
||||
}
|
||||
|
||||
+static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < AIROHA_NUM_QOS_CHANNELS; i++) {
|
||||
+ /* Tx-cpu transferred count */
|
||||
+ airoha_qdma_wr(qdma, REG_CNTR_VAL(i << 1), 0);
|
||||
+ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
|
||||
+ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
|
||||
+ CNTR_ALL_DSCP_RING_EN_MASK |
|
||||
+ FIELD_PREP(CNTR_CHAN_MASK, i));
|
||||
+ /* Tx-fwd transferred count */
|
||||
+ airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
|
||||
+ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
|
||||
+ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
|
||||
+ CNTR_ALL_DSCP_RING_EN_MASK |
|
||||
+ FIELD_PREP(CNTR_SRC_MASK, 1) |
|
||||
+ FIELD_PREP(CNTR_CHAN_MASK, i));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
|
||||
{
|
||||
int i;
|
||||
@@ -2012,6 +2074,7 @@ static int airoha_qdma_hw_init(struct ai
|
||||
|
||||
airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG,
|
||||
TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN);
|
||||
+ airoha_qdma_init_qos_stats(qdma);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -2631,6 +2694,135 @@ airoha_ethtool_get_rmon_stats(struct net
|
||||
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
|
||||
}
|
||||
|
||||
+static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port,
|
||||
+ int channel, enum tx_sched_mode mode,
|
||||
+ const u16 *weights, u8 n_weights)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < AIROHA_NUM_TX_RING; i++)
|
||||
+ airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel),
|
||||
+ TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));
|
||||
+
|
||||
+ for (i = 0; i < n_weights; i++) {
|
||||
+ u32 status;
|
||||
+ int err;
|
||||
+
|
||||
+ airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG,
|
||||
+ TWRR_RW_CMD_MASK |
|
||||
+ FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |
|
||||
+ FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |
|
||||
+ FIELD_PREP(TWRR_VALUE_MASK, weights[i]));
|
||||
+ err = read_poll_timeout(airoha_qdma_rr, status,
|
||||
+ status & TWRR_RW_CMD_DONE,
|
||||
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC,
|
||||
+ true, port->qdma,
|
||||
+ REG_TXWRR_WEIGHT_CFG);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3),
|
||||
+ CHAN_QOS_MODE_MASK(channel),
|
||||
+ mode << __ffs(CHAN_QOS_MODE_MASK(channel)));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_set_tx_prio_sched(struct airoha_gdm_port *port,
|
||||
+ int channel)
|
||||
+{
|
||||
+ static const u16 w[AIROHA_NUM_QOS_QUEUES] = {};
|
||||
+
|
||||
+ return airoha_qdma_set_chan_tx_sched(port, channel, TC_SCH_SP, w,
|
||||
+ ARRAY_SIZE(w));
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port,
|
||||
+ int channel,
|
||||
+ struct tc_ets_qopt_offload *opt)
|
||||
+{
|
||||
+ struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params;
|
||||
+ enum tx_sched_mode mode = TC_SCH_SP;
|
||||
+ u16 w[AIROHA_NUM_QOS_QUEUES] = {};
|
||||
+ int i, nstrict = 0;
|
||||
+
|
||||
+ if (p->bands > AIROHA_NUM_QOS_QUEUES)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (i = 0; i < p->bands; i++) {
|
||||
+ if (!p->quanta[i])
|
||||
+ nstrict++;
|
||||
+ }
|
||||
+
|
||||
+ /* this configuration is not supported by the hw */
|
||||
+ if (nstrict == AIROHA_NUM_QOS_QUEUES - 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for (i = 0; i < p->bands - nstrict; i++)
|
||||
+ w[i] = p->weights[nstrict + i];
|
||||
+
|
||||
+ if (!nstrict)
|
||||
+ mode = TC_SCH_WRR8;
|
||||
+ else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1)
|
||||
+ mode = nstrict + 1;
|
||||
+
|
||||
+ return airoha_qdma_set_chan_tx_sched(port, channel, mode, w,
|
||||
+ ARRAY_SIZE(w));
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port,
|
||||
+ int channel,
|
||||
+ struct tc_ets_qopt_offload *opt)
|
||||
+{
|
||||
+ u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
|
||||
+ REG_CNTR_VAL(channel << 1));
|
||||
+ u64 fwd_tx_packets = airoha_qdma_rr(port->qdma,
|
||||
+ REG_CNTR_VAL((channel << 1) + 1));
|
||||
+ u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) +
|
||||
+ (fwd_tx_packets - port->fwd_tx_packets);
|
||||
+ _bstats_update(opt->stats.bstats, 0, tx_packets);
|
||||
+
|
||||
+ port->cpu_tx_packets = cpu_tx_packets;
|
||||
+ port->fwd_tx_packets = fwd_tx_packets;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
|
||||
+ struct tc_ets_qopt_offload *opt)
|
||||
+{
|
||||
+ int channel = TC_H_MAJ(opt->handle) >> 16;
|
||||
+
|
||||
+ if (opt->parent == TC_H_ROOT)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ switch (opt->command) {
|
||||
+ case TC_ETS_REPLACE:
|
||||
+ return airoha_qdma_set_tx_ets_sched(port, channel, opt);
|
||||
+ case TC_ETS_DESTROY:
|
||||
+ /* PRIO is default qdisc scheduler */
|
||||
+ return airoha_qdma_set_tx_prio_sched(port, channel);
|
||||
+ case TC_ETS_STATS:
|
||||
+ return airoha_qdma_get_tx_ets_stats(port, channel, opt);
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
|
||||
+ void *type_data)
|
||||
+{
|
||||
+ struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case TC_SETUP_QDISC_ETS:
|
||||
+ return airoha_tc_setup_qdisc_ets(port, type_data);
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static const struct net_device_ops airoha_netdev_ops = {
|
||||
.ndo_init = airoha_dev_init,
|
||||
.ndo_open = airoha_dev_open,
|
||||
@@ -2639,6 +2831,7 @@ static const struct net_device_ops airoh
|
||||
.ndo_start_xmit = airoha_dev_xmit,
|
||||
.ndo_get_stats64 = airoha_dev_get_stats64,
|
||||
.ndo_set_mac_address = airoha_dev_set_macaddr,
|
||||
+ .ndo_setup_tc = airoha_dev_tc_setup,
|
||||
};
|
||||
|
||||
static const struct ethtool_ops airoha_ethtool_ops = {
|
||||
@@ -2688,7 +2881,8 @@ static int airoha_alloc_gdm_port(struct
|
||||
dev->watchdog_timeo = 5 * HZ;
|
||||
dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
|
||||
NETIF_F_TSO6 | NETIF_F_IPV6_CSUM |
|
||||
- NETIF_F_SG | NETIF_F_TSO;
|
||||
+ NETIF_F_SG | NETIF_F_TSO |
|
||||
+ NETIF_F_HW_TC;
|
||||
dev->features |= dev->hw_features;
|
||||
dev->dev.of_node = np;
|
||||
dev->irq = qdma->irq;
|
@@ -1,371 +0,0 @@
|
||||
From ef1ca9271313b4ea7b03de69576aacef1e78f381 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 3 Jan 2025 13:17:05 +0100
|
||||
Subject: [PATCH 4/4] net: airoha: Add sched HTB offload support
|
||||
|
||||
Introduce support for HTB Qdisc offload available in the Airoha EN7581
|
||||
ethernet controller. EN7581 can offload only one level of HTB leafs.
|
||||
Each HTB leaf represents a QoS channel supported by EN7581 SoC.
|
||||
The typical use-case is creating a HTB leaf for QoS channel to rate
|
||||
limit the egress traffic and attach an ETS Qdisc to each HTB leaf in
|
||||
order to enforce traffic prioritization.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 288 ++++++++++++++++++++-
|
||||
1 file changed, 287 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -28,6 +28,8 @@
|
||||
#define AIROHA_NUM_QOS_QUEUES 8
|
||||
#define AIROHA_NUM_TX_RING 32
|
||||
#define AIROHA_NUM_RX_RING 32
|
||||
+#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \
|
||||
+ AIROHA_NUM_QOS_CHANNELS)
|
||||
#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
|
||||
#define AIROHA_FE_MC_MAX_VLAN_PORT 16
|
||||
#define AIROHA_NUM_TX_IRQ 2
|
||||
@@ -43,6 +45,9 @@
|
||||
#define PSE_RSV_PAGES 128
|
||||
#define PSE_QUEUE_RSV_PAGES 64
|
||||
|
||||
+#define QDMA_METER_IDX(_n) ((_n) & 0xff)
|
||||
+#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3)
|
||||
+
|
||||
/* FE */
|
||||
#define PSE_BASE 0x0100
|
||||
#define CSR_IFC_BASE 0x0200
|
||||
@@ -583,6 +588,17 @@
|
||||
#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16)
|
||||
#define EGRESS_FAST_TICK_MASK GENMASK(15, 0)
|
||||
|
||||
+#define TRTCM_PARAM_RW_MASK BIT(31)
|
||||
+#define TRTCM_PARAM_RW_DONE_MASK BIT(30)
|
||||
+#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28)
|
||||
+#define TRTCM_METER_GROUP_MASK GENMASK(27, 26)
|
||||
+#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17)
|
||||
+#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16)
|
||||
+
|
||||
+#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4)
|
||||
+#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8)
|
||||
+#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc)
|
||||
+
|
||||
#define REG_TXWRR_MODE_CFG 0x1020
|
||||
#define TWRR_WEIGHT_SCALE_MASK BIT(31)
|
||||
#define TWRR_WEIGHT_BASE_MASK BIT(3)
|
||||
@@ -759,6 +775,29 @@ enum tx_sched_mode {
|
||||
TC_SCH_WRR2,
|
||||
};
|
||||
|
||||
+enum trtcm_param_type {
|
||||
+ TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */
|
||||
+ TRTCM_TOKEN_RATE_MODE,
|
||||
+ TRTCM_BUCKETSIZE_SHIFT_MODE,
|
||||
+ TRTCM_BUCKET_COUNTER_MODE,
|
||||
+};
|
||||
+
|
||||
+enum trtcm_mode_type {
|
||||
+ TRTCM_COMMIT_MODE,
|
||||
+ TRTCM_PEAK_MODE,
|
||||
+};
|
||||
+
|
||||
+enum trtcm_param {
|
||||
+ TRTCM_TICK_SEL = BIT(0),
|
||||
+ TRTCM_PKT_MODE = BIT(1),
|
||||
+ TRTCM_METER_MODE = BIT(2),
|
||||
+};
|
||||
+
|
||||
+#define MIN_TOKEN_SIZE 4096
|
||||
+#define MAX_TOKEN_SIZE_OFFSET 17
|
||||
+#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
|
||||
+#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
|
||||
+
|
||||
struct airoha_queue_entry {
|
||||
union {
|
||||
void *buf;
|
||||
@@ -850,6 +889,8 @@ struct airoha_gdm_port {
|
||||
|
||||
struct airoha_hw_stats stats;
|
||||
|
||||
+ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
|
||||
+
|
||||
/* qos stats counters */
|
||||
u64 cpu_tx_packets;
|
||||
u64 fwd_tx_packets;
|
||||
@@ -2810,6 +2851,243 @@ static int airoha_tc_setup_qdisc_ets(str
|
||||
}
|
||||
}
|
||||
|
||||
+static int airoha_qdma_get_trtcm_param(struct airoha_qdma *qdma, int channel,
|
||||
+ u32 addr, enum trtcm_param_type param,
|
||||
+ enum trtcm_mode_type mode,
|
||||
+ u32 *val_low, u32 *val_high)
|
||||
+{
|
||||
+ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel);
|
||||
+ u32 val, config = FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) |
|
||||
+ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
|
||||
+ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
|
||||
+ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
|
||||
+
|
||||
+ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
|
||||
+ if (read_poll_timeout(airoha_qdma_rr, val,
|
||||
+ val & TRTCM_PARAM_RW_DONE_MASK,
|
||||
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
|
||||
+ qdma, REG_TRTCM_CFG_PARAM(addr)))
|
||||
+ return -ETIMEDOUT;
|
||||
+
|
||||
+ *val_low = airoha_qdma_rr(qdma, REG_TRTCM_DATA_LOW(addr));
|
||||
+ if (val_high)
|
||||
+ *val_high = airoha_qdma_rr(qdma, REG_TRTCM_DATA_HIGH(addr));
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel,
|
||||
+ u32 addr, enum trtcm_param_type param,
|
||||
+ enum trtcm_mode_type mode, u32 val)
|
||||
+{
|
||||
+ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel);
|
||||
+ u32 config = TRTCM_PARAM_RW_MASK |
|
||||
+ FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) |
|
||||
+ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
|
||||
+ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
|
||||
+ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
|
||||
+
|
||||
+ airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
|
||||
+ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
|
||||
+
|
||||
+ return read_poll_timeout(airoha_qdma_rr, val,
|
||||
+ val & TRTCM_PARAM_RW_DONE_MASK,
|
||||
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
|
||||
+ qdma, REG_TRTCM_CFG_PARAM(addr));
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel,
|
||||
+ u32 addr, enum trtcm_mode_type mode,
|
||||
+ bool enable, u32 enable_mask)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
|
||||
+ mode, &val, NULL))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ val = enable ? val | enable_mask : val & ~enable_mask;
|
||||
+
|
||||
+ return airoha_qdma_set_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
|
||||
+ mode, val);
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma,
|
||||
+ int channel, u32 addr,
|
||||
+ enum trtcm_mode_type mode,
|
||||
+ u32 rate_val, u32 bucket_size)
|
||||
+{
|
||||
+ u32 val, config, tick, unit, rate, rate_frac;
|
||||
+ int err;
|
||||
+
|
||||
+ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
|
||||
+ mode, &config, NULL))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ val = airoha_qdma_rr(qdma, addr);
|
||||
+ tick = FIELD_GET(INGRESS_FAST_TICK_MASK, val);
|
||||
+ if (config & TRTCM_TICK_SEL)
|
||||
+ tick *= FIELD_GET(INGRESS_SLOW_TICK_RATIO_MASK, val);
|
||||
+ if (!tick)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ unit = (config & TRTCM_PKT_MODE) ? 1000000 / tick : 8000 / tick;
|
||||
+ if (!unit)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ rate = rate_val / unit;
|
||||
+ rate_frac = rate_val % unit;
|
||||
+ rate_frac = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate_frac) / unit;
|
||||
+ rate = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate) |
|
||||
+ FIELD_PREP(TRTCM_TOKEN_RATE_FRACTION_MASK, rate_frac);
|
||||
+
|
||||
+ err = airoha_qdma_set_trtcm_param(qdma, channel, addr,
|
||||
+ TRTCM_TOKEN_RATE_MODE, mode, rate);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ val = max_t(u32, bucket_size, MIN_TOKEN_SIZE);
|
||||
+ val = min_t(u32, __fls(val), MAX_TOKEN_SIZE_OFFSET);
|
||||
+
|
||||
+ return airoha_qdma_set_trtcm_param(qdma, channel, addr,
|
||||
+ TRTCM_BUCKETSIZE_SHIFT_MODE,
|
||||
+ mode, val);
|
||||
+}
|
||||
+
|
||||
+static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port,
|
||||
+ int channel, u32 rate,
|
||||
+ u32 bucket_size)
|
||||
+{
|
||||
+ int i, err;
|
||||
+
|
||||
+ for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
|
||||
+ err = airoha_qdma_set_trtcm_config(port->qdma, channel,
|
||||
+ REG_EGRESS_TRTCM_CFG, i,
|
||||
+ !!rate, TRTCM_METER_MODE);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel,
|
||||
+ REG_EGRESS_TRTCM_CFG,
|
||||
+ i, rate, bucket_size);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port,
|
||||
+ struct tc_htb_qopt_offload *opt)
|
||||
+{
|
||||
+ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
|
||||
+ u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */
|
||||
+ struct net_device *dev = port->dev;
|
||||
+ int num_tx_queues = dev->real_num_tx_queues;
|
||||
+ int err;
|
||||
+
|
||||
+ if (opt->parent_classid != TC_HTB_CLASSID_ROOT) {
|
||||
+ NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum);
|
||||
+ if (err) {
|
||||
+ NL_SET_ERR_MSG_MOD(opt->extack,
|
||||
+ "failed configuring htb offload");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (opt->command == TC_HTB_NODE_MODIFY)
|
||||
+ return 0;
|
||||
+
|
||||
+ err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1);
|
||||
+ if (err) {
|
||||
+ airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum);
|
||||
+ NL_SET_ERR_MSG_MOD(opt->extack,
|
||||
+ "failed setting real_num_tx_queues");
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ set_bit(channel, port->qos_sq_bmap);
|
||||
+ opt->qid = AIROHA_NUM_TX_RING + channel;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue)
|
||||
+{
|
||||
+ struct net_device *dev = port->dev;
|
||||
+
|
||||
+ netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1);
|
||||
+ airoha_qdma_set_tx_rate_limit(port, queue + 1, 0, 0);
|
||||
+ clear_bit(queue, port->qos_sq_bmap);
|
||||
+}
|
||||
+
|
||||
+static int airoha_tc_htb_delete_leaf_queue(struct airoha_gdm_port *port,
|
||||
+ struct tc_htb_qopt_offload *opt)
|
||||
+{
|
||||
+ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
|
||||
+
|
||||
+ if (!test_bit(channel, port->qos_sq_bmap)) {
|
||||
+ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ airoha_tc_remove_htb_queue(port, channel);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_tc_htb_destroy(struct airoha_gdm_port *port)
|
||||
+{
|
||||
+ int q;
|
||||
+
|
||||
+ for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
|
||||
+ airoha_tc_remove_htb_queue(port, q);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port,
|
||||
+ struct tc_htb_qopt_offload *opt)
|
||||
+{
|
||||
+ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
|
||||
+
|
||||
+ if (!test_bit(channel, port->qos_sq_bmap)) {
|
||||
+ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ opt->qid = channel;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_tc_setup_qdisc_htb(struct airoha_gdm_port *port,
|
||||
+ struct tc_htb_qopt_offload *opt)
|
||||
+{
|
||||
+ switch (opt->command) {
|
||||
+ case TC_HTB_CREATE:
|
||||
+ break;
|
||||
+ case TC_HTB_DESTROY:
|
||||
+ return airoha_tc_htb_destroy(port);
|
||||
+ case TC_HTB_NODE_MODIFY:
|
||||
+ case TC_HTB_LEAF_ALLOC_QUEUE:
|
||||
+ return airoha_tc_htb_alloc_leaf_queue(port, opt);
|
||||
+ case TC_HTB_LEAF_DEL:
|
||||
+ case TC_HTB_LEAF_DEL_LAST:
|
||||
+ case TC_HTB_LEAF_DEL_LAST_FORCE:
|
||||
+ return airoha_tc_htb_delete_leaf_queue(port, opt);
|
||||
+ case TC_HTB_LEAF_QUERY_QUEUE:
|
||||
+ return airoha_tc_get_htb_get_leaf_queue(port, opt);
|
||||
+ default:
|
||||
+ return -EOPNOTSUPP;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
|
||||
void *type_data)
|
||||
{
|
||||
@@ -2818,6 +3096,8 @@ static int airoha_dev_tc_setup(struct ne
|
||||
switch (type) {
|
||||
case TC_SETUP_QDISC_ETS:
|
||||
return airoha_tc_setup_qdisc_ets(port, type_data);
|
||||
+ case TC_SETUP_QDISC_HTB:
|
||||
+ return airoha_tc_setup_qdisc_htb(port, type_data);
|
||||
default:
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
@@ -2868,7 +3148,8 @@ static int airoha_alloc_gdm_port(struct
|
||||
}
|
||||
|
||||
dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port),
|
||||
- AIROHA_NUM_TX_RING, AIROHA_NUM_RX_RING);
|
||||
+ AIROHA_NUM_NETDEV_TX_RINGS,
|
||||
+ AIROHA_NUM_RX_RING);
|
||||
if (!dev) {
|
||||
dev_err(eth->dev, "alloc_etherdev failed\n");
|
||||
return -ENOMEM;
|
||||
@@ -2888,6 +3169,11 @@ static int airoha_alloc_gdm_port(struct
|
||||
dev->irq = qdma->irq;
|
||||
SET_NETDEV_DEV(dev, eth->dev);
|
||||
|
||||
+ /* reserve hw queues for HTB offloading */
|
||||
+ err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
err = of_get_ethdev_address(np, dev);
|
||||
if (err) {
|
||||
if (err == -EPROBE_DEFER)
|
@@ -1,232 +0,0 @@
|
||||
From 84cf9e541cccb8cb698518a9897942e8c78f1d83 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 9 Jan 2025 14:12:58 +0100
|
||||
Subject: [PATCH] cpufreq: airoha: Add EN7581 CPUFreq SMCCC driver
|
||||
|
||||
Add simple CPU Freq driver for Airoha EN7581 SoC that control CPU
|
||||
frequency scaling with SMC APIs and register a generic "cpufreq-dt"
|
||||
device.
|
||||
|
||||
All CPU share the same frequency and can't be controlled independently.
|
||||
CPU frequency is controlled by the attached PM domain.
|
||||
|
||||
Add SoC compatible to cpufreq-dt-plat block list as a dedicated cpufreq
|
||||
driver is needed with OPP v2 nodes declared in DTS.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
|
||||
---
|
||||
drivers/cpufreq/Kconfig.arm | 8 ++
|
||||
drivers/cpufreq/Makefile | 1 +
|
||||
drivers/cpufreq/airoha-cpufreq.c | 152 +++++++++++++++++++++++++++
|
||||
drivers/cpufreq/cpufreq-dt-platdev.c | 2 +
|
||||
4 files changed, 163 insertions(+)
|
||||
create mode 100644 drivers/cpufreq/airoha-cpufreq.c
|
||||
|
||||
--- a/drivers/cpufreq/Kconfig.arm
|
||||
+++ b/drivers/cpufreq/Kconfig.arm
|
||||
@@ -41,6 +41,14 @@ config ARM_ALLWINNER_SUN50I_CPUFREQ_NVME
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called sun50i-cpufreq-nvmem.
|
||||
|
||||
+config ARM_AIROHA_SOC_CPUFREQ
|
||||
+ tristate "Airoha EN7581 SoC CPUFreq support"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ select PM_OPP
|
||||
+ default ARCH_AIROHA
|
||||
+ help
|
||||
+ This adds the CPUFreq driver for Airoha EN7581 SoCs.
|
||||
+
|
||||
config ARM_APPLE_SOC_CPUFREQ
|
||||
tristate "Apple Silicon SoC CPUFreq support"
|
||||
depends on ARCH_APPLE || (COMPILE_TEST && 64BIT)
|
||||
--- a/drivers/cpufreq/Makefile
|
||||
+++ b/drivers/cpufreq/Makefile
|
||||
@@ -52,6 +52,7 @@ obj-$(CONFIG_X86_AMD_FREQ_SENSITIVITY) +
|
||||
|
||||
##################################################################################
|
||||
# ARM SoC drivers
|
||||
+obj-$(CONFIG_ARM_AIROHA_SOC_CPUFREQ) += airoha-cpufreq.o
|
||||
obj-$(CONFIG_ARM_APPLE_SOC_CPUFREQ) += apple-soc-cpufreq.o
|
||||
obj-$(CONFIG_ARM_ARMADA_37XX_CPUFREQ) += armada-37xx-cpufreq.o
|
||||
obj-$(CONFIG_ARM_ARMADA_8K_CPUFREQ) += armada-8k-cpufreq.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/cpufreq/airoha-cpufreq.c
|
||||
@@ -0,0 +1,166 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#include "cpufreq-dt.h"
|
||||
+
|
||||
+struct airoha_cpufreq_priv {
|
||||
+ int opp_token;
|
||||
+ struct device **virt_devs;
|
||||
+ struct platform_device *cpufreq_dt;
|
||||
+};
|
||||
+
|
||||
+static struct platform_device *cpufreq_pdev;
|
||||
+
|
||||
+/* NOP function to disable OPP from setting clock */
|
||||
+static int airoha_cpufreq_config_clks_nop(struct device *dev,
|
||||
+ struct opp_table *opp_table,
|
||||
+ struct dev_pm_opp *old_opp,
|
||||
+ struct dev_pm_opp *opp,
|
||||
+ void *data, bool scaling_down)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const char * const airoha_cpufreq_clk_names[] = { "cpu", NULL };
|
||||
+static const char * const airoha_cpufreq_pd_names[] = { "perf", NULL };
|
||||
+
|
||||
+static int airoha_cpufreq_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct dev_pm_opp_config config = {
|
||||
+ .clk_names = airoha_cpufreq_clk_names,
|
||||
+ .config_clks = airoha_cpufreq_config_clks_nop,
|
||||
+ .genpd_names = airoha_cpufreq_pd_names,
|
||||
+ };
|
||||
+ struct platform_device *cpufreq_dt;
|
||||
+ struct airoha_cpufreq_priv *priv;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct device **virt_devs = NULL;
|
||||
+ struct device *cpu_dev;
|
||||
+ int ret;
|
||||
+
|
||||
+ /* CPUs refer to the same OPP table */
|
||||
+ cpu_dev = get_cpu_device(0);
|
||||
+ if (!cpu_dev)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* Set OPP table conf with NOP config_clks */
|
||||
+ priv->opp_token = dev_pm_opp_set_config(cpu_dev, &config);
|
||||
+ if (priv->opp_token < 0)
|
||||
+ return dev_err_probe(dev, priv->opp_token, "Failed to set OPP config\n");
|
||||
+
|
||||
+ /* Set Attached PM for OPP ACTIVE */
|
||||
+ if (virt_devs) {
|
||||
+ const char * const *name = airoha_cpufreq_pd_names;
|
||||
+ int i, j;
|
||||
+
|
||||
+ for (i = 0; *name; i++, name++) {
|
||||
+ ret = pm_runtime_resume_and_get(virt_devs[i]);
|
||||
+ if (ret) {
|
||||
+ dev_err(cpu_dev, "failed to resume %s: %d\n",
|
||||
+ *name, ret);
|
||||
+
|
||||
+ /* Rollback previous PM runtime calls */
|
||||
+ name = config.genpd_names;
|
||||
+ for (j = 0; *name && j < i; j++, name++)
|
||||
+ pm_runtime_put(virt_devs[j]);
|
||||
+
|
||||
+ goto err_register_cpufreq;
|
||||
+ }
|
||||
+ }
|
||||
+ priv->virt_devs = virt_devs;
|
||||
+ }
|
||||
+
|
||||
+ cpufreq_dt = platform_device_register_simple("cpufreq-dt", -1, NULL, 0);
|
||||
+ ret = PTR_ERR_OR_ZERO(cpufreq_dt);
|
||||
+ if (ret) {
|
||||
+ dev_err(dev, "failed to create cpufreq-dt device: %d\n", ret);
|
||||
+ goto err_register_cpufreq;
|
||||
+ }
|
||||
+
|
||||
+ priv->cpufreq_dt = cpufreq_dt;
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_register_cpufreq:
|
||||
+ dev_pm_opp_clear_config(priv->opp_token);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void airoha_cpufreq_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct airoha_cpufreq_priv *priv = platform_get_drvdata(pdev);
|
||||
+ const char * const *name = airoha_cpufreq_pd_names;
|
||||
+ int i;
|
||||
+
|
||||
+ platform_device_unregister(priv->cpufreq_dt);
|
||||
+
|
||||
+ dev_pm_opp_clear_config(priv->opp_token);
|
||||
+
|
||||
+ for (i = 0; *name; i++, name++)
|
||||
+ pm_runtime_put(priv->virt_devs[i]);
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver airoha_cpufreq_driver = {
|
||||
+ .probe = airoha_cpufreq_probe,
|
||||
+ .remove_new = airoha_cpufreq_remove,
|
||||
+ .driver = {
|
||||
+ .name = "airoha-cpufreq",
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static const struct of_device_id airoha_cpufreq_match_list[] __initconst = {
|
||||
+ { .compatible = "airoha,en7581" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_cpufreq_match_list);
|
||||
+
|
||||
+static int __init airoha_cpufreq_init(void)
|
||||
+{
|
||||
+ struct device_node *np = of_find_node_by_path("/");
|
||||
+ const struct of_device_id *match;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ match = of_match_node(airoha_cpufreq_match_list, np);
|
||||
+ of_node_put(np);
|
||||
+ if (!match)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ret = platform_driver_register(&airoha_cpufreq_driver);
|
||||
+ if (unlikely(ret < 0))
|
||||
+ return ret;
|
||||
+
|
||||
+ cpufreq_pdev = platform_device_register_data(NULL, "airoha-cpufreq",
|
||||
+ -1, match, sizeof(*match));
|
||||
+ ret = PTR_ERR_OR_ZERO(cpufreq_pdev);
|
||||
+ if (ret)
|
||||
+ platform_driver_unregister(&airoha_cpufreq_driver);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+module_init(airoha_cpufreq_init);
|
||||
+
|
||||
+static void __exit airoha_cpufreq_exit(void)
|
||||
+{
|
||||
+ platform_device_unregister(cpufreq_pdev);
|
||||
+ platform_driver_unregister(&airoha_cpufreq_driver);
|
||||
+}
|
||||
+module_exit(airoha_cpufreq_exit);
|
||||
+
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("CPUfreq driver for Airoha SoCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- a/drivers/cpufreq/cpufreq-dt-platdev.c
|
||||
+++ b/drivers/cpufreq/cpufreq-dt-platdev.c
|
||||
@@ -103,6 +103,8 @@ static const struct of_device_id allowli
|
||||
* platforms using "operating-points-v2" property.
|
||||
*/
|
||||
static const struct of_device_id blocklist[] __initconst = {
|
||||
+ { .compatible = "airoha,en7581", },
|
||||
+
|
||||
{ .compatible = "allwinner,sun50i-h6", },
|
||||
|
||||
{ .compatible = "apple,arm-platform", },
|
@@ -1,53 +0,0 @@
|
||||
From b56e4d660a9688ff83f5cbdc6e3ea063352d0d79 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sun, 12 Jan 2025 19:32:45 +0100
|
||||
Subject: [PATCH] net: airoha: Enforce ETS Qdisc priomap
|
||||
|
||||
EN7581 SoC supports fixed QoS band priority where WRR queues have lowest
|
||||
priorities with respect to SP ones.
|
||||
E.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn
|
||||
|
||||
Enforce ETS Qdisc priomap according to the hw capabilities.
|
||||
|
||||
Suggested-by: Davide Caratti <dcaratti@redhat.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Davide Caratti <dcaratti@redhat.com>
|
||||
Link: https://patch.msgid.link/20250112-airoha_ets_priomap-v1-1-fb616de159ba@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 17 +++++++++++++++--
|
||||
1 file changed, 15 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2786,7 +2786,7 @@ static int airoha_qdma_set_tx_ets_sched(
|
||||
struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params;
|
||||
enum tx_sched_mode mode = TC_SCH_SP;
|
||||
u16 w[AIROHA_NUM_QOS_QUEUES] = {};
|
||||
- int i, nstrict = 0;
|
||||
+ int i, nstrict = 0, nwrr, qidx;
|
||||
|
||||
if (p->bands > AIROHA_NUM_QOS_QUEUES)
|
||||
return -EINVAL;
|
||||
@@ -2800,7 +2800,20 @@ static int airoha_qdma_set_tx_ets_sched(
|
||||
if (nstrict == AIROHA_NUM_QOS_QUEUES - 1)
|
||||
return -EINVAL;
|
||||
|
||||
- for (i = 0; i < p->bands - nstrict; i++)
|
||||
+ /* EN7581 SoC supports fixed QoS band priority where WRR queues have
|
||||
+ * lowest priorities with respect to SP ones.
|
||||
+ * e.g: WRR0, WRR1, .., WRRm, SP0, SP1, .., SPn
|
||||
+ */
|
||||
+ nwrr = p->bands - nstrict;
|
||||
+ qidx = nstrict && nwrr ? nstrict : 0;
|
||||
+ for (i = 1; i <= p->bands; i++) {
|
||||
+ if (p->priomap[i % AIROHA_NUM_QOS_QUEUES] != qidx)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ qidx = i == nwrr ? 0 : qidx + 1;
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < nwrr; i++)
|
||||
w[i] = p->weights[nstrict + i];
|
||||
|
||||
if (!nstrict)
|
@@ -1,196 +0,0 @@
|
||||
From 82e703dd438b71432cc0ccbb90925d1e32dd014a Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 9 Jan 2025 14:12:57 +0100
|
||||
Subject: [PATCH] pmdomain: airoha: Add Airoha CPU PM Domain support
|
||||
|
||||
Add Airoha CPU PM Domain support to control frequency and power of CPU
|
||||
present on Airoha EN7581 SoC.
|
||||
|
||||
Frequency and power can be controlled with the use of the SMC command by
|
||||
passing the performance state. The driver also expose a read-only clock
|
||||
that expose the current CPU frequency with SMC command.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20250109131313.32317-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
|
||||
---
|
||||
drivers/pmdomain/mediatek/Kconfig | 12 ++
|
||||
drivers/pmdomain/mediatek/Makefile | 1 +
|
||||
.../pmdomain/mediatek/airoha-cpu-pmdomain.c | 144 ++++++++++++++++++
|
||||
3 files changed, 157 insertions(+)
|
||||
create mode 100644 drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
|
||||
|
||||
--- a/drivers/soc/mediatek/Kconfig
|
||||
+++ b/drivers/soc/mediatek/Kconfig
|
||||
@@ -2,6 +2,17 @@
|
||||
#
|
||||
# MediaTek SoC drivers
|
||||
#
|
||||
+config AIROHA_CPU_PM_DOMAIN
|
||||
+ tristate "Airoha CPU power domain"
|
||||
+ default ARCH_AIROHA
|
||||
+ depends on PM
|
||||
+ select PM_GENERIC_DOMAINS
|
||||
+ help
|
||||
+ Say y here to enable CPU power domain support for Airoha SoC.
|
||||
+
|
||||
+ CPU frequency and power is controlled by ATF with SMC command to
|
||||
+ set performance states.
|
||||
+
|
||||
menu "MediaTek SoC drivers"
|
||||
depends on ARCH_MEDIATEK || COMPILE_TEST
|
||||
|
||||
--- a/drivers/pmdomain/mediatek/Makefile
|
||||
+++ b/drivers/pmdomain/mediatek/Makefile
|
||||
@@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
|
||||
obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
|
||||
+obj-$(CONFIG_AIROHA_CPU_PM_DOMAIN) += airoha-cpu-pmdomain.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/pmdomain/mediatek/airoha-cpu-pmdomain.c
|
||||
@@ -0,0 +1,144 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0
|
||||
+
|
||||
+#include <linux/arm-smccc.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/clk-provider.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/pm_domain.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+#define AIROHA_SIP_AVS_HANDLE 0x82000301
|
||||
+#define AIROHA_AVS_OP_BASE 0xddddddd0
|
||||
+#define AIROHA_AVS_OP_MASK GENMASK(1, 0)
|
||||
+#define AIROHA_AVS_OP_FREQ_DYN_ADJ (AIROHA_AVS_OP_BASE | \
|
||||
+ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x1))
|
||||
+#define AIROHA_AVS_OP_GET_FREQ (AIROHA_AVS_OP_BASE | \
|
||||
+ FIELD_PREP(AIROHA_AVS_OP_MASK, 0x2))
|
||||
+
|
||||
+struct airoha_cpu_pmdomain_priv {
|
||||
+ struct clk_hw hw;
|
||||
+ struct generic_pm_domain pd;
|
||||
+};
|
||||
+
|
||||
+static long airoha_cpu_pmdomain_clk_round(struct clk_hw *hw, unsigned long rate,
|
||||
+ unsigned long *parent_rate)
|
||||
+{
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static unsigned long airoha_cpu_pmdomain_clk_get(struct clk_hw *hw,
|
||||
+ unsigned long parent_rate)
|
||||
+{
|
||||
+ struct arm_smccc_res res;
|
||||
+
|
||||
+ arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_GET_FREQ,
|
||||
+ 0, 0, 0, 0, 0, 0, &res);
|
||||
+
|
||||
+ /* SMCCC returns freq in MHz */
|
||||
+ return (int)(res.a0 * 1000 * 1000);
|
||||
+}
|
||||
+
|
||||
+/* Airoha CPU clk SMCC is always enabled */
|
||||
+static int airoha_cpu_pmdomain_clk_is_enabled(struct clk_hw *hw)
|
||||
+{
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+static const struct clk_ops airoha_cpu_pmdomain_clk_ops = {
|
||||
+ .recalc_rate = airoha_cpu_pmdomain_clk_get,
|
||||
+ .is_enabled = airoha_cpu_pmdomain_clk_is_enabled,
|
||||
+ .round_rate = airoha_cpu_pmdomain_clk_round,
|
||||
+};
|
||||
+
|
||||
+static int airoha_cpu_pmdomain_set_performance_state(struct generic_pm_domain *domain,
|
||||
+ unsigned int state)
|
||||
+{
|
||||
+ struct arm_smccc_res res;
|
||||
+
|
||||
+ arm_smccc_1_1_invoke(AIROHA_SIP_AVS_HANDLE, AIROHA_AVS_OP_FREQ_DYN_ADJ,
|
||||
+ 0, state, 0, 0, 0, 0, &res);
|
||||
+
|
||||
+ /* SMC signal correct apply by unsetting BIT 0 */
|
||||
+ return res.a0 & BIT(0) ? -EINVAL : 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_cpu_pmdomain_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct airoha_cpu_pmdomain_priv *priv;
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ const struct clk_init_data init = {
|
||||
+ .name = "cpu",
|
||||
+ .ops = &airoha_cpu_pmdomain_clk_ops,
|
||||
+ /* Clock with no set_rate, can't cache */
|
||||
+ .flags = CLK_GET_RATE_NOCACHE,
|
||||
+ };
|
||||
+ struct generic_pm_domain *pd;
|
||||
+ int ret;
|
||||
+
|
||||
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ /* Init and register a get-only clk for Cpufreq */
|
||||
+ priv->hw.init = &init;
|
||||
+ ret = devm_clk_hw_register(dev, &priv->hw);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get,
|
||||
+ &priv->hw);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Init and register a PD for CPU */
|
||||
+ pd = &priv->pd;
|
||||
+ pd->name = "cpu_pd";
|
||||
+ pd->flags = GENPD_FLAG_ALWAYS_ON;
|
||||
+ pd->set_performance_state = airoha_cpu_pmdomain_set_performance_state;
|
||||
+
|
||||
+ ret = pm_genpd_init(pd, NULL, false);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = of_genpd_add_provider_simple(dev->of_node, pd);
|
||||
+ if (ret)
|
||||
+ goto err_add_provider;
|
||||
+
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+err_add_provider:
|
||||
+ pm_genpd_remove(pd);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static void airoha_cpu_pmdomain_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct airoha_cpu_pmdomain_priv *priv = platform_get_drvdata(pdev);
|
||||
+
|
||||
+ of_genpd_del_provider(pdev->dev.of_node);
|
||||
+ pm_genpd_remove(&priv->pd);
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_cpu_pmdomain_of_match[] = {
|
||||
+ { .compatible = "airoha,en7581-cpufreq" },
|
||||
+ { },
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_cpu_pmdomain_of_match);
|
||||
+
|
||||
+static struct platform_driver airoha_cpu_pmdomain_driver = {
|
||||
+ .probe = airoha_cpu_pmdomain_probe,
|
||||
+ .remove_new = airoha_cpu_pmdomain_remove,
|
||||
+ .driver = {
|
||||
+ .name = "airoha-cpu-pmdomain",
|
||||
+ .of_match_table = airoha_cpu_pmdomain_of_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(airoha_cpu_pmdomain_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("CPU PM domain driver for Airoha SoCs");
|
||||
+MODULE_LICENSE("GPL");
|
@@ -1,83 +0,0 @@
|
||||
From e4a9748e7103c47e575459db2b6a77d14f34da2b Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 14 Jan 2025 00:10:02 +0100
|
||||
Subject: [PATCH 1/4] clk: en7523: Rework clock handling for different clock
|
||||
numbers
|
||||
|
||||
Airoha EN7581 SoC have additional clock compared to EN7523 but current
|
||||
driver permits to only support up to EN7523 clock numbers.
|
||||
|
||||
To handle this, rework the clock handling and permit to declare the
|
||||
clocks number in match_data and alloca clk_data based on the compatible
|
||||
match_data.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20250113231030.6735-2-ansuelsmth@gmail.com
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 14 ++++++++------
|
||||
1 file changed, 8 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -75,6 +75,7 @@ struct en_rst_data {
|
||||
};
|
||||
|
||||
struct en_clk_soc_data {
|
||||
+ u32 num_clocks;
|
||||
const struct clk_ops pcie_ops;
|
||||
int (*hw_init)(struct platform_device *pdev,
|
||||
struct clk_hw_onecell_data *clk_data);
|
||||
@@ -504,8 +505,6 @@ static void en7523_register_clocks(struc
|
||||
u32 rate;
|
||||
int i;
|
||||
|
||||
- clk_data->num = EN7523_NUM_CLOCKS;
|
||||
-
|
||||
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;
|
||||
@@ -587,8 +586,6 @@ static void en7581_register_clocks(struc
|
||||
|
||||
hw = en7523_register_pcie_clk(dev, base);
|
||||
clk_data->hws[EN7523_CLK_PCIE] = hw;
|
||||
-
|
||||
- clk_data->num = EN7523_NUM_CLOCKS;
|
||||
}
|
||||
|
||||
static int en7523_reset_update(struct reset_controller_dev *rcdev,
|
||||
@@ -702,13 +699,15 @@ static int en7523_clk_probe(struct platf
|
||||
struct clk_hw_onecell_data *clk_data;
|
||||
int r;
|
||||
|
||||
+ soc_data = device_get_match_data(&pdev->dev);
|
||||
+
|
||||
clk_data = devm_kzalloc(&pdev->dev,
|
||||
- struct_size(clk_data, hws, EN7523_NUM_CLOCKS),
|
||||
+ struct_size(clk_data, hws, soc_data->num_clocks),
|
||||
GFP_KERNEL);
|
||||
if (!clk_data)
|
||||
return -ENOMEM;
|
||||
|
||||
- soc_data = device_get_match_data(&pdev->dev);
|
||||
+ clk_data->num = soc_data->num_clocks;
|
||||
r = soc_data->hw_init(pdev, clk_data);
|
||||
if (r)
|
||||
return r;
|
||||
@@ -717,6 +716,7 @@ static int en7523_clk_probe(struct platf
|
||||
}
|
||||
|
||||
static const struct en_clk_soc_data en7523_data = {
|
||||
+ .num_clocks = ARRAY_SIZE(en7523_base_clks) + 1,
|
||||
.pcie_ops = {
|
||||
.is_enabled = en7523_pci_is_enabled,
|
||||
.prepare = en7523_pci_prepare,
|
||||
@@ -726,6 +726,8 @@ static const struct en_clk_soc_data en75
|
||||
};
|
||||
|
||||
static const struct en_clk_soc_data en7581_data = {
|
||||
+ /* We increment num_clocks by 1 to account for additional PCIe clock */
|
||||
+ .num_clocks = ARRAY_SIZE(en7581_base_clks) + 1,
|
||||
.pcie_ops = {
|
||||
.is_enabled = en7581_pci_is_enabled,
|
||||
.enable = en7581_pci_enable,
|
@@ -1,26 +0,0 @@
|
||||
From 02d3b7557ce28c373ea1e925ae16ab5988284313 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 14 Jan 2025 00:10:03 +0100
|
||||
Subject: [PATCH 2/4] dt-bindings: clock: drop NUM_CLOCKS define for EN7581
|
||||
|
||||
Drop NUM_CLOCKS define for EN7581 include. This is not a binding and
|
||||
should not be placed here. Value is derived internally in the user
|
||||
driver.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Acked-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||
Link: https://lore.kernel.org/r/20250113231030.6735-3-ansuelsmth@gmail.com
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
include/dt-bindings/clock/en7523-clk.h | 2 --
|
||||
1 file changed, 2 deletions(-)
|
||||
|
||||
--- a/include/dt-bindings/clock/en7523-clk.h
|
||||
+++ b/include/dt-bindings/clock/en7523-clk.h
|
||||
@@ -12,6 +12,4 @@
|
||||
#define EN7523_CLK_CRYPTO 6
|
||||
#define EN7523_CLK_PCIE 7
|
||||
|
||||
-#define EN7523_NUM_CLOCKS 8
|
||||
-
|
||||
#endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */
|
@@ -1,25 +0,0 @@
|
||||
From 82108ad3285f58f314ad41398f44017c7dbe44de Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 14 Jan 2025 00:10:04 +0100
|
||||
Subject: [PATCH 3/4] dt-bindings: clock: add ID for eMMC for EN7581
|
||||
|
||||
Add ID for eMMC for EN7581. This is to control clock selection of eMMC
|
||||
between 200MHz and 150MHz.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Acked-by: Conor Dooley <conor.dooley@microchip.com>
|
||||
Link: https://lore.kernel.org/r/20250113231030.6735-4-ansuelsmth@gmail.com
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
include/dt-bindings/clock/en7523-clk.h | 2 ++
|
||||
1 file changed, 2 insertions(+)
|
||||
|
||||
--- a/include/dt-bindings/clock/en7523-clk.h
|
||||
+++ b/include/dt-bindings/clock/en7523-clk.h
|
||||
@@ -12,4 +12,6 @@
|
||||
#define EN7523_CLK_CRYPTO 6
|
||||
#define EN7523_CLK_PCIE 7
|
||||
|
||||
+#define EN7581_CLK_EMMC 8
|
||||
+
|
||||
#endif /* _DT_BINDINGS_CLOCK_AIROHA_EN7523_H_ */
|
@@ -1,41 +0,0 @@
|
||||
From bfe257f9780d8f77045a7da6ec959ee0659d2f98 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 14 Jan 2025 00:10:05 +0100
|
||||
Subject: [PATCH 4/4] clk: en7523: Add clock for eMMC for EN7581
|
||||
|
||||
Add clock for eMMC for EN7581. This is used to give info of the current
|
||||
eMMC source clock and to switch it from 200MHz or 150MHz.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20250113231030.6735-5-ansuelsmth@gmail.com
|
||||
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 10 ++++++++++
|
||||
1 file changed, 10 insertions(+)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -91,6 +91,7 @@ static const u32 emi7581_base[] = { 5400
|
||||
static const u32 bus7581_base[] = { 600000000, 540000000 };
|
||||
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
|
||||
static const u32 crypto_base[] = { 540000000, 480000000 };
|
||||
+static const u32 emmc7581_base[] = { 200000000, 150000000 };
|
||||
|
||||
static const struct en_clk_desc en7523_base_clks[] = {
|
||||
{
|
||||
@@ -281,6 +282,15 @@ static const struct en_clk_desc en7581_b
|
||||
.base_shift = 0,
|
||||
.base_values = crypto_base,
|
||||
.n_base_values = ARRAY_SIZE(crypto_base),
|
||||
+ }, {
|
||||
+ .id = EN7581_CLK_EMMC,
|
||||
+ .name = "emmc",
|
||||
+
|
||||
+ .base_reg = REG_CRYPTO_CLKSRC2,
|
||||
+ .base_bits = 1,
|
||||
+ .base_shift = 12,
|
||||
+ .base_values = emmc7581_base,
|
||||
+ .n_base_values = ARRAY_SIZE(emmc7581_base),
|
||||
}
|
||||
};
|
||||
|
@@ -1,57 +0,0 @@
|
||||
From 0e7a622da17da0042294860cdb7a2fac091d25b1 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 8 Jan 2025 10:50:40 +0100
|
||||
Subject: [PATCH 1/6] PCI: mediatek-gen3: Rely on clk_bulk_prepare_enable() in
|
||||
mtk_pcie_en7581_power_up()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Replace clk_bulk_prepare() and clk_bulk_enable() with
|
||||
clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up() routine.
|
||||
|
||||
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-1-21ac939a3b9b@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 14 +++-----------
|
||||
1 file changed, 3 insertions(+), 11 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -907,12 +907,6 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
- err = clk_bulk_prepare(pcie->num_clks, pcie->clks);
|
||||
- if (err) {
|
||||
- dev_err(dev, "failed to prepare clock\n");
|
||||
- goto err_clk_prepare;
|
||||
- }
|
||||
-
|
||||
val = FIELD_PREP(PCIE_VAL_LN0_DOWNSTREAM, 0x47) |
|
||||
FIELD_PREP(PCIE_VAL_LN1_DOWNSTREAM, 0x47) |
|
||||
FIELD_PREP(PCIE_VAL_LN0_UPSTREAM, 0x41) |
|
||||
@@ -925,17 +919,15 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
FIELD_PREP(PCIE_K_FINETUNE_MAX, 0xf);
|
||||
writel_relaxed(val, pcie->base + PCIE_PIPE4_PIE8_REG);
|
||||
|
||||
- err = clk_bulk_enable(pcie->num_clks, pcie->clks);
|
||||
+ err = clk_bulk_prepare_enable(pcie->num_clks, pcie->clks);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to prepare clock\n");
|
||||
- goto err_clk_enable;
|
||||
+ goto err_clk_prepare_enable;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
-err_clk_enable:
|
||||
- clk_bulk_unprepare(pcie->num_clks, pcie->clks);
|
||||
-err_clk_prepare:
|
||||
+err_clk_prepare_enable:
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_disable(dev);
|
||||
reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
@@ -1,86 +0,0 @@
|
||||
From e4c7dfd953f7618f0ccb70d87c1629634f306fab Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 8 Jan 2025 10:50:41 +0100
|
||||
Subject: [PATCH 2/6] PCI: mediatek-gen3: Move reset/assert callbacks in
|
||||
.power_up()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
In order to make the code more readable, the reset_control_bulk_assert()
|
||||
function for PHY reset lines is moved to make it pair with
|
||||
reset_control_bulk_deassert() in mtk_pcie_power_up() and
|
||||
mtk_pcie_en7581_power_up(). The same change is done for
|
||||
reset_control_assert() used to assert MAC reset line.
|
||||
|
||||
Introduce PCIE_MTK_RESET_TIME_US macro for the time needed to
|
||||
complete PCIe reset on MediaTek controller.
|
||||
|
||||
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-2-21ac939a3b9b@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 28 +++++++++++++--------
|
||||
1 file changed, 18 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -120,6 +120,8 @@
|
||||
|
||||
#define MAX_NUM_PHY_RESETS 3
|
||||
|
||||
+#define PCIE_MTK_RESET_TIME_US 10
|
||||
+
|
||||
/* Time in ms needed to complete PCIe reset on EN7581 SoC */
|
||||
#define PCIE_EN7581_RESET_TIME_MS 100
|
||||
|
||||
@@ -875,9 +877,14 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
u32 val;
|
||||
|
||||
/*
|
||||
- * Wait for the time needed to complete the bulk assert in
|
||||
- * mtk_pcie_setup for EN7581 SoC.
|
||||
+ * The controller may have been left out of reset by the bootloader
|
||||
+ * so make sure that we get a clean start by asserting resets here.
|
||||
*/
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
|
||||
+ pcie->phy_resets);
|
||||
+ reset_control_assert(pcie->mac_reset);
|
||||
+
|
||||
+ /* Wait for the time needed to complete the reset lines assert. */
|
||||
mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
|
||||
err = phy_init(pcie->phy);
|
||||
@@ -944,6 +951,15 @@ static int mtk_pcie_power_up(struct mtk_
|
||||
struct device *dev = pcie->dev;
|
||||
int err;
|
||||
|
||||
+ /*
|
||||
+ * The controller may have been left out of reset by the bootloader
|
||||
+ * so make sure that we get a clean start by asserting resets here.
|
||||
+ */
|
||||
+ reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
|
||||
+ pcie->phy_resets);
|
||||
+ reset_control_assert(pcie->mac_reset);
|
||||
+ usleep_range(PCIE_MTK_RESET_TIME_US, 2 * PCIE_MTK_RESET_TIME_US);
|
||||
+
|
||||
/* PHY power on and enable pipe clock */
|
||||
err = reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
if (err) {
|
||||
@@ -1016,14 +1032,6 @@ static int mtk_pcie_setup(struct mtk_gen
|
||||
* counter since the bulk is shared.
|
||||
*/
|
||||
reset_control_bulk_deassert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
- /*
|
||||
- * The controller may have been left out of reset by the bootloader
|
||||
- * so make sure that we get a clean start by asserting resets here.
|
||||
- */
|
||||
- reset_control_bulk_assert(pcie->soc->phy_resets.num_resets, pcie->phy_resets);
|
||||
-
|
||||
- reset_control_assert(pcie->mac_reset);
|
||||
- usleep_range(10, 20);
|
||||
|
||||
/* Don't touch the hardware registers before power up */
|
||||
err = pcie->soc->power_up(pcie);
|
@@ -1,35 +0,0 @@
|
||||
From 0c9d2d2ef0d916b490a9222ed20ff4616fca876d Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 8 Jan 2025 10:50:42 +0100
|
||||
Subject: [PATCH 3/6] PCI: mediatek-gen3: Add comment about initialization
|
||||
order in mtk_pcie_en7581_power_up()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Add a comment in mtk_pcie_en7581_power_up() to clarify, unlike the other
|
||||
MediaTek Gen3 controllers, the Airoha EN7581 requires PHY initialization
|
||||
and power-on before PHY reset deassert.
|
||||
|
||||
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-3-21ac939a3b9b@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 4 ++++
|
||||
1 file changed, 4 insertions(+)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -887,6 +887,10 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
/* Wait for the time needed to complete the reset lines assert. */
|
||||
mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
|
||||
+ /*
|
||||
+ * Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
|
||||
+ * requires PHY initialization and power-on before PHY reset deassert.
|
||||
+ */
|
||||
err = phy_init(pcie->phy);
|
||||
if (err) {
|
||||
dev_err(dev, "failed to initialize PHY\n");
|
@@ -1,59 +0,0 @@
|
||||
From 90d4e466c9ea2010f33880a36317a8486ccbe082 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 8 Jan 2025 10:50:43 +0100
|
||||
Subject: [PATCH 4/6] PCI: mediatek-gen3: Move reset delay in
|
||||
mtk_pcie_en7581_power_up()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
|
||||
causing occasional PCIe link down issues. In order to overcome the
|
||||
problem, PCIe block is reset using REG_PCI_CONTROL (0x88) and
|
||||
REG_RESET_CONTROL (0x834) registers available in the clock module
|
||||
running clk_bulk_prepare_enable() in mtk_pcie_en7581_power_up().
|
||||
|
||||
In order to make the code more readable, move the wait for the time
|
||||
needed to complete the PCIe reset from en7581_pci_enable() to
|
||||
mtk_pcie_en7581_power_up().
|
||||
|
||||
Reduce reset timeout from 250ms to the standard PCIE_T_PVPERL_MS value
|
||||
(100ms) since it has no impact on the driver behavior.
|
||||
|
||||
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-4-21ac939a3b9b@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
Acked-by: Stephen Boyd <sboyd@kernel.org>
|
||||
---
|
||||
drivers/clk/clk-en7523.c | 1 -
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 7 +++++++
|
||||
2 files changed, 7 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/clk/clk-en7523.c
|
||||
+++ b/drivers/clk/clk-en7523.c
|
||||
@@ -489,7 +489,6 @@ static int en7581_pci_enable(struct clk_
|
||||
REG_PCI_CONTROL_PERSTOUT;
|
||||
val = readl(np_base + REG_PCI_CONTROL);
|
||||
writel(val | mask, np_base + REG_PCI_CONTROL);
|
||||
- msleep(250);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -936,6 +936,13 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
goto err_clk_prepare_enable;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ * Airoha EN7581 performs PCIe reset via clk callbacks since it has a
|
||||
+ * hw issue with PCIE_PE_RSTB signal. Add wait for the time needed to
|
||||
+ * complete the PCIe reset.
|
||||
+ */
|
||||
+ msleep(PCIE_T_PVPERL_MS);
|
||||
+
|
||||
return 0;
|
||||
|
||||
err_clk_prepare_enable:
|
@@ -1,41 +0,0 @@
|
||||
From c98bee18d0a094e37100c85effe5e161418f8644 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Wed, 8 Jan 2025 10:50:44 +0100
|
||||
Subject: [PATCH 5/6] PCI: mediatek-gen3: Rely on msleep() in
|
||||
mtk_pcie_en7581_power_up()
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Since mtk_pcie_en7581_power_up() runs in non-atomic context, rely on
|
||||
msleep() routine instead of mdelay().
|
||||
|
||||
Link: https://lore.kernel.org/r/20250108-pcie-en7581-fixes-v6-5-21ac939a3b9b@kernel.org
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -885,7 +885,7 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
reset_control_assert(pcie->mac_reset);
|
||||
|
||||
/* Wait for the time needed to complete the reset lines assert. */
|
||||
- mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+ msleep(PCIE_EN7581_RESET_TIME_MS);
|
||||
|
||||
/*
|
||||
* Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
|
||||
@@ -913,7 +913,7 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
* Wait for the time needed to complete the bulk de-assert above.
|
||||
* This time is specific for EN7581 SoC.
|
||||
*/
|
||||
- mdelay(PCIE_EN7581_RESET_TIME_MS);
|
||||
+ msleep(PCIE_EN7581_RESET_TIME_MS);
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
pm_runtime_get_sync(dev);
|
@@ -1,128 +0,0 @@
|
||||
From 491cb9c5084790aafa02e843349492c284373231 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 9 Jan 2025 00:30:45 +0100
|
||||
Subject: [PATCH 6/6] PCI: mediatek-gen3: Avoid PCIe resetting via PERST# for
|
||||
Airoha EN7581 SoC
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Airoha EN7581 has a hw bug asserting/releasing PERST# signal causing
|
||||
occasional PCIe link down issues. In order to overcome the problem,
|
||||
PERST# signal is not asserted/released during device probe or
|
||||
suspend/resume phase and the PCIe block is reset using
|
||||
en7523_reset_assert() and en7581_pci_enable().
|
||||
|
||||
Introduce flags field in the mtk_gen3_pcie_pdata struct in order to
|
||||
specify per-SoC capabilities.
|
||||
|
||||
Link: https://lore.kernel.org/r/20250109-pcie-en7581-rst-fix-v4-1-4a45c89fb143@kernel.org
|
||||
Tested-by: Hui Ma <hui.ma@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 59 ++++++++++++++-------
|
||||
1 file changed, 41 insertions(+), 18 deletions(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -127,10 +127,18 @@
|
||||
|
||||
struct mtk_gen3_pcie;
|
||||
|
||||
+enum mtk_gen3_pcie_flags {
|
||||
+ SKIP_PCIE_RSTB = BIT(0), /* Skip PERST# assertion during device
|
||||
+ * probing or suspend/resume phase to
|
||||
+ * avoid hw bugs/issues.
|
||||
+ */
|
||||
+};
|
||||
+
|
||||
/**
|
||||
* struct mtk_gen3_pcie_pdata - differentiate between host generations
|
||||
* @power_up: pcie power_up callback
|
||||
* @phy_resets: phy reset lines SoC data.
|
||||
+ * @flags: pcie device flags.
|
||||
*/
|
||||
struct mtk_gen3_pcie_pdata {
|
||||
int (*power_up)(struct mtk_gen3_pcie *pcie);
|
||||
@@ -138,6 +146,7 @@ struct mtk_gen3_pcie_pdata {
|
||||
const char *id[MAX_NUM_PHY_RESETS];
|
||||
int num_resets;
|
||||
} phy_resets;
|
||||
+ u32 flags;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -404,22 +413,33 @@ static int mtk_pcie_startup_port(struct
|
||||
val |= PCIE_DISABLE_DVFSRC_VLT_REQ;
|
||||
writel_relaxed(val, pcie->base + PCIE_MISC_CTRL_REG);
|
||||
|
||||
- /* Assert all reset signals */
|
||||
- val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
|
||||
- val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB;
|
||||
- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
|
||||
-
|
||||
/*
|
||||
- * Described in PCIe CEM specification sections 2.2 (PERST# Signal)
|
||||
- * and 2.2.1 (Initial Power-Up (G3 to S0)).
|
||||
- * The deassertion of PERST# should be delayed 100ms (TPVPERL)
|
||||
- * for the power and clock to become stable.
|
||||
+ * Airoha EN7581 has a hw bug asserting/releasing PCIE_PE_RSTB signal
|
||||
+ * causing occasional PCIe link down. In order to overcome the issue,
|
||||
+ * PCIE_RSTB signals are not asserted/released at this stage and the
|
||||
+ * PCIe block is reset using en7523_reset_assert() and
|
||||
+ * en7581_pci_enable().
|
||||
*/
|
||||
- msleep(100);
|
||||
-
|
||||
- /* De-assert reset signals */
|
||||
- val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB | PCIE_PE_RSTB);
|
||||
- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
|
||||
+ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
|
||||
+ /* Assert all reset signals */
|
||||
+ val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
|
||||
+ val |= PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
|
||||
+ PCIE_PE_RSTB;
|
||||
+ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
|
||||
+
|
||||
+ /*
|
||||
+ * Described in PCIe CEM specification revision 6.0.
|
||||
+ *
|
||||
+ * The deassertion of PERST# should be delayed 100ms (TPVPERL)
|
||||
+ * for the power and clock to become stable.
|
||||
+ */
|
||||
+ msleep(PCIE_T_PVPERL_MS);
|
||||
+
|
||||
+ /* De-assert reset signals */
|
||||
+ val &= ~(PCIE_MAC_RSTB | PCIE_PHY_RSTB | PCIE_BRG_RSTB |
|
||||
+ PCIE_PE_RSTB);
|
||||
+ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
|
||||
+ }
|
||||
|
||||
/* Check if the link is up or not */
|
||||
err = readl_poll_timeout(pcie->base + PCIE_LINK_STATUS_REG, val,
|
||||
@@ -1178,10 +1198,12 @@ static int mtk_pcie_suspend_noirq(struct
|
||||
return err;
|
||||
}
|
||||
|
||||
- /* Pull down the PERST# pin */
|
||||
- val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
|
||||
- val |= PCIE_PE_RSTB;
|
||||
- writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
|
||||
+ if (!(pcie->soc->flags & SKIP_PCIE_RSTB)) {
|
||||
+ /* Assert the PERST# pin */
|
||||
+ val = readl_relaxed(pcie->base + PCIE_RST_CTRL_REG);
|
||||
+ val |= PCIE_PE_RSTB;
|
||||
+ writel_relaxed(val, pcie->base + PCIE_RST_CTRL_REG);
|
||||
+ }
|
||||
|
||||
dev_dbg(pcie->dev, "entered L2 states successfully");
|
||||
|
||||
@@ -1232,6 +1254,7 @@ static const struct mtk_gen3_pcie_pdata
|
||||
.id[2] = "phy-lane2",
|
||||
.num_resets = 3,
|
||||
},
|
||||
+ .flags = SKIP_PCIE_RSTB,
|
||||
};
|
||||
|
||||
static const struct of_device_id mtk_pcie_of_match[] = {
|
@@ -1,34 +0,0 @@
|
||||
From b6d7bb0d3bd74b491e2e6fd59c4d5110d06fd63b Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Sat, 1 Feb 2025 12:00:18 +0100
|
||||
Subject: [PATCH] PCI: mediatek-gen3: Remove leftover mac_reset assert for
|
||||
Airoha EN7581 SoC
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Remove a leftover assert for mac_reset line in mtk_pcie_en7581_power_up().
|
||||
|
||||
This is not harmful since EN7581 does not requires mac_reset and
|
||||
mac_reset is not defined in EN7581 device tree.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
Reviewed-by: Philipp Zabel <p.zabel@pengutronix.de>
|
||||
Link: https://lore.kernel.org/r/20250201-pcie-en7581-remove-mac_reset-v2-1-a06786cdc683@kernel.org
|
||||
[kwilczynski: commit log]
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 1 -
|
||||
1 file changed, 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -902,7 +902,6 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
*/
|
||||
reset_control_bulk_assert(pcie->soc->phy_resets.num_resets,
|
||||
pcie->phy_resets);
|
||||
- reset_control_assert(pcie->mac_reset);
|
||||
|
||||
/* Wait for the time needed to complete the reset lines assert. */
|
||||
msleep(PCIE_EN7581_RESET_TIME_MS);
|
@@ -1,81 +0,0 @@
|
||||
From 249b78298078448a699c39356d27d8183af4b281 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Tue, 25 Feb 2025 09:04:07 +0100
|
||||
Subject: [PATCH] PCI: mediatek-gen3: Configure PBUS_CSR registers for EN7581
|
||||
SoC
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Configure PBus base address and address mask to allow the hw
|
||||
to detect if a given address is accessible on PCIe controller.
|
||||
|
||||
Fixes: f6ab898356dd ("PCI: mediatek-gen3: Add Airoha EN7581 support")
|
||||
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/r/20250225-en7581-pcie-pbus-csr-v4-2-24324382424a@kernel.org
|
||||
Signed-off-by: Krzysztof Wilczyński <kwilczynski@kernel.org>
|
||||
---
|
||||
drivers/pci/controller/pcie-mediatek-gen3.c | 28 ++++++++++++++++++++-
|
||||
1 file changed, 27 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
+++ b/drivers/pci/controller/pcie-mediatek-gen3.c
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <linux/irqchip/chained_irq.h>
|
||||
#include <linux/irqdomain.h>
|
||||
#include <linux/kernel.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/msi.h>
|
||||
#include <linux/of_device.h>
|
||||
@@ -24,6 +25,7 @@
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_domain.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
+#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "../pci.h"
|
||||
@@ -892,9 +894,13 @@ static int mtk_pcie_parse_port(struct mt
|
||||
|
||||
static int mtk_pcie_en7581_power_up(struct mtk_gen3_pcie *pcie)
|
||||
{
|
||||
+ struct pci_host_bridge *host = pci_host_bridge_from_priv(pcie);
|
||||
struct device *dev = pcie->dev;
|
||||
+ struct resource_entry *entry;
|
||||
+ struct regmap *pbus_regmap;
|
||||
+ u32 val, args[2], size;
|
||||
+ resource_size_t addr;
|
||||
int err;
|
||||
- u32 val;
|
||||
|
||||
/*
|
||||
* The controller may have been left out of reset by the bootloader
|
||||
@@ -907,6 +913,26 @@ static int mtk_pcie_en7581_power_up(stru
|
||||
msleep(PCIE_EN7581_RESET_TIME_MS);
|
||||
|
||||
/*
|
||||
+ * Configure PBus base address and base address mask to allow the
|
||||
+ * hw to detect if a given address is accessible on PCIe controller.
|
||||
+ */
|
||||
+ pbus_regmap = syscon_regmap_lookup_by_phandle_args(dev->of_node,
|
||||
+ "mediatek,pbus-csr",
|
||||
+ ARRAY_SIZE(args),
|
||||
+ args);
|
||||
+ if (IS_ERR(pbus_regmap))
|
||||
+ return PTR_ERR(pbus_regmap);
|
||||
+
|
||||
+ entry = resource_list_first_type(&host->windows, IORESOURCE_MEM);
|
||||
+ if (!entry)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ addr = entry->res->start - entry->offset;
|
||||
+ regmap_write(pbus_regmap, args[0], lower_32_bits(addr));
|
||||
+ size = lower_32_bits(resource_size(entry->res));
|
||||
+ regmap_write(pbus_regmap, args[1], GENMASK(31, __fls(size)));
|
||||
+
|
||||
+ /*
|
||||
* Unlike the other MediaTek Gen3 controllers, the Airoha EN7581
|
||||
* requires PHY initialization and power-on before PHY reset deassert.
|
||||
*/
|
@@ -1,41 +0,0 @@
|
||||
From d31a49d37cb132b31cc6683eef2122f8609d6229 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Mon, 20 Jan 2025 16:41:40 +0100
|
||||
Subject: [PATCH] net: airoha: Fix wrong GDM4 register definition
|
||||
|
||||
Fix wrong GDM4 register definition, in Airoha SDK GDM4 is defined at
|
||||
offset 0x2400 but this doesn't make sense as it does conflict with the
|
||||
CDM4 that is in the same location.
|
||||
|
||||
Following the pattern where each GDM base is at the FWD_CFG, currently
|
||||
GDM4 base offset is set to 0x2500. This is correct but REG_GDM4_FWD_CFG
|
||||
and REG_GDM4_SRC_PORT_SET are still using the SDK reference with the
|
||||
0x2400 offset. Fix these 2 define by subtracting 0x100 to each register
|
||||
to reflect the real address location.
|
||||
|
||||
Fixes: 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
|
||||
Link: https://patch.msgid.link/20250120154148.13424-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 4 ++--
|
||||
1 file changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -266,11 +266,11 @@
|
||||
#define REG_GDM3_FWD_CFG GDM3_BASE
|
||||
#define GDM3_PAD_EN_MASK BIT(28)
|
||||
|
||||
-#define REG_GDM4_FWD_CFG (GDM4_BASE + 0x100)
|
||||
+#define REG_GDM4_FWD_CFG GDM4_BASE
|
||||
#define GDM4_PAD_EN_MASK BIT(28)
|
||||
#define GDM4_SPORT_OFFSET0_MASK GENMASK(11, 8)
|
||||
|
||||
-#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x33c)
|
||||
+#define REG_GDM4_SRC_PORT_SET (GDM4_BASE + 0x23c)
|
||||
#define GDM4_SPORT_OFF2_MASK GENMASK(19, 16)
|
||||
#define GDM4_SPORT_OFF1_MASK GENMASK(15, 12)
|
||||
#define GDM4_SPORT_OFF0_MASK GENMASK(11, 8)
|
@@ -1,60 +0,0 @@
|
||||
From c6287e1a858e336cc202b484c6138a0fe252c6b3 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 13 Feb 2025 16:34:20 +0100
|
||||
Subject: [PATCH] net: airoha: Fix TSO support for header cloned skbs
|
||||
|
||||
For GSO packets, skb_cow_head() will reallocate the skb for TSO header
|
||||
cloned skbs in airoha_dev_xmit(). For this reason, sinfo pointer can be
|
||||
no more valid. Fix the issue relying on skb_shinfo() macro directly in
|
||||
airoha_dev_xmit().
|
||||
|
||||
The problem exists since
|
||||
commit 23020f049327 ("net: airoha: Introduce ethernet support for EN7581 SoC")
|
||||
but it is not a user visible, since we can't currently enable TSO
|
||||
for DSA user ports since we are missing to initialize net_device
|
||||
vlan_features field.
|
||||
|
||||
Reviewed-by: Mateusz Polchlopek <mateusz.polchlopek@intel.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://patch.msgid.link/20250213-airoha-en7581-flowtable-offload-v4-1-b69ca16d74db@kernel.org
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2549,11 +2549,10 @@ static u16 airoha_dev_select_queue(struc
|
||||
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
- struct skb_shared_info *sinfo = skb_shinfo(skb);
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
+ u32 nr_frags = 1 + skb_shinfo(skb)->nr_frags;
|
||||
u32 msg0, msg1, len = skb_headlen(skb);
|
||||
struct airoha_qdma *qdma = port->qdma;
|
||||
- u32 nr_frags = 1 + sinfo->nr_frags;
|
||||
struct netdev_queue *txq;
|
||||
struct airoha_queue *q;
|
||||
void *data = skb->data;
|
||||
@@ -2576,8 +2575,9 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
if (skb_cow_head(skb, 0))
|
||||
goto error;
|
||||
|
||||
- if (sinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
|
||||
- __be16 csum = cpu_to_be16(sinfo->gso_size);
|
||||
+ if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 |
|
||||
+ SKB_GSO_TCPV6)) {
|
||||
+ __be16 csum = cpu_to_be16(skb_shinfo(skb)->gso_size);
|
||||
|
||||
tcp_hdr(skb)->check = (__force __sum16)csum;
|
||||
msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TSO_MASK, 1);
|
||||
@@ -2606,7 +2606,7 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
struct airoha_qdma_desc *desc = &q->desc[index];
|
||||
struct airoha_queue_entry *e = &q->entry[index];
|
||||
- skb_frag_t *frag = &sinfo->frags[i];
|
||||
+ skb_frag_t *frag = &skb_shinfo(skb)->frags[i];
|
||||
dma_addr_t addr;
|
||||
u32 val;
|
||||
|
@@ -1,42 +0,0 @@
|
||||
From c9f947769b77c8e8f318bfc8a0777e5d20c44d8d Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Thu, 17 Oct 2024 16:01:41 +0200
|
||||
Subject: [PATCH] net: airoha: Reset BQL stopping the netdevice
|
||||
|
||||
Run airoha_qdma_cleanup_tx_queue() in ndo_stop callback in order to
|
||||
unmap pending skbs. Moreover, reset BQL txq state stopping the netdevice,
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Reviewed-by: Hariprasad Kelam <hkelam@marvell.com>
|
||||
Message-ID: <20241017-airoha-en7581-reset-bql-v1-1-08c0c9888de5@kernel.org>
|
||||
Signed-off-by: Andrew Lunn <andrew@lunn.ch>
|
||||
---
|
||||
drivers/net/ethernet/mediatek/airoha_eth.c | 10 +++++++++-
|
||||
1 file changed, 9 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
|
||||
@@ -2469,7 +2469,7 @@ static int airoha_dev_stop(struct net_de
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
struct airoha_qdma *qdma = port->qdma;
|
||||
- int err;
|
||||
+ int i, err;
|
||||
|
||||
netif_tx_disable(dev);
|
||||
err = airoha_set_gdm_ports(qdma->eth, false);
|
||||
@@ -2480,6 +2480,14 @@ static int airoha_dev_stop(struct net_de
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
+ continue;
|
||||
+
|
||||
+ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
|
||||
+ netdev_tx_reset_subqueue(dev, i);
|
||||
+ }
|
||||
+
|
||||
return 0;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,538 +0,0 @@
|
||||
From b38f4ff0ceacd6ce8d333a8dc90f405a040968d3 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:10 +0100
|
||||
Subject: [PATCH 02/15] net: airoha: Move definitions in airoha_eth.h
|
||||
|
||||
Move common airoha_eth definitions in airoha_eth.h in order to reuse
|
||||
them for Packet Processor Engine (PPE) codebase.
|
||||
PPE module is used to enable support for flowtable hw offloading in
|
||||
airoha_eth driver.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 240 +---------------------
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 251 +++++++++++++++++++++++
|
||||
2 files changed, 252 insertions(+), 239 deletions(-)
|
||||
create mode 100644 drivers/net/ethernet/airoha/airoha_eth.h
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -3,14 +3,9 @@
|
||||
* Copyright (c) 2024 AIROHA Inc
|
||||
* Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
*/
|
||||
-#include <linux/etherdevice.h>
|
||||
-#include <linux/iopoll.h>
|
||||
-#include <linux/kernel.h>
|
||||
-#include <linux/netdevice.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_net.h>
|
||||
#include <linux/platform_device.h>
|
||||
-#include <linux/reset.h>
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <net/dsa.h>
|
||||
@@ -18,35 +13,7 @@
|
||||
#include <net/pkt_cls.h>
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
|
||||
-#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
-#define AIROHA_MAX_NUM_QDMA 2
|
||||
-#define AIROHA_MAX_NUM_RSTS 3
|
||||
-#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
-#define AIROHA_MAX_MTU 2000
|
||||
-#define AIROHA_MAX_PACKET_SIZE 2048
|
||||
-#define AIROHA_NUM_QOS_CHANNELS 4
|
||||
-#define AIROHA_NUM_QOS_QUEUES 8
|
||||
-#define AIROHA_NUM_TX_RING 32
|
||||
-#define AIROHA_NUM_RX_RING 32
|
||||
-#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \
|
||||
- AIROHA_NUM_QOS_CHANNELS)
|
||||
-#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
|
||||
-#define AIROHA_FE_MC_MAX_VLAN_PORT 16
|
||||
-#define AIROHA_NUM_TX_IRQ 2
|
||||
-#define HW_DSCP_NUM 2048
|
||||
-#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048)
|
||||
-#define TX_DSCP_NUM 1024
|
||||
-#define RX_DSCP_NUM(_n) \
|
||||
- ((_n) == 2 ? 128 : \
|
||||
- (_n) == 11 ? 128 : \
|
||||
- (_n) == 15 ? 128 : \
|
||||
- (_n) == 0 ? 1024 : 16)
|
||||
-
|
||||
-#define PSE_RSV_PAGES 128
|
||||
-#define PSE_QUEUE_RSV_PAGES 64
|
||||
-
|
||||
-#define QDMA_METER_IDX(_n) ((_n) & 0xff)
|
||||
-#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3)
|
||||
+#include "airoha_eth.h"
|
||||
|
||||
/* FE */
|
||||
#define PSE_BASE 0x0100
|
||||
@@ -706,211 +673,6 @@ struct airoha_qdma_fwd_desc {
|
||||
__le32 rsv1;
|
||||
};
|
||||
|
||||
-enum {
|
||||
- QDMA_INT_REG_IDX0,
|
||||
- QDMA_INT_REG_IDX1,
|
||||
- QDMA_INT_REG_IDX2,
|
||||
- QDMA_INT_REG_IDX3,
|
||||
- QDMA_INT_REG_IDX4,
|
||||
- QDMA_INT_REG_MAX
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- XSI_PCIE0_PORT,
|
||||
- XSI_PCIE1_PORT,
|
||||
- XSI_USB_PORT,
|
||||
- XSI_AE_PORT,
|
||||
- XSI_ETH_PORT,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- XSI_PCIE0_VIP_PORT_MASK = BIT(22),
|
||||
- XSI_PCIE1_VIP_PORT_MASK = BIT(23),
|
||||
- XSI_USB_VIP_PORT_MASK = BIT(25),
|
||||
- XSI_ETH_VIP_PORT_MASK = BIT(24),
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- DEV_STATE_INITIALIZED,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- CDM_CRSN_QSEL_Q1 = 1,
|
||||
- CDM_CRSN_QSEL_Q5 = 5,
|
||||
- CDM_CRSN_QSEL_Q6 = 6,
|
||||
- CDM_CRSN_QSEL_Q15 = 15,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- CRSN_08 = 0x8,
|
||||
- CRSN_21 = 0x15, /* KA */
|
||||
- CRSN_22 = 0x16, /* hit bind and force route to CPU */
|
||||
- CRSN_24 = 0x18,
|
||||
- CRSN_25 = 0x19,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
- FE_PSE_PORT_CDM1,
|
||||
- FE_PSE_PORT_GDM1,
|
||||
- FE_PSE_PORT_GDM2,
|
||||
- FE_PSE_PORT_GDM3,
|
||||
- FE_PSE_PORT_PPE1,
|
||||
- FE_PSE_PORT_CDM2,
|
||||
- FE_PSE_PORT_CDM3,
|
||||
- FE_PSE_PORT_CDM4,
|
||||
- FE_PSE_PORT_PPE2,
|
||||
- FE_PSE_PORT_GDM4,
|
||||
- FE_PSE_PORT_CDM5,
|
||||
- FE_PSE_PORT_DROP = 0xf,
|
||||
-};
|
||||
-
|
||||
-enum tx_sched_mode {
|
||||
- TC_SCH_WRR8,
|
||||
- TC_SCH_SP,
|
||||
- TC_SCH_WRR7,
|
||||
- TC_SCH_WRR6,
|
||||
- TC_SCH_WRR5,
|
||||
- TC_SCH_WRR4,
|
||||
- TC_SCH_WRR3,
|
||||
- TC_SCH_WRR2,
|
||||
-};
|
||||
-
|
||||
-enum trtcm_param_type {
|
||||
- TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */
|
||||
- TRTCM_TOKEN_RATE_MODE,
|
||||
- TRTCM_BUCKETSIZE_SHIFT_MODE,
|
||||
- TRTCM_BUCKET_COUNTER_MODE,
|
||||
-};
|
||||
-
|
||||
-enum trtcm_mode_type {
|
||||
- TRTCM_COMMIT_MODE,
|
||||
- TRTCM_PEAK_MODE,
|
||||
-};
|
||||
-
|
||||
-enum trtcm_param {
|
||||
- TRTCM_TICK_SEL = BIT(0),
|
||||
- TRTCM_PKT_MODE = BIT(1),
|
||||
- TRTCM_METER_MODE = BIT(2),
|
||||
-};
|
||||
-
|
||||
-#define MIN_TOKEN_SIZE 4096
|
||||
-#define MAX_TOKEN_SIZE_OFFSET 17
|
||||
-#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
|
||||
-#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
|
||||
-
|
||||
-struct airoha_queue_entry {
|
||||
- union {
|
||||
- void *buf;
|
||||
- struct sk_buff *skb;
|
||||
- };
|
||||
- dma_addr_t dma_addr;
|
||||
- u16 dma_len;
|
||||
-};
|
||||
-
|
||||
-struct airoha_queue {
|
||||
- struct airoha_qdma *qdma;
|
||||
-
|
||||
- /* protect concurrent queue accesses */
|
||||
- spinlock_t lock;
|
||||
- struct airoha_queue_entry *entry;
|
||||
- struct airoha_qdma_desc *desc;
|
||||
- u16 head;
|
||||
- u16 tail;
|
||||
-
|
||||
- int queued;
|
||||
- int ndesc;
|
||||
- int free_thr;
|
||||
- int buf_size;
|
||||
-
|
||||
- struct napi_struct napi;
|
||||
- struct page_pool *page_pool;
|
||||
-};
|
||||
-
|
||||
-struct airoha_tx_irq_queue {
|
||||
- struct airoha_qdma *qdma;
|
||||
-
|
||||
- struct napi_struct napi;
|
||||
-
|
||||
- int size;
|
||||
- u32 *q;
|
||||
-};
|
||||
-
|
||||
-struct airoha_hw_stats {
|
||||
- /* protect concurrent hw_stats accesses */
|
||||
- spinlock_t lock;
|
||||
- struct u64_stats_sync syncp;
|
||||
-
|
||||
- /* get_stats64 */
|
||||
- u64 rx_ok_pkts;
|
||||
- u64 tx_ok_pkts;
|
||||
- u64 rx_ok_bytes;
|
||||
- u64 tx_ok_bytes;
|
||||
- u64 rx_multicast;
|
||||
- u64 rx_errors;
|
||||
- u64 rx_drops;
|
||||
- u64 tx_drops;
|
||||
- u64 rx_crc_error;
|
||||
- u64 rx_over_errors;
|
||||
- /* ethtool stats */
|
||||
- u64 tx_broadcast;
|
||||
- u64 tx_multicast;
|
||||
- u64 tx_len[7];
|
||||
- u64 rx_broadcast;
|
||||
- u64 rx_fragment;
|
||||
- u64 rx_jabber;
|
||||
- u64 rx_len[7];
|
||||
-};
|
||||
-
|
||||
-struct airoha_qdma {
|
||||
- struct airoha_eth *eth;
|
||||
- void __iomem *regs;
|
||||
-
|
||||
- /* protect concurrent irqmask accesses */
|
||||
- spinlock_t irq_lock;
|
||||
- u32 irqmask[QDMA_INT_REG_MAX];
|
||||
- int irq;
|
||||
-
|
||||
- struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
-
|
||||
- struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
- struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
-
|
||||
- /* descriptor and packet buffers for qdma hw forward */
|
||||
- struct {
|
||||
- void *desc;
|
||||
- void *q;
|
||||
- } hfwd;
|
||||
-};
|
||||
-
|
||||
-struct airoha_gdm_port {
|
||||
- struct airoha_qdma *qdma;
|
||||
- struct net_device *dev;
|
||||
- int id;
|
||||
-
|
||||
- struct airoha_hw_stats stats;
|
||||
-
|
||||
- DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
|
||||
-
|
||||
- /* qos stats counters */
|
||||
- u64 cpu_tx_packets;
|
||||
- u64 fwd_tx_packets;
|
||||
-};
|
||||
-
|
||||
-struct airoha_eth {
|
||||
- struct device *dev;
|
||||
-
|
||||
- unsigned long state;
|
||||
- void __iomem *fe_regs;
|
||||
-
|
||||
- struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
- struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
-
|
||||
- struct net_device *napi_dev;
|
||||
-
|
||||
- struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
- struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
-};
|
||||
-
|
||||
static u32 airoha_rr(void __iomem *base, u32 offset)
|
||||
{
|
||||
return readl(base + offset);
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -0,0 +1,251 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
+/*
|
||||
+ * Copyright (c) 2024 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#ifndef AIROHA_ETH_H
|
||||
+#define AIROHA_ETH_H
|
||||
+
|
||||
+#include <linux/etherdevice.h>
|
||||
+#include <linux/iopoll.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/netdevice.h>
|
||||
+#include <linux/reset.h>
|
||||
+
|
||||
+#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
+#define AIROHA_MAX_NUM_QDMA 2
|
||||
+#define AIROHA_MAX_NUM_RSTS 3
|
||||
+#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
+#define AIROHA_MAX_MTU 2000
|
||||
+#define AIROHA_MAX_PACKET_SIZE 2048
|
||||
+#define AIROHA_NUM_QOS_CHANNELS 4
|
||||
+#define AIROHA_NUM_QOS_QUEUES 8
|
||||
+#define AIROHA_NUM_TX_RING 32
|
||||
+#define AIROHA_NUM_RX_RING 32
|
||||
+#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \
|
||||
+ AIROHA_NUM_QOS_CHANNELS)
|
||||
+#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
|
||||
+#define AIROHA_FE_MC_MAX_VLAN_PORT 16
|
||||
+#define AIROHA_NUM_TX_IRQ 2
|
||||
+#define HW_DSCP_NUM 2048
|
||||
+#define IRQ_QUEUE_LEN(_n) ((_n) ? 1024 : 2048)
|
||||
+#define TX_DSCP_NUM 1024
|
||||
+#define RX_DSCP_NUM(_n) \
|
||||
+ ((_n) == 2 ? 128 : \
|
||||
+ (_n) == 11 ? 128 : \
|
||||
+ (_n) == 15 ? 128 : \
|
||||
+ (_n) == 0 ? 1024 : 16)
|
||||
+
|
||||
+#define PSE_RSV_PAGES 128
|
||||
+#define PSE_QUEUE_RSV_PAGES 64
|
||||
+
|
||||
+#define QDMA_METER_IDX(_n) ((_n) & 0xff)
|
||||
+#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3)
|
||||
+
|
||||
+enum {
|
||||
+ QDMA_INT_REG_IDX0,
|
||||
+ QDMA_INT_REG_IDX1,
|
||||
+ QDMA_INT_REG_IDX2,
|
||||
+ QDMA_INT_REG_IDX3,
|
||||
+ QDMA_INT_REG_IDX4,
|
||||
+ QDMA_INT_REG_MAX
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ XSI_PCIE0_PORT,
|
||||
+ XSI_PCIE1_PORT,
|
||||
+ XSI_USB_PORT,
|
||||
+ XSI_AE_PORT,
|
||||
+ XSI_ETH_PORT,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ XSI_PCIE0_VIP_PORT_MASK = BIT(22),
|
||||
+ XSI_PCIE1_VIP_PORT_MASK = BIT(23),
|
||||
+ XSI_USB_VIP_PORT_MASK = BIT(25),
|
||||
+ XSI_ETH_VIP_PORT_MASK = BIT(24),
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ DEV_STATE_INITIALIZED,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ CDM_CRSN_QSEL_Q1 = 1,
|
||||
+ CDM_CRSN_QSEL_Q5 = 5,
|
||||
+ CDM_CRSN_QSEL_Q6 = 6,
|
||||
+ CDM_CRSN_QSEL_Q15 = 15,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ CRSN_08 = 0x8,
|
||||
+ CRSN_21 = 0x15, /* KA */
|
||||
+ CRSN_22 = 0x16, /* hit bind and force route to CPU */
|
||||
+ CRSN_24 = 0x18,
|
||||
+ CRSN_25 = 0x19,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ FE_PSE_PORT_CDM1,
|
||||
+ FE_PSE_PORT_GDM1,
|
||||
+ FE_PSE_PORT_GDM2,
|
||||
+ FE_PSE_PORT_GDM3,
|
||||
+ FE_PSE_PORT_PPE1,
|
||||
+ FE_PSE_PORT_CDM2,
|
||||
+ FE_PSE_PORT_CDM3,
|
||||
+ FE_PSE_PORT_CDM4,
|
||||
+ FE_PSE_PORT_PPE2,
|
||||
+ FE_PSE_PORT_GDM4,
|
||||
+ FE_PSE_PORT_CDM5,
|
||||
+ FE_PSE_PORT_DROP = 0xf,
|
||||
+};
|
||||
+
|
||||
+enum tx_sched_mode {
|
||||
+ TC_SCH_WRR8,
|
||||
+ TC_SCH_SP,
|
||||
+ TC_SCH_WRR7,
|
||||
+ TC_SCH_WRR6,
|
||||
+ TC_SCH_WRR5,
|
||||
+ TC_SCH_WRR4,
|
||||
+ TC_SCH_WRR3,
|
||||
+ TC_SCH_WRR2,
|
||||
+};
|
||||
+
|
||||
+enum trtcm_param_type {
|
||||
+ TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */
|
||||
+ TRTCM_TOKEN_RATE_MODE,
|
||||
+ TRTCM_BUCKETSIZE_SHIFT_MODE,
|
||||
+ TRTCM_BUCKET_COUNTER_MODE,
|
||||
+};
|
||||
+
|
||||
+enum trtcm_mode_type {
|
||||
+ TRTCM_COMMIT_MODE,
|
||||
+ TRTCM_PEAK_MODE,
|
||||
+};
|
||||
+
|
||||
+enum trtcm_param {
|
||||
+ TRTCM_TICK_SEL = BIT(0),
|
||||
+ TRTCM_PKT_MODE = BIT(1),
|
||||
+ TRTCM_METER_MODE = BIT(2),
|
||||
+};
|
||||
+
|
||||
+#define MIN_TOKEN_SIZE 4096
|
||||
+#define MAX_TOKEN_SIZE_OFFSET 17
|
||||
+#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
|
||||
+#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
|
||||
+
|
||||
+struct airoha_queue_entry {
|
||||
+ union {
|
||||
+ void *buf;
|
||||
+ struct sk_buff *skb;
|
||||
+ };
|
||||
+ dma_addr_t dma_addr;
|
||||
+ u16 dma_len;
|
||||
+};
|
||||
+
|
||||
+struct airoha_queue {
|
||||
+ struct airoha_qdma *qdma;
|
||||
+
|
||||
+ /* protect concurrent queue accesses */
|
||||
+ spinlock_t lock;
|
||||
+ struct airoha_queue_entry *entry;
|
||||
+ struct airoha_qdma_desc *desc;
|
||||
+ u16 head;
|
||||
+ u16 tail;
|
||||
+
|
||||
+ int queued;
|
||||
+ int ndesc;
|
||||
+ int free_thr;
|
||||
+ int buf_size;
|
||||
+
|
||||
+ struct napi_struct napi;
|
||||
+ struct page_pool *page_pool;
|
||||
+};
|
||||
+
|
||||
+struct airoha_tx_irq_queue {
|
||||
+ struct airoha_qdma *qdma;
|
||||
+
|
||||
+ struct napi_struct napi;
|
||||
+
|
||||
+ int size;
|
||||
+ u32 *q;
|
||||
+};
|
||||
+
|
||||
+struct airoha_hw_stats {
|
||||
+ /* protect concurrent hw_stats accesses */
|
||||
+ spinlock_t lock;
|
||||
+ struct u64_stats_sync syncp;
|
||||
+
|
||||
+ /* get_stats64 */
|
||||
+ u64 rx_ok_pkts;
|
||||
+ u64 tx_ok_pkts;
|
||||
+ u64 rx_ok_bytes;
|
||||
+ u64 tx_ok_bytes;
|
||||
+ u64 rx_multicast;
|
||||
+ u64 rx_errors;
|
||||
+ u64 rx_drops;
|
||||
+ u64 tx_drops;
|
||||
+ u64 rx_crc_error;
|
||||
+ u64 rx_over_errors;
|
||||
+ /* ethtool stats */
|
||||
+ u64 tx_broadcast;
|
||||
+ u64 tx_multicast;
|
||||
+ u64 tx_len[7];
|
||||
+ u64 rx_broadcast;
|
||||
+ u64 rx_fragment;
|
||||
+ u64 rx_jabber;
|
||||
+ u64 rx_len[7];
|
||||
+};
|
||||
+
|
||||
+struct airoha_qdma {
|
||||
+ struct airoha_eth *eth;
|
||||
+ void __iomem *regs;
|
||||
+
|
||||
+ /* protect concurrent irqmask accesses */
|
||||
+ spinlock_t irq_lock;
|
||||
+ u32 irqmask[QDMA_INT_REG_MAX];
|
||||
+ int irq;
|
||||
+
|
||||
+ struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
+
|
||||
+ struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
||||
+ struct airoha_queue q_rx[AIROHA_NUM_RX_RING];
|
||||
+
|
||||
+ /* descriptor and packet buffers for qdma hw forward */
|
||||
+ struct {
|
||||
+ void *desc;
|
||||
+ void *q;
|
||||
+ } hfwd;
|
||||
+};
|
||||
+
|
||||
+struct airoha_gdm_port {
|
||||
+ struct airoha_qdma *qdma;
|
||||
+ struct net_device *dev;
|
||||
+ int id;
|
||||
+
|
||||
+ struct airoha_hw_stats stats;
|
||||
+
|
||||
+ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
|
||||
+
|
||||
+ /* qos stats counters */
|
||||
+ u64 cpu_tx_packets;
|
||||
+ u64 fwd_tx_packets;
|
||||
+};
|
||||
+
|
||||
+struct airoha_eth {
|
||||
+ struct device *dev;
|
||||
+
|
||||
+ unsigned long state;
|
||||
+ void __iomem *fe_regs;
|
||||
+
|
||||
+ struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
+ struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
+
|
||||
+ struct net_device *napi_dev;
|
||||
+
|
||||
+ struct airoha_qdma qdma[AIROHA_MAX_NUM_QDMA];
|
||||
+ struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
+};
|
||||
+
|
||||
+#endif /* AIROHA_ETH_H */
|
@@ -1,101 +0,0 @@
|
||||
From e0758a8694fbaffdc72940774db295585e951119 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:11 +0100
|
||||
Subject: [PATCH 03/15] net: airoha: Move reg/write utility routines in
|
||||
airoha_eth.h
|
||||
|
||||
This is a preliminary patch to introduce flowtable hw offloading
|
||||
support for airoha_eth driver.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 28 +++---------------------
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 26 ++++++++++++++++++++++
|
||||
2 files changed, 29 insertions(+), 25 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -673,17 +673,17 @@ struct airoha_qdma_fwd_desc {
|
||||
__le32 rsv1;
|
||||
};
|
||||
|
||||
-static u32 airoha_rr(void __iomem *base, u32 offset)
|
||||
+u32 airoha_rr(void __iomem *base, u32 offset)
|
||||
{
|
||||
return readl(base + offset);
|
||||
}
|
||||
|
||||
-static void airoha_wr(void __iomem *base, u32 offset, u32 val)
|
||||
+void airoha_wr(void __iomem *base, u32 offset, u32 val)
|
||||
{
|
||||
writel(val, base + offset);
|
||||
}
|
||||
|
||||
-static u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
|
||||
+u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val)
|
||||
{
|
||||
val |= (airoha_rr(base, offset) & ~mask);
|
||||
airoha_wr(base, offset, val);
|
||||
@@ -691,28 +691,6 @@ static u32 airoha_rmw(void __iomem *base
|
||||
return val;
|
||||
}
|
||||
|
||||
-#define airoha_fe_rr(eth, offset) \
|
||||
- airoha_rr((eth)->fe_regs, (offset))
|
||||
-#define airoha_fe_wr(eth, offset, val) \
|
||||
- airoha_wr((eth)->fe_regs, (offset), (val))
|
||||
-#define airoha_fe_rmw(eth, offset, mask, val) \
|
||||
- airoha_rmw((eth)->fe_regs, (offset), (mask), (val))
|
||||
-#define airoha_fe_set(eth, offset, val) \
|
||||
- airoha_rmw((eth)->fe_regs, (offset), 0, (val))
|
||||
-#define airoha_fe_clear(eth, offset, val) \
|
||||
- airoha_rmw((eth)->fe_regs, (offset), (val), 0)
|
||||
-
|
||||
-#define airoha_qdma_rr(qdma, offset) \
|
||||
- airoha_rr((qdma)->regs, (offset))
|
||||
-#define airoha_qdma_wr(qdma, offset, val) \
|
||||
- airoha_wr((qdma)->regs, (offset), (val))
|
||||
-#define airoha_qdma_rmw(qdma, offset, mask, val) \
|
||||
- airoha_rmw((qdma)->regs, (offset), (mask), (val))
|
||||
-#define airoha_qdma_set(qdma, offset, val) \
|
||||
- airoha_rmw((qdma)->regs, (offset), 0, (val))
|
||||
-#define airoha_qdma_clear(qdma, offset, val) \
|
||||
- airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
-
|
||||
static void airoha_qdma_set_irqmask(struct airoha_qdma *qdma, int index,
|
||||
u32 clear, u32 set)
|
||||
{
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -248,4 +248,30 @@ struct airoha_eth {
|
||||
struct airoha_gdm_port *ports[AIROHA_MAX_NUM_GDM_PORTS];
|
||||
};
|
||||
|
||||
+u32 airoha_rr(void __iomem *base, u32 offset);
|
||||
+void airoha_wr(void __iomem *base, u32 offset, u32 val);
|
||||
+u32 airoha_rmw(void __iomem *base, u32 offset, u32 mask, u32 val);
|
||||
+
|
||||
+#define airoha_fe_rr(eth, offset) \
|
||||
+ airoha_rr((eth)->fe_regs, (offset))
|
||||
+#define airoha_fe_wr(eth, offset, val) \
|
||||
+ airoha_wr((eth)->fe_regs, (offset), (val))
|
||||
+#define airoha_fe_rmw(eth, offset, mask, val) \
|
||||
+ airoha_rmw((eth)->fe_regs, (offset), (mask), (val))
|
||||
+#define airoha_fe_set(eth, offset, val) \
|
||||
+ airoha_rmw((eth)->fe_regs, (offset), 0, (val))
|
||||
+#define airoha_fe_clear(eth, offset, val) \
|
||||
+ airoha_rmw((eth)->fe_regs, (offset), (val), 0)
|
||||
+
|
||||
+#define airoha_qdma_rr(qdma, offset) \
|
||||
+ airoha_rr((qdma)->regs, (offset))
|
||||
+#define airoha_qdma_wr(qdma, offset, val) \
|
||||
+ airoha_wr((qdma)->regs, (offset), (val))
|
||||
+#define airoha_qdma_rmw(qdma, offset, mask, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (mask), (val))
|
||||
+#define airoha_qdma_set(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), 0, (val))
|
||||
+#define airoha_qdma_clear(qdma, offset, val) \
|
||||
+ airoha_rmw((qdma)->regs, (offset), (val), 0)
|
||||
+
|
||||
#endif /* AIROHA_ETH_H */
|
File diff suppressed because it is too large
Load Diff
@@ -1,287 +0,0 @@
|
||||
From af3cf757d5c99011b9b94ea8d78aeaccc0153fdc Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:13 +0100
|
||||
Subject: [PATCH 05/15] net: airoha: Move DSA tag in DMA descriptor
|
||||
|
||||
Packet Processor Engine (PPE) module reads DSA tags from the DMA descriptor
|
||||
and requires untagged DSA packets to properly parse them. Move DSA tag
|
||||
in the DMA descriptor on TX side and read DSA tag from DMA descriptor
|
||||
on RX side. In order to avoid skb reallocation, store tag in skb_dst on
|
||||
RX side.
|
||||
This is a preliminary patch to enable netfilter flowtable hw offloading
|
||||
on EN7581 SoC.
|
||||
|
||||
Tested-by: Sayantan Nandy <sayantan.nandy@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 125 ++++++++++++++++++++--
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 7 ++
|
||||
drivers/net/ethernet/airoha/airoha_regs.h | 2 +
|
||||
3 files changed, 128 insertions(+), 6 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <linux/tcp.h>
|
||||
#include <linux/u64_stats_sync.h>
|
||||
#include <net/dsa.h>
|
||||
+#include <net/dst_metadata.h>
|
||||
#include <net/page_pool/helpers.h>
|
||||
#include <net/pkt_cls.h>
|
||||
#include <uapi/linux/ppp_defs.h>
|
||||
@@ -656,6 +657,7 @@ static int airoha_qdma_rx_process(struct
|
||||
struct airoha_qdma_desc *desc = &q->desc[q->tail];
|
||||
dma_addr_t dma_addr = le32_to_cpu(desc->addr);
|
||||
u32 desc_ctrl = le32_to_cpu(desc->ctrl);
|
||||
+ struct airoha_gdm_port *port;
|
||||
struct sk_buff *skb;
|
||||
int len, p;
|
||||
|
||||
@@ -683,6 +685,7 @@ static int airoha_qdma_rx_process(struct
|
||||
continue;
|
||||
}
|
||||
|
||||
+ port = eth->ports[p];
|
||||
skb = napi_build_skb(e->buf, q->buf_size);
|
||||
if (!skb) {
|
||||
page_pool_put_full_page(q->page_pool,
|
||||
@@ -694,10 +697,26 @@ static int airoha_qdma_rx_process(struct
|
||||
skb_reserve(skb, 2);
|
||||
__skb_put(skb, len);
|
||||
skb_mark_for_recycle(skb);
|
||||
- skb->dev = eth->ports[p]->dev;
|
||||
+ skb->dev = port->dev;
|
||||
skb->protocol = eth_type_trans(skb, skb->dev);
|
||||
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
||||
skb_record_rx_queue(skb, qid);
|
||||
+
|
||||
+ if (netdev_uses_dsa(port->dev)) {
|
||||
+ /* PPE module requires untagged packets to work
|
||||
+ * properly and it provides DSA port index via the
|
||||
+ * DMA descriptor. Report DSA tag to the DSA stack
|
||||
+ * via skb dst info.
|
||||
+ */
|
||||
+ u32 sptag = FIELD_GET(QDMA_ETH_RXMSG_SPTAG,
|
||||
+ le32_to_cpu(desc->msg0));
|
||||
+
|
||||
+ if (sptag < ARRAY_SIZE(port->dsa_meta) &&
|
||||
+ port->dsa_meta[sptag])
|
||||
+ skb_dst_set_noref(skb,
|
||||
+ &port->dsa_meta[sptag]->dst);
|
||||
+ }
|
||||
+
|
||||
napi_gro_receive(&q->napi, skb);
|
||||
|
||||
done++;
|
||||
@@ -1637,25 +1656,76 @@ static u16 airoha_dev_select_queue(struc
|
||||
return queue < dev->num_tx_queues ? queue : 0;
|
||||
}
|
||||
|
||||
+static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev)
|
||||
+{
|
||||
+#if IS_ENABLED(CONFIG_NET_DSA)
|
||||
+ struct ethhdr *ehdr;
|
||||
+ struct dsa_port *dp;
|
||||
+ u8 xmit_tpid;
|
||||
+ u16 tag;
|
||||
+
|
||||
+ if (!netdev_uses_dsa(dev))
|
||||
+ return 0;
|
||||
+
|
||||
+ dp = dev->dsa_ptr;
|
||||
+ if (IS_ERR(dp))
|
||||
+ return 0;
|
||||
+
|
||||
+ if (dp->tag_ops->proto != DSA_TAG_PROTO_MTK)
|
||||
+ return 0;
|
||||
+
|
||||
+ if (skb_cow_head(skb, 0))
|
||||
+ return 0;
|
||||
+
|
||||
+ ehdr = (struct ethhdr *)skb->data;
|
||||
+ tag = be16_to_cpu(ehdr->h_proto);
|
||||
+ xmit_tpid = tag >> 8;
|
||||
+
|
||||
+ switch (xmit_tpid) {
|
||||
+ case MTK_HDR_XMIT_TAGGED_TPID_8100:
|
||||
+ ehdr->h_proto = cpu_to_be16(ETH_P_8021Q);
|
||||
+ tag &= ~(MTK_HDR_XMIT_TAGGED_TPID_8100 << 8);
|
||||
+ break;
|
||||
+ case MTK_HDR_XMIT_TAGGED_TPID_88A8:
|
||||
+ ehdr->h_proto = cpu_to_be16(ETH_P_8021AD);
|
||||
+ tag &= ~(MTK_HDR_XMIT_TAGGED_TPID_88A8 << 8);
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* PPE module requires untagged DSA packets to work properly,
|
||||
+ * so move DSA tag to DMA descriptor.
|
||||
+ */
|
||||
+ memmove(skb->data + MTK_HDR_LEN, skb->data, 2 * ETH_ALEN);
|
||||
+ __skb_pull(skb, MTK_HDR_LEN);
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return tag;
|
||||
+#else
|
||||
+ return 0;
|
||||
+#endif
|
||||
+}
|
||||
+
|
||||
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
|
||||
struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
- u32 nr_frags = 1 + skb_shinfo(skb)->nr_frags;
|
||||
- u32 msg0, msg1, len = skb_headlen(skb);
|
||||
struct airoha_qdma *qdma = port->qdma;
|
||||
+ u32 nr_frags, tag, msg0, msg1, len;
|
||||
struct netdev_queue *txq;
|
||||
struct airoha_queue *q;
|
||||
- void *data = skb->data;
|
||||
+ void *data;
|
||||
int i, qid;
|
||||
u16 index;
|
||||
u8 fport;
|
||||
|
||||
qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx);
|
||||
+ tag = airoha_get_dsa_tag(skb, dev);
|
||||
+
|
||||
msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK,
|
||||
qid / AIROHA_NUM_QOS_QUEUES) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK,
|
||||
- qid % AIROHA_NUM_QOS_QUEUES);
|
||||
+ qid % AIROHA_NUM_QOS_QUEUES) |
|
||||
+ FIELD_PREP(QDMA_ETH_TXMSG_SP_TAG_MASK, tag);
|
||||
if (skb->ip_summed == CHECKSUM_PARTIAL)
|
||||
msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) |
|
||||
FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) |
|
||||
@@ -1686,6 +1756,8 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
spin_lock_bh(&q->lock);
|
||||
|
||||
txq = netdev_get_tx_queue(dev, qid);
|
||||
+ nr_frags = 1 + skb_shinfo(skb)->nr_frags;
|
||||
+
|
||||
if (q->queued + nr_frags > q->ndesc) {
|
||||
/* not enough space in the queue */
|
||||
netif_tx_stop_queue(txq);
|
||||
@@ -1693,7 +1765,10 @@ static netdev_tx_t airoha_dev_xmit(struc
|
||||
return NETDEV_TX_BUSY;
|
||||
}
|
||||
|
||||
+ len = skb_headlen(skb);
|
||||
+ data = skb->data;
|
||||
index = q->head;
|
||||
+
|
||||
for (i = 0; i < nr_frags; i++) {
|
||||
struct airoha_qdma_desc *desc = &q->desc[index];
|
||||
struct airoha_queue_entry *e = &q->entry[index];
|
||||
@@ -2224,6 +2299,37 @@ static const struct ethtool_ops airoha_e
|
||||
.get_rmon_stats = airoha_ethtool_get_rmon_stats,
|
||||
};
|
||||
|
||||
+static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(port->dsa_meta); i++) {
|
||||
+ struct metadata_dst *md_dst;
|
||||
+
|
||||
+ md_dst = metadata_dst_alloc(0, METADATA_HW_PORT_MUX,
|
||||
+ GFP_KERNEL);
|
||||
+ if (!md_dst)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ md_dst->u.port_info.port_id = i;
|
||||
+ port->dsa_meta[i] = md_dst;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_metadata_dst_free(struct airoha_gdm_port *port)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(port->dsa_meta); i++) {
|
||||
+ if (!port->dsa_meta[i])
|
||||
+ continue;
|
||||
+
|
||||
+ metadata_dst_free(port->dsa_meta[i]);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
|
||||
{
|
||||
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
|
||||
@@ -2296,6 +2402,10 @@ static int airoha_alloc_gdm_port(struct
|
||||
port->id = id;
|
||||
eth->ports[index] = port;
|
||||
|
||||
+ err = airoha_metadata_dst_alloc(port);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
return register_netdev(dev);
|
||||
}
|
||||
|
||||
@@ -2388,8 +2498,10 @@ error_hw_cleanup:
|
||||
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
|
||||
struct airoha_gdm_port *port = eth->ports[i];
|
||||
|
||||
- if (port && port->dev->reg_state == NETREG_REGISTERED)
|
||||
+ if (port && port->dev->reg_state == NETREG_REGISTERED) {
|
||||
unregister_netdev(port->dev);
|
||||
+ airoha_metadata_dst_free(port);
|
||||
+ }
|
||||
}
|
||||
free_netdev(eth->napi_dev);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
@@ -2415,6 +2527,7 @@ static void airoha_remove(struct platfor
|
||||
|
||||
airoha_dev_stop(port->dev);
|
||||
unregister_netdev(port->dev);
|
||||
+ airoha_metadata_dst_free(port);
|
||||
}
|
||||
free_netdev(eth->napi_dev);
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
#define AIROHA_MAX_NUM_QDMA 2
|
||||
+#define AIROHA_MAX_DSA_PORTS 7
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
#define AIROHA_MAX_NUM_XSI_RSTS 5
|
||||
#define AIROHA_MAX_MTU 2000
|
||||
@@ -43,6 +44,10 @@
|
||||
#define QDMA_METER_IDX(_n) ((_n) & 0xff)
|
||||
#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3)
|
||||
|
||||
+#define MTK_HDR_LEN 4
|
||||
+#define MTK_HDR_XMIT_TAGGED_TPID_8100 1
|
||||
+#define MTK_HDR_XMIT_TAGGED_TPID_88A8 2
|
||||
+
|
||||
enum {
|
||||
QDMA_INT_REG_IDX0,
|
||||
QDMA_INT_REG_IDX1,
|
||||
@@ -231,6 +236,8 @@ struct airoha_gdm_port {
|
||||
/* qos stats counters */
|
||||
u64 cpu_tx_packets;
|
||||
u64 fwd_tx_packets;
|
||||
+
|
||||
+ struct metadata_dst *dsa_meta[AIROHA_MAX_DSA_PORTS];
|
||||
};
|
||||
|
||||
struct airoha_eth {
|
||||
--- a/drivers/net/ethernet/airoha/airoha_regs.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
|
||||
@@ -624,6 +624,8 @@
|
||||
#define QDMA_ETH_TXMSG_ACNT_G1_MASK GENMASK(10, 6) /* 0x1f do not count */
|
||||
#define QDMA_ETH_TXMSG_ACNT_G0_MASK GENMASK(5, 0) /* 0x3f do not count */
|
||||
|
||||
+/* RX MSG0 */
|
||||
+#define QDMA_ETH_RXMSG_SPTAG GENMASK(21, 14)
|
||||
/* RX MSG1 */
|
||||
#define QDMA_ETH_RXMSG_DEI_MASK BIT(31)
|
||||
#define QDMA_ETH_RXMSG_IP6_MASK BIT(30)
|
@@ -1,46 +0,0 @@
|
||||
From ab667db1e6014634c6607ebdddc16c1b8394a935 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:14 +0100
|
||||
Subject: [PATCH 06/15] net: dsa: mt7530: Enable Rx sptag for EN7581 SoC
|
||||
|
||||
Packet Processor Engine (PPE) module used for hw acceleration on EN7581
|
||||
mac block, in order to properly parse packets, requires DSA untagged
|
||||
packets on TX side and read DSA tag from DMA descriptor on RX side.
|
||||
For this reason, enable RX Special Tag (SPTAG) for EN7581 SoC.
|
||||
This is a preliminary patch to enable netfilter flowtable hw offloading
|
||||
on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/dsa/mt7530.c | 5 +++++
|
||||
drivers/net/dsa/mt7530.h | 4 ++++
|
||||
2 files changed, 9 insertions(+)
|
||||
|
||||
--- a/drivers/net/dsa/mt7530.c
|
||||
+++ b/drivers/net/dsa/mt7530.c
|
||||
@@ -2588,6 +2588,11 @@ mt7531_setup_common(struct dsa_switch *d
|
||||
/* Allow mirroring frames received on the local port (monitor port). */
|
||||
mt7530_set(priv, MT753X_AGC, LOCAL_EN);
|
||||
|
||||
+ /* Enable Special Tag for rx frames */
|
||||
+ if (priv->id == ID_EN7581)
|
||||
+ mt7530_write(priv, MT753X_CPORT_SPTAG_CFG,
|
||||
+ CPORT_SW2FE_STAG_EN | CPORT_FE2SW_STAG_EN);
|
||||
+
|
||||
/* Flush the FDB table */
|
||||
ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
|
||||
if (ret < 0)
|
||||
--- a/drivers/net/dsa/mt7530.h
|
||||
+++ b/drivers/net/dsa/mt7530.h
|
||||
@@ -615,6 +615,10 @@ enum mt7531_xtal_fsel {
|
||||
#define MT7531_GPIO12_RG_RXD3_MASK GENMASK(19, 16)
|
||||
#define MT7531_EXT_P_MDIO_12 (2 << 16)
|
||||
|
||||
+#define MT753X_CPORT_SPTAG_CFG 0x7c10
|
||||
+#define CPORT_SW2FE_STAG_EN BIT(1)
|
||||
+#define CPORT_FE2SW_STAG_EN BIT(0)
|
||||
+
|
||||
/* Registers for LED GPIO control (MT7530 only)
|
||||
* All registers follow this pattern:
|
||||
* [ 2: 0] port 0
|
@@ -1,144 +0,0 @@
|
||||
From 80369686737fe07c233a1152da0b84372dabdcd6 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:15 +0100
|
||||
Subject: [PATCH 07/15] net: airoha: Enable support for multiple net_devices
|
||||
|
||||
In the current codebase airoha_eth driver supports just a single
|
||||
net_device connected to the Packet Switch Engine (PSE) lan port (GDM1).
|
||||
As shown in commit 23020f049327 ("net: airoha: Introduce ethernet
|
||||
support for EN7581 SoC"), PSE can switch packets between four GDM ports.
|
||||
Enable the capability to create a net_device for each GDM port of the
|
||||
PSE module. Moreover, since the QDMA blocks can be shared between
|
||||
net_devices, do not stop TX/RX DMA in airoha_dev_stop() if there are
|
||||
active net_devices for this QDMA block.
|
||||
This is a preliminary patch to enable flowtable hw offloading for EN7581
|
||||
SoC.
|
||||
|
||||
Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 35 ++++++++++++++----------
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 4 ++-
|
||||
2 files changed, 24 insertions(+), 15 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -1563,6 +1563,7 @@ static int airoha_dev_open(struct net_de
|
||||
airoha_qdma_set(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ atomic_inc(&qdma->users);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1578,16 +1579,20 @@ static int airoha_dev_stop(struct net_de
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
- airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
- GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
- GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++)
|
||||
+ netdev_tx_reset_subqueue(dev, i);
|
||||
|
||||
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
- if (!qdma->q_tx[i].ndesc)
|
||||
- continue;
|
||||
+ if (atomic_dec_and_test(&qdma->users)) {
|
||||
+ airoha_qdma_clear(qdma, REG_QDMA_GLOBAL_CFG,
|
||||
+ GLOBAL_CFG_TX_DMA_EN_MASK |
|
||||
+ GLOBAL_CFG_RX_DMA_EN_MASK);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
|
||||
+ if (!qdma->q_tx[i].ndesc)
|
||||
+ continue;
|
||||
|
||||
- airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
|
||||
- netdev_tx_reset_subqueue(dev, i);
|
||||
+ airoha_qdma_cleanup_tx_queue(&qdma->q_tx[i]);
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -2330,13 +2335,14 @@ static void airoha_metadata_dst_free(str
|
||||
}
|
||||
}
|
||||
|
||||
-static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
|
||||
+static int airoha_alloc_gdm_port(struct airoha_eth *eth,
|
||||
+ struct device_node *np, int index)
|
||||
{
|
||||
const __be32 *id_ptr = of_get_property(np, "reg", NULL);
|
||||
struct airoha_gdm_port *port;
|
||||
struct airoha_qdma *qdma;
|
||||
struct net_device *dev;
|
||||
- int err, index;
|
||||
+ int err, p;
|
||||
u32 id;
|
||||
|
||||
if (!id_ptr) {
|
||||
@@ -2345,14 +2351,14 @@ static int airoha_alloc_gdm_port(struct
|
||||
}
|
||||
|
||||
id = be32_to_cpup(id_ptr);
|
||||
- index = id - 1;
|
||||
+ p = id - 1;
|
||||
|
||||
if (!id || id > ARRAY_SIZE(eth->ports)) {
|
||||
dev_err(eth->dev, "invalid gdm port id: %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (eth->ports[index]) {
|
||||
+ if (eth->ports[p]) {
|
||||
dev_err(eth->dev, "duplicate gdm port id: %d\n", id);
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -2400,7 +2406,7 @@ static int airoha_alloc_gdm_port(struct
|
||||
port->qdma = qdma;
|
||||
port->dev = dev;
|
||||
port->id = id;
|
||||
- eth->ports[index] = port;
|
||||
+ eth->ports[p] = port;
|
||||
|
||||
err = airoha_metadata_dst_alloc(port);
|
||||
if (err)
|
||||
@@ -2472,6 +2478,7 @@ static int airoha_probe(struct platform_
|
||||
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
|
||||
airoha_qdma_start_napi(ð->qdma[i]);
|
||||
|
||||
+ i = 0;
|
||||
for_each_child_of_node(pdev->dev.of_node, np) {
|
||||
if (!of_device_is_compatible(np, "airoha,eth-mac"))
|
||||
continue;
|
||||
@@ -2479,7 +2486,7 @@ static int airoha_probe(struct platform_
|
||||
if (!of_device_is_available(np))
|
||||
continue;
|
||||
|
||||
- err = airoha_alloc_gdm_port(eth, np);
|
||||
+ err = airoha_alloc_gdm_port(eth, np, i++);
|
||||
if (err) {
|
||||
of_node_put(np);
|
||||
goto error_napi_stop;
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -13,7 +13,7 @@
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
-#define AIROHA_MAX_NUM_GDM_PORTS 1
|
||||
+#define AIROHA_MAX_NUM_GDM_PORTS 4
|
||||
#define AIROHA_MAX_NUM_QDMA 2
|
||||
#define AIROHA_MAX_DSA_PORTS 7
|
||||
#define AIROHA_MAX_NUM_RSTS 3
|
||||
@@ -212,6 +212,8 @@ struct airoha_qdma {
|
||||
u32 irqmask[QDMA_INT_REG_MAX];
|
||||
int irq;
|
||||
|
||||
+ atomic_t users;
|
||||
+
|
||||
struct airoha_tx_irq_queue q_tx_irq[AIROHA_NUM_TX_IRQ];
|
||||
|
||||
struct airoha_queue q_tx[AIROHA_NUM_TX_RING];
|
@@ -1,77 +0,0 @@
|
||||
From 67fde5d58cd43d129a979e918ec9cd5d2e2fbcfb Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:16 +0100
|
||||
Subject: [PATCH 08/15] net: airoha: Move REG_GDM_FWD_CFG() initialization in
|
||||
airoha_dev_init()
|
||||
|
||||
Move REG_GDM_FWD_CFG() register initialization in airoha_dev_init
|
||||
routine. Moreover, always send traffic PPE module in order to be
|
||||
processed by hw accelerator.
|
||||
This is a preliminary patch to enable netfilter flowtable hw offloading
|
||||
on EN7581 SoC.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 14 ++++----------
|
||||
1 file changed, 4 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -107,25 +107,20 @@ static void airoha_set_gdm_port_fwd_cfg(
|
||||
|
||||
static int airoha_set_gdm_port(struct airoha_eth *eth, int port, bool enable)
|
||||
{
|
||||
- u32 val = enable ? FE_PSE_PORT_PPE1 : FE_PSE_PORT_DROP;
|
||||
- u32 vip_port, cfg_addr;
|
||||
+ u32 vip_port;
|
||||
|
||||
switch (port) {
|
||||
case XSI_PCIE0_PORT:
|
||||
vip_port = XSI_PCIE0_VIP_PORT_MASK;
|
||||
- cfg_addr = REG_GDM_FWD_CFG(3);
|
||||
break;
|
||||
case XSI_PCIE1_PORT:
|
||||
vip_port = XSI_PCIE1_VIP_PORT_MASK;
|
||||
- cfg_addr = REG_GDM_FWD_CFG(3);
|
||||
break;
|
||||
case XSI_USB_PORT:
|
||||
vip_port = XSI_USB_VIP_PORT_MASK;
|
||||
- cfg_addr = REG_GDM_FWD_CFG(4);
|
||||
break;
|
||||
case XSI_ETH_PORT:
|
||||
vip_port = XSI_ETH_VIP_PORT_MASK;
|
||||
- cfg_addr = REG_GDM_FWD_CFG(4);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
@@ -139,8 +134,6 @@ static int airoha_set_gdm_port(struct ai
|
||||
airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, vip_port);
|
||||
}
|
||||
|
||||
- airoha_set_gdm_port_fwd_cfg(eth, cfg_addr, val);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -177,8 +170,6 @@ static void airoha_fe_maccr_init(struct
|
||||
airoha_fe_set(eth, REG_GDM_FWD_CFG(p),
|
||||
GDM_TCP_CKSUM | GDM_UDP_CKSUM | GDM_IP4_CKSUM |
|
||||
GDM_DROP_CRC_ERR);
|
||||
- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(p),
|
||||
- FE_PSE_PORT_CDM1);
|
||||
airoha_fe_rmw(eth, REG_GDM_LEN_CFG(p),
|
||||
GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
|
||||
FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
|
||||
@@ -1615,8 +1606,11 @@ static int airoha_dev_set_macaddr(struct
|
||||
static int airoha_dev_init(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
|
||||
airoha_set_macaddr(port, dev->dev_addr);
|
||||
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id),
|
||||
+ FE_PSE_PORT_PPE1);
|
||||
|
||||
return 0;
|
||||
}
|
@@ -1,120 +0,0 @@
|
||||
From c28b8375f6d02ef3b5e8c51234cc3f6d47d9fb7f Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:17 +0100
|
||||
Subject: [PATCH 09/15] net: airoha: Rename airoha_set_gdm_port_fwd_cfg() in
|
||||
airoha_set_vip_for_gdm_port()
|
||||
|
||||
Rename airoha_set_gdm_port() in airoha_set_vip_for_gdm_port().
|
||||
Get rid of airoha_set_gdm_ports routine.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 49 ++++++------------------
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 8 ----
|
||||
2 files changed, 11 insertions(+), 46 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -105,25 +105,23 @@ static void airoha_set_gdm_port_fwd_cfg(
|
||||
FIELD_PREP(GDM_UCFQ_MASK, val));
|
||||
}
|
||||
|
||||
-static int airoha_set_gdm_port(struct airoha_eth *eth, int port, bool enable)
|
||||
+static int airoha_set_vip_for_gdm_port(struct airoha_gdm_port *port,
|
||||
+ bool enable)
|
||||
{
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
u32 vip_port;
|
||||
|
||||
- switch (port) {
|
||||
- case XSI_PCIE0_PORT:
|
||||
+ switch (port->id) {
|
||||
+ case 3:
|
||||
+ /* FIXME: handle XSI_PCIE1_PORT */
|
||||
vip_port = XSI_PCIE0_VIP_PORT_MASK;
|
||||
break;
|
||||
- case XSI_PCIE1_PORT:
|
||||
- vip_port = XSI_PCIE1_VIP_PORT_MASK;
|
||||
- break;
|
||||
- case XSI_USB_PORT:
|
||||
- vip_port = XSI_USB_VIP_PORT_MASK;
|
||||
- break;
|
||||
- case XSI_ETH_PORT:
|
||||
+ case 4:
|
||||
+ /* FIXME: handle XSI_USB_PORT */
|
||||
vip_port = XSI_ETH_VIP_PORT_MASK;
|
||||
break;
|
||||
default:
|
||||
- return -EINVAL;
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
@@ -137,31 +135,6 @@ static int airoha_set_gdm_port(struct ai
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int airoha_set_gdm_ports(struct airoha_eth *eth, bool enable)
|
||||
-{
|
||||
- const int port_list[] = {
|
||||
- XSI_PCIE0_PORT,
|
||||
- XSI_PCIE1_PORT,
|
||||
- XSI_USB_PORT,
|
||||
- XSI_ETH_PORT
|
||||
- };
|
||||
- int i, err;
|
||||
-
|
||||
- for (i = 0; i < ARRAY_SIZE(port_list); i++) {
|
||||
- err = airoha_set_gdm_port(eth, port_list[i], enable);
|
||||
- if (err)
|
||||
- goto error;
|
||||
- }
|
||||
-
|
||||
- return 0;
|
||||
-
|
||||
-error:
|
||||
- for (i--; i >= 0; i--)
|
||||
- airoha_set_gdm_port(eth, port_list[i], false);
|
||||
-
|
||||
- return err;
|
||||
-}
|
||||
-
|
||||
static void airoha_fe_maccr_init(struct airoha_eth *eth)
|
||||
{
|
||||
int p;
|
||||
@@ -1540,7 +1513,7 @@ static int airoha_dev_open(struct net_de
|
||||
int err;
|
||||
|
||||
netif_tx_start_all_queues(dev);
|
||||
- err = airoha_set_gdm_ports(qdma->eth, true);
|
||||
+ err = airoha_set_vip_for_gdm_port(port, true);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
@@ -1566,7 +1539,7 @@ static int airoha_dev_stop(struct net_de
|
||||
int i, err;
|
||||
|
||||
netif_tx_disable(dev);
|
||||
- err = airoha_set_gdm_ports(qdma->eth, false);
|
||||
+ err = airoha_set_vip_for_gdm_port(port, false);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -58,14 +58,6 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
- XSI_PCIE0_PORT,
|
||||
- XSI_PCIE1_PORT,
|
||||
- XSI_USB_PORT,
|
||||
- XSI_AE_PORT,
|
||||
- XSI_ETH_PORT,
|
||||
-};
|
||||
-
|
||||
-enum {
|
||||
XSI_PCIE0_VIP_PORT_MASK = BIT(22),
|
||||
XSI_PCIE1_VIP_PORT_MASK = BIT(23),
|
||||
XSI_USB_VIP_PORT_MASK = BIT(25),
|
@@ -1,627 +0,0 @@
|
||||
From 23290c7bc190def4e1ca61610992d9b7c32e33f3 Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:20 +0100
|
||||
Subject: [PATCH 12/15] net: airoha: Introduce Airoha NPU support
|
||||
|
||||
Packet Processor Engine (PPE) module available on EN7581 SoC populates
|
||||
the PPE table with 5-tuples flower rules learned from traffic forwarded
|
||||
between the GDM ports connected to the Packet Switch Engine (PSE) module.
|
||||
The airoha_eth driver can enable hw acceleration of learned 5-tuples
|
||||
rules if the user configure them in netfilter flowtable (netfilter
|
||||
flowtable support will be added with subsequent patches).
|
||||
airoha_eth driver configures and collects data from the PPE module via a
|
||||
Network Processor Unit (NPU) RISC-V module available on the EN7581 SoC.
|
||||
Introduce basic support for Airoha NPU module.
|
||||
|
||||
Tested-by: Sayantan Nandy <sayantan.nandy@airoha.com>
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/Kconfig | 9 +
|
||||
drivers/net/ethernet/airoha/Makefile | 1 +
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 2 +
|
||||
drivers/net/ethernet/airoha/airoha_npu.c | 520 +++++++++++++++++++++++
|
||||
drivers/net/ethernet/airoha/airoha_npu.h | 34 ++
|
||||
5 files changed, 566 insertions(+)
|
||||
create mode 100644 drivers/net/ethernet/airoha/airoha_npu.c
|
||||
create mode 100644 drivers/net/ethernet/airoha/airoha_npu.h
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/Kconfig
|
||||
+++ b/drivers/net/ethernet/airoha/Kconfig
|
||||
@@ -7,9 +7,18 @@ config NET_VENDOR_AIROHA
|
||||
|
||||
if NET_VENDOR_AIROHA
|
||||
|
||||
+config NET_AIROHA_NPU
|
||||
+ tristate "Airoha NPU support"
|
||||
+ select WANT_DEV_COREDUMP
|
||||
+ select REGMAP_MMIO
|
||||
+ help
|
||||
+ This driver supports Airoha Network Processor (NPU) available
|
||||
+ on the Airoha Soc family.
|
||||
+
|
||||
config NET_AIROHA
|
||||
tristate "Airoha SoC Gigabit Ethernet support"
|
||||
depends on NET_DSA || !NET_DSA
|
||||
+ select NET_AIROHA_NPU
|
||||
select PAGE_POOL
|
||||
help
|
||||
This driver supports the gigabit ethernet MACs in the
|
||||
--- a/drivers/net/ethernet/airoha/Makefile
|
||||
+++ b/drivers/net/ethernet/airoha/Makefile
|
||||
@@ -4,3 +4,4 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_NET_AIROHA) += airoha_eth.o
|
||||
+obj-$(CONFIG_NET_AIROHA_NPU) += airoha_npu.o
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -240,6 +240,8 @@ struct airoha_eth {
|
||||
unsigned long state;
|
||||
void __iomem *fe_regs;
|
||||
|
||||
+ struct airoha_npu __rcu *npu;
|
||||
+
|
||||
struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
|
||||
struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
|
||||
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_npu.c
|
||||
@@ -0,0 +1,520 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2025 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/devcoredump.h>
|
||||
+#include <linux/firmware.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/of_net.h>
|
||||
+#include <linux/of_platform.h>
|
||||
+#include <linux/of_reserved_mem.h>
|
||||
+#include <linux/regmap.h>
|
||||
+
|
||||
+#include "airoha_npu.h"
|
||||
+
|
||||
+#define NPU_EN7581_FIRMWARE_DATA "airoha/en7581_npu_data.bin"
|
||||
+#define NPU_EN7581_FIRMWARE_RV32 "airoha/en7581_npu_rv32.bin"
|
||||
+#define NPU_EN7581_FIRMWARE_RV32_MAX_SIZE 0x200000
|
||||
+#define NPU_EN7581_FIRMWARE_DATA_MAX_SIZE 0x10000
|
||||
+#define NPU_DUMP_SIZE 512
|
||||
+
|
||||
+#define REG_NPU_LOCAL_SRAM 0x0
|
||||
+
|
||||
+#define NPU_PC_BASE_ADDR 0x305000
|
||||
+#define REG_PC_DBG(_n) (0x305000 + ((_n) * 0x100))
|
||||
+
|
||||
+#define NPU_CLUSTER_BASE_ADDR 0x306000
|
||||
+
|
||||
+#define REG_CR_BOOT_TRIGGER (NPU_CLUSTER_BASE_ADDR + 0x000)
|
||||
+#define REG_CR_BOOT_CONFIG (NPU_CLUSTER_BASE_ADDR + 0x004)
|
||||
+#define REG_CR_BOOT_BASE(_n) (NPU_CLUSTER_BASE_ADDR + 0x020 + ((_n) << 2))
|
||||
+
|
||||
+#define NPU_MBOX_BASE_ADDR 0x30c000
|
||||
+
|
||||
+#define REG_CR_MBOX_INT_STATUS (NPU_MBOX_BASE_ADDR + 0x000)
|
||||
+#define MBOX_INT_STATUS_MASK BIT(8)
|
||||
+
|
||||
+#define REG_CR_MBOX_INT_MASK(_n) (NPU_MBOX_BASE_ADDR + 0x004 + ((_n) << 2))
|
||||
+#define REG_CR_MBQ0_CTRL(_n) (NPU_MBOX_BASE_ADDR + 0x030 + ((_n) << 2))
|
||||
+#define REG_CR_MBQ8_CTRL(_n) (NPU_MBOX_BASE_ADDR + 0x0b0 + ((_n) << 2))
|
||||
+#define REG_CR_NPU_MIB(_n) (NPU_MBOX_BASE_ADDR + 0x140 + ((_n) << 2))
|
||||
+
|
||||
+#define NPU_TIMER_BASE_ADDR 0x310100
|
||||
+#define REG_WDT_TIMER_CTRL(_n) (NPU_TIMER_BASE_ADDR + ((_n) * 0x100))
|
||||
+#define WDT_EN_MASK BIT(25)
|
||||
+#define WDT_INTR_MASK BIT(21)
|
||||
+
|
||||
+enum {
|
||||
+ NPU_OP_SET = 1,
|
||||
+ NPU_OP_SET_NO_WAIT,
|
||||
+ NPU_OP_GET,
|
||||
+ NPU_OP_GET_NO_WAIT,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ NPU_FUNC_WIFI,
|
||||
+ NPU_FUNC_TUNNEL,
|
||||
+ NPU_FUNC_NOTIFY,
|
||||
+ NPU_FUNC_DBA,
|
||||
+ NPU_FUNC_TR471,
|
||||
+ NPU_FUNC_PPE,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ NPU_MBOX_ERROR,
|
||||
+ NPU_MBOX_SUCCESS,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ PPE_FUNC_SET_WAIT,
|
||||
+ PPE_FUNC_SET_WAIT_HWNAT_INIT,
|
||||
+ PPE_FUNC_SET_WAIT_HWNAT_DEINIT,
|
||||
+ PPE_FUNC_SET_WAIT_API,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ PPE2_SRAM_SET_ENTRY,
|
||||
+ PPE_SRAM_SET_ENTRY,
|
||||
+ PPE_SRAM_SET_VAL,
|
||||
+ PPE_SRAM_RESET_VAL,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ QDMA_WAN_ETHER = 1,
|
||||
+ QDMA_WAN_PON_XDSL,
|
||||
+};
|
||||
+
|
||||
+#define MBOX_MSG_FUNC_ID GENMASK(14, 11)
|
||||
+#define MBOX_MSG_STATIC_BUF BIT(5)
|
||||
+#define MBOX_MSG_STATUS GENMASK(4, 2)
|
||||
+#define MBOX_MSG_DONE BIT(1)
|
||||
+#define MBOX_MSG_WAIT_RSP BIT(0)
|
||||
+
|
||||
+#define PPE_TYPE_L2B_IPV4 2
|
||||
+#define PPE_TYPE_L2B_IPV4_IPV6 3
|
||||
+
|
||||
+struct ppe_mbox_data {
|
||||
+ u32 func_type;
|
||||
+ u32 func_id;
|
||||
+ union {
|
||||
+ struct {
|
||||
+ u8 cds;
|
||||
+ u8 xpon_hal_api;
|
||||
+ u8 wan_xsi;
|
||||
+ u8 ct_joyme4;
|
||||
+ int ppe_type;
|
||||
+ int wan_mode;
|
||||
+ int wan_sel;
|
||||
+ } init_info;
|
||||
+ struct {
|
||||
+ int func_id;
|
||||
+ u32 size;
|
||||
+ u32 data;
|
||||
+ } set_info;
|
||||
+ };
|
||||
+};
|
||||
+
|
||||
+static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,
|
||||
+ void *p, int size)
|
||||
+{
|
||||
+ u16 core = 0; /* FIXME */
|
||||
+ u32 val, offset = core << 4;
|
||||
+ dma_addr_t dma_addr;
|
||||
+ void *addr;
|
||||
+ int ret;
|
||||
+
|
||||
+ addr = kmemdup(p, size, GFP_ATOMIC);
|
||||
+ if (!addr)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ dma_addr = dma_map_single(npu->dev, addr, size, DMA_TO_DEVICE);
|
||||
+ ret = dma_mapping_error(npu->dev, dma_addr);
|
||||
+ if (ret)
|
||||
+ goto out;
|
||||
+
|
||||
+ spin_lock_bh(&npu->cores[core].lock);
|
||||
+
|
||||
+ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(0) + offset, dma_addr);
|
||||
+ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(1) + offset, size);
|
||||
+ regmap_read(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, &val);
|
||||
+ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(2) + offset, val + 1);
|
||||
+ val = FIELD_PREP(MBOX_MSG_FUNC_ID, func_id) | MBOX_MSG_WAIT_RSP;
|
||||
+ regmap_write(npu->regmap, REG_CR_MBQ0_CTRL(3) + offset, val);
|
||||
+
|
||||
+ ret = regmap_read_poll_timeout_atomic(npu->regmap,
|
||||
+ REG_CR_MBQ0_CTRL(3) + offset,
|
||||
+ val, (val & MBOX_MSG_DONE),
|
||||
+ 100, 100 * MSEC_PER_SEC);
|
||||
+ if (!ret && FIELD_GET(MBOX_MSG_STATUS, val) != NPU_MBOX_SUCCESS)
|
||||
+ ret = -EINVAL;
|
||||
+
|
||||
+ spin_unlock_bh(&npu->cores[core].lock);
|
||||
+
|
||||
+ dma_unmap_single(npu->dev, dma_addr, size, DMA_TO_DEVICE);
|
||||
+out:
|
||||
+ kfree(addr);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int airoha_npu_run_firmware(struct device *dev, void __iomem *base,
|
||||
+ struct reserved_mem *rmem)
|
||||
+{
|
||||
+ const struct firmware *fw;
|
||||
+ void __iomem *addr;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_RV32, dev);
|
||||
+ if (ret)
|
||||
+ return ret == -ENOENT ? -EPROBE_DEFER : ret;
|
||||
+
|
||||
+ if (fw->size > NPU_EN7581_FIRMWARE_RV32_MAX_SIZE) {
|
||||
+ dev_err(dev, "%s: fw size too overlimit (%zu)\n",
|
||||
+ NPU_EN7581_FIRMWARE_RV32, fw->size);
|
||||
+ ret = -E2BIG;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ addr = devm_ioremap(dev, rmem->base, rmem->size);
|
||||
+ if (!addr) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy_toio(addr, fw->data, fw->size);
|
||||
+ release_firmware(fw);
|
||||
+
|
||||
+ ret = request_firmware(&fw, NPU_EN7581_FIRMWARE_DATA, dev);
|
||||
+ if (ret)
|
||||
+ return ret == -ENOENT ? -EPROBE_DEFER : ret;
|
||||
+
|
||||
+ if (fw->size > NPU_EN7581_FIRMWARE_DATA_MAX_SIZE) {
|
||||
+ dev_err(dev, "%s: fw size too overlimit (%zu)\n",
|
||||
+ NPU_EN7581_FIRMWARE_DATA, fw->size);
|
||||
+ ret = -E2BIG;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy_toio(base + REG_NPU_LOCAL_SRAM, fw->data, fw->size);
|
||||
+out:
|
||||
+ release_firmware(fw);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t airoha_npu_mbox_handler(int irq, void *npu_instance)
|
||||
+{
|
||||
+ struct airoha_npu *npu = npu_instance;
|
||||
+
|
||||
+ /* clear mbox interrupt status */
|
||||
+ regmap_write(npu->regmap, REG_CR_MBOX_INT_STATUS,
|
||||
+ MBOX_INT_STATUS_MASK);
|
||||
+
|
||||
+ /* acknowledge npu */
|
||||
+ regmap_update_bits(npu->regmap, REG_CR_MBQ8_CTRL(3),
|
||||
+ MBOX_MSG_STATUS | MBOX_MSG_DONE, MBOX_MSG_DONE);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static void airoha_npu_wdt_work(struct work_struct *work)
|
||||
+{
|
||||
+ struct airoha_npu_core *core;
|
||||
+ struct airoha_npu *npu;
|
||||
+ void *dump;
|
||||
+ u32 val[3];
|
||||
+ int c;
|
||||
+
|
||||
+ core = container_of(work, struct airoha_npu_core, wdt_work);
|
||||
+ npu = core->npu;
|
||||
+
|
||||
+ dump = vzalloc(NPU_DUMP_SIZE);
|
||||
+ if (!dump)
|
||||
+ return;
|
||||
+
|
||||
+ c = core - &npu->cores[0];
|
||||
+ regmap_bulk_read(npu->regmap, REG_PC_DBG(c), val, ARRAY_SIZE(val));
|
||||
+ snprintf(dump, NPU_DUMP_SIZE, "PC: %08x SP: %08x LR: %08x\n",
|
||||
+ val[0], val[1], val[2]);
|
||||
+
|
||||
+ dev_coredumpv(npu->dev, dump, NPU_DUMP_SIZE, GFP_KERNEL);
|
||||
+}
|
||||
+
|
||||
+static irqreturn_t airoha_npu_wdt_handler(int irq, void *core_instance)
|
||||
+{
|
||||
+ struct airoha_npu_core *core = core_instance;
|
||||
+ struct airoha_npu *npu = core->npu;
|
||||
+ int c = core - &npu->cores[0];
|
||||
+ u32 val;
|
||||
+
|
||||
+ regmap_set_bits(npu->regmap, REG_WDT_TIMER_CTRL(c), WDT_INTR_MASK);
|
||||
+ if (!regmap_read(npu->regmap, REG_WDT_TIMER_CTRL(c), &val) &&
|
||||
+ FIELD_GET(WDT_EN_MASK, val))
|
||||
+ schedule_work(&core->wdt_work);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static int airoha_npu_ppe_init(struct airoha_npu *npu)
|
||||
+{
|
||||
+ struct ppe_mbox_data ppe_data = {
|
||||
+ .func_type = NPU_OP_SET,
|
||||
+ .func_id = PPE_FUNC_SET_WAIT_HWNAT_INIT,
|
||||
+ .init_info = {
|
||||
+ .ppe_type = PPE_TYPE_L2B_IPV4_IPV6,
|
||||
+ .wan_mode = QDMA_WAN_ETHER,
|
||||
+ },
|
||||
+ };
|
||||
+
|
||||
+ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
|
||||
+ sizeof(struct ppe_mbox_data));
|
||||
+}
|
||||
+
|
||||
+static int airoha_npu_ppe_deinit(struct airoha_npu *npu)
|
||||
+{
|
||||
+ struct ppe_mbox_data ppe_data = {
|
||||
+ .func_type = NPU_OP_SET,
|
||||
+ .func_id = PPE_FUNC_SET_WAIT_HWNAT_DEINIT,
|
||||
+ };
|
||||
+
|
||||
+ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
|
||||
+ sizeof(struct ppe_mbox_data));
|
||||
+}
|
||||
+
|
||||
+static int airoha_npu_ppe_flush_sram_entries(struct airoha_npu *npu,
|
||||
+ dma_addr_t foe_addr,
|
||||
+ int sram_num_entries)
|
||||
+{
|
||||
+ struct ppe_mbox_data ppe_data = {
|
||||
+ .func_type = NPU_OP_SET,
|
||||
+ .func_id = PPE_FUNC_SET_WAIT_API,
|
||||
+ .set_info = {
|
||||
+ .func_id = PPE_SRAM_RESET_VAL,
|
||||
+ .data = foe_addr,
|
||||
+ .size = sram_num_entries,
|
||||
+ },
|
||||
+ };
|
||||
+
|
||||
+ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
|
||||
+ sizeof(struct ppe_mbox_data));
|
||||
+}
|
||||
+
|
||||
+static int airoha_npu_foe_commit_entry(struct airoha_npu *npu,
|
||||
+ dma_addr_t foe_addr,
|
||||
+ u32 entry_size, u32 hash, bool ppe2)
|
||||
+{
|
||||
+ struct ppe_mbox_data ppe_data = {
|
||||
+ .func_type = NPU_OP_SET,
|
||||
+ .func_id = PPE_FUNC_SET_WAIT_API,
|
||||
+ .set_info = {
|
||||
+ .data = foe_addr,
|
||||
+ .size = entry_size,
|
||||
+ },
|
||||
+ };
|
||||
+ int err;
|
||||
+
|
||||
+ ppe_data.set_info.func_id = ppe2 ? PPE2_SRAM_SET_ENTRY
|
||||
+ : PPE_SRAM_SET_ENTRY;
|
||||
+
|
||||
+ err = airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
|
||||
+ sizeof(struct ppe_mbox_data));
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ ppe_data.set_info.func_id = PPE_SRAM_SET_VAL;
|
||||
+ ppe_data.set_info.data = hash;
|
||||
+ ppe_data.set_info.size = sizeof(u32);
|
||||
+
|
||||
+ return airoha_npu_send_msg(npu, NPU_FUNC_PPE, &ppe_data,
|
||||
+ sizeof(struct ppe_mbox_data));
|
||||
+}
|
||||
+
|
||||
+struct airoha_npu *airoha_npu_get(struct device *dev)
|
||||
+{
|
||||
+ struct platform_device *pdev;
|
||||
+ struct device_node *np;
|
||||
+ struct airoha_npu *npu;
|
||||
+
|
||||
+ np = of_parse_phandle(dev->of_node, "airoha,npu", 0);
|
||||
+ if (!np)
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
+
|
||||
+ pdev = of_find_device_by_node(np);
|
||||
+ of_node_put(np);
|
||||
+
|
||||
+ if (!pdev) {
|
||||
+ dev_err(dev, "cannot find device node %s\n", np->name);
|
||||
+ return ERR_PTR(-ENODEV);
|
||||
+ }
|
||||
+
|
||||
+ if (!try_module_get(THIS_MODULE)) {
|
||||
+ dev_err(dev, "failed to get the device driver module\n");
|
||||
+ npu = ERR_PTR(-ENODEV);
|
||||
+ goto error_pdev_put;
|
||||
+ }
|
||||
+
|
||||
+ npu = platform_get_drvdata(pdev);
|
||||
+ if (!npu) {
|
||||
+ npu = ERR_PTR(-ENODEV);
|
||||
+ goto error_module_put;
|
||||
+ }
|
||||
+
|
||||
+ if (!device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER)) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "failed to create device link to consumer %s\n",
|
||||
+ dev_name(dev));
|
||||
+ npu = ERR_PTR(-EINVAL);
|
||||
+ goto error_module_put;
|
||||
+ }
|
||||
+
|
||||
+ return npu;
|
||||
+
|
||||
+error_module_put:
|
||||
+ module_put(THIS_MODULE);
|
||||
+error_pdev_put:
|
||||
+ platform_device_put(pdev);
|
||||
+
|
||||
+ return npu;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(airoha_npu_get);
|
||||
+
|
||||
+void airoha_npu_put(struct airoha_npu *npu)
|
||||
+{
|
||||
+ module_put(THIS_MODULE);
|
||||
+ put_device(npu->dev);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(airoha_npu_put);
|
||||
+
|
||||
+static const struct of_device_id of_airoha_npu_match[] = {
|
||||
+ { .compatible = "airoha,en7581-npu" },
|
||||
+ { /* sentinel */ }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, of_airoha_npu_match);
|
||||
+
|
||||
+static const struct regmap_config regmap_config = {
|
||||
+ .name = "npu",
|
||||
+ .reg_bits = 32,
|
||||
+ .val_bits = 32,
|
||||
+ .reg_stride = 4,
|
||||
+ .disable_locking = true,
|
||||
+};
|
||||
+
|
||||
+static int airoha_npu_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct device *dev = &pdev->dev;
|
||||
+ struct reserved_mem *rmem;
|
||||
+ struct airoha_npu *npu;
|
||||
+ struct device_node *np;
|
||||
+ void __iomem *base;
|
||||
+ int i, irq, err;
|
||||
+
|
||||
+ base = devm_platform_ioremap_resource(pdev, 0);
|
||||
+ if (IS_ERR(base))
|
||||
+ return PTR_ERR(base);
|
||||
+
|
||||
+ npu = devm_kzalloc(dev, sizeof(*npu), GFP_KERNEL);
|
||||
+ if (!npu)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ npu->dev = dev;
|
||||
+ npu->ops.ppe_init = airoha_npu_ppe_init;
|
||||
+ npu->ops.ppe_deinit = airoha_npu_ppe_deinit;
|
||||
+ npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries;
|
||||
+ npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry;
|
||||
+
|
||||
+ npu->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
|
||||
+ if (IS_ERR(npu->regmap))
|
||||
+ return PTR_ERR(npu->regmap);
|
||||
+
|
||||
+ np = of_parse_phandle(dev->of_node, "memory-region", 0);
|
||||
+ if (!np)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ rmem = of_reserved_mem_lookup(np);
|
||||
+ of_node_put(np);
|
||||
+
|
||||
+ if (!rmem)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ err = devm_request_irq(dev, irq, airoha_npu_mbox_handler,
|
||||
+ IRQF_SHARED, "airoha-npu-mbox", npu);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(npu->cores); i++) {
|
||||
+ struct airoha_npu_core *core = &npu->cores[i];
|
||||
+
|
||||
+ spin_lock_init(&core->lock);
|
||||
+ core->npu = npu;
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, i + 1);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ err = devm_request_irq(dev, irq, airoha_npu_wdt_handler,
|
||||
+ IRQF_SHARED, "airoha-npu-wdt", core);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ INIT_WORK(&core->wdt_work, airoha_npu_wdt_work);
|
||||
+ }
|
||||
+
|
||||
+ err = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = airoha_npu_run_firmware(dev, base, rmem);
|
||||
+ if (err)
|
||||
+ return dev_err_probe(dev, err, "failed to run npu firmware\n");
|
||||
+
|
||||
+ regmap_write(npu->regmap, REG_CR_NPU_MIB(10),
|
||||
+ rmem->base + NPU_EN7581_FIRMWARE_RV32_MAX_SIZE);
|
||||
+ regmap_write(npu->regmap, REG_CR_NPU_MIB(11), 0x40000); /* SRAM 256K */
|
||||
+ regmap_write(npu->regmap, REG_CR_NPU_MIB(12), 0);
|
||||
+ regmap_write(npu->regmap, REG_CR_NPU_MIB(21), 1);
|
||||
+ msleep(100);
|
||||
+
|
||||
+ /* setting booting address */
|
||||
+ for (i = 0; i < NPU_NUM_CORES; i++)
|
||||
+ regmap_write(npu->regmap, REG_CR_BOOT_BASE(i), rmem->base);
|
||||
+ usleep_range(1000, 2000);
|
||||
+
|
||||
+ /* enable NPU cores */
|
||||
+ /* do not start core3 since it is used for WiFi offloading */
|
||||
+ regmap_write(npu->regmap, REG_CR_BOOT_CONFIG, 0xf7);
|
||||
+ regmap_write(npu->regmap, REG_CR_BOOT_TRIGGER, 0x1);
|
||||
+ msleep(100);
|
||||
+
|
||||
+ platform_set_drvdata(pdev, npu);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void airoha_npu_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct airoha_npu *npu = platform_get_drvdata(pdev);
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(npu->cores); i++)
|
||||
+ cancel_work_sync(&npu->cores[i].wdt_work);
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver airoha_npu_driver = {
|
||||
+ .probe = airoha_npu_probe,
|
||||
+ .remove_new = airoha_npu_remove,
|
||||
+ .driver = {
|
||||
+ .name = "airoha-npu",
|
||||
+ .of_match_table = of_airoha_npu_match,
|
||||
+ },
|
||||
+};
|
||||
+module_platform_driver(airoha_npu_driver);
|
||||
+
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Lorenzo Bianconi <lorenzo@kernel.org>");
|
||||
+MODULE_DESCRIPTION("Airoha Network Processor Unit driver");
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_npu.h
|
||||
@@ -0,0 +1,34 @@
|
||||
+/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
+/*
|
||||
+ * Copyright (c) 2025 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#define NPU_NUM_CORES 8
|
||||
+
|
||||
+struct airoha_npu {
|
||||
+ struct device *dev;
|
||||
+ struct regmap *regmap;
|
||||
+
|
||||
+ struct airoha_npu_core {
|
||||
+ struct airoha_npu *npu;
|
||||
+ /* protect concurrent npu memory accesses */
|
||||
+ spinlock_t lock;
|
||||
+ struct work_struct wdt_work;
|
||||
+ } cores[NPU_NUM_CORES];
|
||||
+
|
||||
+ struct {
|
||||
+ int (*ppe_init)(struct airoha_npu *npu);
|
||||
+ int (*ppe_deinit)(struct airoha_npu *npu);
|
||||
+ int (*ppe_flush_sram_entries)(struct airoha_npu *npu,
|
||||
+ dma_addr_t foe_addr,
|
||||
+ int sram_num_entries);
|
||||
+ int (*ppe_foe_commit_entry)(struct airoha_npu *npu,
|
||||
+ dma_addr_t foe_addr,
|
||||
+ u32 entry_size, u32 hash,
|
||||
+ bool ppe2);
|
||||
+ } ops;
|
||||
+};
|
||||
+
|
||||
+struct airoha_npu *airoha_npu_get(struct device *dev);
|
||||
+void airoha_npu_put(struct airoha_npu *npu);
|
File diff suppressed because it is too large
Load Diff
@@ -1,210 +0,0 @@
|
||||
From 9cd451d414f6e29f507a216fb3b19fa68c011f8c Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:22 +0100
|
||||
Subject: [PATCH 14/15] net: airoha: Add loopback support for GDM2
|
||||
|
||||
Enable hw redirection for traffic received on GDM2 port to GDM{3,4}.
|
||||
This is required to apply Qdisc offloading (HTB or ETS) for traffic to
|
||||
and from GDM{3,4} port.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/airoha_eth.c | 71 ++++++++++++++++++++++-
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 7 +++
|
||||
drivers/net/ethernet/airoha/airoha_ppe.c | 12 ++--
|
||||
drivers/net/ethernet/airoha/airoha_regs.h | 29 +++++++++
|
||||
4 files changed, 111 insertions(+), 8 deletions(-)
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.c
|
||||
@@ -1589,14 +1589,81 @@ static int airoha_dev_set_macaddr(struct
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
|
||||
+{
|
||||
+ u32 pse_port = port->id == 3 ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4;
|
||||
+ struct airoha_eth *eth = port->qdma->eth;
|
||||
+ u32 chan = port->id == 3 ? 4 : 0;
|
||||
+
|
||||
+ /* Forward the traffic to the proper GDM port */
|
||||
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(2), pse_port);
|
||||
+ airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC);
|
||||
+
|
||||
+ /* Enable GDM2 loopback */
|
||||
+ airoha_fe_wr(eth, REG_GDM_TXCHN_EN(2), 0xffffffff);
|
||||
+ airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff);
|
||||
+ airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2),
|
||||
+ LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK,
|
||||
+ FIELD_PREP(LPBK_CHAN_MASK, chan) | LPBK_EN_MASK);
|
||||
+ airoha_fe_rmw(eth, REG_GDM_LEN_CFG(2),
|
||||
+ GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
|
||||
+ FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
|
||||
+ FIELD_PREP(GDM_LONG_LEN_MASK, AIROHA_MAX_MTU));
|
||||
+
|
||||
+ /* Disable VIP and IFC for GDM2 */
|
||||
+ airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2));
|
||||
+ airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2));
|
||||
+
|
||||
+ if (port->id == 3) {
|
||||
+ /* FIXME: handle XSI_PCE1_PORT */
|
||||
+ airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0), 0x5500);
|
||||
+ airoha_fe_rmw(eth, REG_FE_WAN_PORT,
|
||||
+ WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
|
||||
+ FIELD_PREP(WAN0_MASK, HSGMII_LAN_PCIE0_SRCPORT));
|
||||
+ airoha_fe_rmw(eth,
|
||||
+ REG_SP_DFT_CPORT(HSGMII_LAN_PCIE0_SRCPORT >> 3),
|
||||
+ SP_CPORT_PCIE0_MASK,
|
||||
+ FIELD_PREP(SP_CPORT_PCIE0_MASK,
|
||||
+ FE_PSE_PORT_CDM2));
|
||||
+ } else {
|
||||
+ /* FIXME: handle XSI_USB_PORT */
|
||||
+ airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6,
|
||||
+ FC_ID_OF_SRC_PORT24_MASK,
|
||||
+ FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2));
|
||||
+ airoha_fe_rmw(eth, REG_FE_WAN_PORT,
|
||||
+ WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
|
||||
+ FIELD_PREP(WAN0_MASK, HSGMII_LAN_ETH_SRCPORT));
|
||||
+ airoha_fe_rmw(eth,
|
||||
+ REG_SP_DFT_CPORT(HSGMII_LAN_ETH_SRCPORT >> 3),
|
||||
+ SP_CPORT_ETH_MASK,
|
||||
+ FIELD_PREP(SP_CPORT_ETH_MASK, FE_PSE_PORT_CDM2));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
static int airoha_dev_init(struct net_device *dev)
|
||||
{
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
struct airoha_eth *eth = port->qdma->eth;
|
||||
+ u32 pse_port;
|
||||
|
||||
airoha_set_macaddr(port, dev->dev_addr);
|
||||
- airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id),
|
||||
- FE_PSE_PORT_PPE1);
|
||||
+
|
||||
+ switch (port->id) {
|
||||
+ case 3:
|
||||
+ case 4:
|
||||
+ /* If GDM2 is active we can't enable loopback */
|
||||
+ if (!eth->ports[1])
|
||||
+ airhoha_set_gdm2_loopback(port);
|
||||
+ fallthrough;
|
||||
+ case 2:
|
||||
+ pse_port = FE_PSE_PORT_PPE2;
|
||||
+ break;
|
||||
+ default:
|
||||
+ pse_port = FE_PSE_PORT_PPE1;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -68,6 +68,13 @@ enum {
|
||||
};
|
||||
|
||||
enum {
|
||||
+ HSGMII_LAN_PCIE0_SRCPORT = 0x16,
|
||||
+ HSGMII_LAN_PCIE1_SRCPORT,
|
||||
+ HSGMII_LAN_ETH_SRCPORT,
|
||||
+ HSGMII_LAN_USB_SRCPORT,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
XSI_PCIE0_VIP_PORT_MASK = BIT(22),
|
||||
XSI_PCIE1_VIP_PORT_MASK = BIT(23),
|
||||
XSI_USB_VIP_PORT_MASK = BIT(25),
|
||||
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
|
||||
@@ -216,7 +216,8 @@ static int airoha_ppe_foe_entry_prepare(
|
||||
AIROHA_FOE_IB1_BIND_TTL;
|
||||
hwe->ib1 = val;
|
||||
|
||||
- val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f);
|
||||
+ val = FIELD_PREP(AIROHA_FOE_IB2_PORT_AG, 0x1f) |
|
||||
+ AIROHA_FOE_IB2_PSE_QOS;
|
||||
if (dsa_port >= 0)
|
||||
val |= FIELD_PREP(AIROHA_FOE_IB2_NBQ, dsa_port);
|
||||
|
||||
@@ -224,14 +225,13 @@ static int airoha_ppe_foe_entry_prepare(
|
||||
struct airoha_gdm_port *port = netdev_priv(dev);
|
||||
u8 pse_port;
|
||||
|
||||
- pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
|
||||
+ if (dsa_port >= 0)
|
||||
+ pse_port = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
|
||||
+ else
|
||||
+ pse_port = 2; /* uplink relies on GDM2 loopback */
|
||||
val |= FIELD_PREP(AIROHA_FOE_IB2_PSE_PORT, pse_port);
|
||||
}
|
||||
|
||||
- /* FIXME: implement QoS support setting pse_port to 2 (loopback)
|
||||
- * for uplink and setting qos bit in ib2
|
||||
- */
|
||||
-
|
||||
if (is_multicast_ether_addr(data->eth.h_dest))
|
||||
val |= AIROHA_FOE_IB2_MULTICAST;
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/airoha_regs.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
|
||||
@@ -38,6 +38,12 @@
|
||||
#define FE_RST_CORE_MASK BIT(0)
|
||||
|
||||
#define REG_FE_FOE_TS 0x0010
|
||||
+
|
||||
+#define REG_FE_WAN_PORT 0x0024
|
||||
+#define WAN1_EN_MASK BIT(16)
|
||||
+#define WAN1_MASK GENMASK(12, 8)
|
||||
+#define WAN0_MASK GENMASK(4, 0)
|
||||
+
|
||||
#define REG_FE_WAN_MAC_H 0x0030
|
||||
#define REG_FE_LAN_MAC_H 0x0040
|
||||
|
||||
@@ -126,6 +132,7 @@
|
||||
#define GDM_IP4_CKSUM BIT(22)
|
||||
#define GDM_TCP_CKSUM BIT(21)
|
||||
#define GDM_UDP_CKSUM BIT(20)
|
||||
+#define GDM_STRIP_CRC BIT(16)
|
||||
#define GDM_UCFQ_MASK GENMASK(15, 12)
|
||||
#define GDM_BCFQ_MASK GENMASK(11, 8)
|
||||
#define GDM_MCFQ_MASK GENMASK(7, 4)
|
||||
@@ -139,6 +146,16 @@
|
||||
#define GDM_SHORT_LEN_MASK GENMASK(13, 0)
|
||||
#define GDM_LONG_LEN_MASK GENMASK(29, 16)
|
||||
|
||||
+#define REG_GDM_LPBK_CFG(_n) (GDM_BASE(_n) + 0x1c)
|
||||
+#define LPBK_GAP_MASK GENMASK(31, 24)
|
||||
+#define LPBK_LEN_MASK GENMASK(23, 10)
|
||||
+#define LPBK_CHAN_MASK GENMASK(8, 4)
|
||||
+#define LPBK_MODE_MASK GENMASK(3, 1)
|
||||
+#define LPBK_EN_MASK BIT(0)
|
||||
+
|
||||
+#define REG_GDM_TXCHN_EN(_n) (GDM_BASE(_n) + 0x24)
|
||||
+#define REG_GDM_RXCHN_EN(_n) (GDM_BASE(_n) + 0x28)
|
||||
+
|
||||
#define REG_FE_CPORT_CFG (GDM1_BASE + 0x40)
|
||||
#define FE_CPORT_PAD BIT(26)
|
||||
#define FE_CPORT_PORT_XFC_MASK BIT(25)
|
||||
@@ -351,6 +368,18 @@
|
||||
|
||||
#define REG_MC_VLAN_DATA 0x2108
|
||||
|
||||
+#define REG_SP_DFT_CPORT(_n) (0x20e0 + ((_n) << 2))
|
||||
+#define SP_CPORT_PCIE1_MASK GENMASK(31, 28)
|
||||
+#define SP_CPORT_PCIE0_MASK GENMASK(27, 24)
|
||||
+#define SP_CPORT_USB_MASK GENMASK(7, 4)
|
||||
+#define SP_CPORT_ETH_MASK GENMASK(7, 4)
|
||||
+
|
||||
+#define REG_SRC_PORT_FC_MAP6 0x2298
|
||||
+#define FC_ID_OF_SRC_PORT27_MASK GENMASK(28, 24)
|
||||
+#define FC_ID_OF_SRC_PORT26_MASK GENMASK(20, 16)
|
||||
+#define FC_ID_OF_SRC_PORT25_MASK GENMASK(12, 8)
|
||||
+#define FC_ID_OF_SRC_PORT24_MASK GENMASK(4, 0)
|
||||
+
|
||||
#define REG_CDM5_RX_OQ1_DROP_CNT 0x29d4
|
||||
|
||||
/* QDMA */
|
@@ -1,291 +0,0 @@
|
||||
From 3fe15c640f3808c3faf235553c67c867d1389e5c Mon Sep 17 00:00:00 2001
|
||||
From: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Date: Fri, 28 Feb 2025 11:54:23 +0100
|
||||
Subject: [PATCH 15/15] net: airoha: Introduce PPE debugfs support
|
||||
|
||||
Similar to PPE support for Mediatek devices, introduce PPE debugfs
|
||||
in order to dump binded and unbinded flows.
|
||||
|
||||
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
|
||||
---
|
||||
drivers/net/ethernet/airoha/Makefile | 1 +
|
||||
drivers/net/ethernet/airoha/airoha_eth.h | 14 ++
|
||||
drivers/net/ethernet/airoha/airoha_ppe.c | 17 +-
|
||||
.../net/ethernet/airoha/airoha_ppe_debugfs.c | 181 ++++++++++++++++++
|
||||
4 files changed, 209 insertions(+), 4 deletions(-)
|
||||
create mode 100644 drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
|
||||
|
||||
--- a/drivers/net/ethernet/airoha/Makefile
|
||||
+++ b/drivers/net/ethernet/airoha/Makefile
|
||||
@@ -5,4 +5,5 @@
|
||||
|
||||
obj-$(CONFIG_NET_AIROHA) += airoha-eth.o
|
||||
airoha-eth-y := airoha_eth.o airoha_ppe.o
|
||||
+airoha-eth-$(CONFIG_DEBUG_FS) += airoha_ppe_debugfs.o
|
||||
obj-$(CONFIG_NET_AIROHA_NPU) += airoha_npu.o
|
||||
--- a/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef AIROHA_ETH_H
|
||||
#define AIROHA_ETH_H
|
||||
|
||||
+#include <linux/debugfs.h>
|
||||
#include <linux/etherdevice.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/kernel.h>
|
||||
@@ -480,6 +481,8 @@ struct airoha_ppe {
|
||||
|
||||
struct hlist_head *foe_flow;
|
||||
u16 foe_check_time[PPE_NUM_ENTRIES];
|
||||
+
|
||||
+ struct dentry *debugfs_dir;
|
||||
};
|
||||
|
||||
struct airoha_eth {
|
||||
@@ -533,5 +536,16 @@ int airoha_ppe_setup_tc_block_cb(enum tc
|
||||
void *cb_priv);
|
||||
int airoha_ppe_init(struct airoha_eth *eth);
|
||||
void airoha_ppe_deinit(struct airoha_eth *eth);
|
||||
+struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
|
||||
+ u32 hash);
|
||||
+
|
||||
+#if CONFIG_DEBUG_FS
|
||||
+int airoha_ppe_debugfs_init(struct airoha_ppe *ppe);
|
||||
+#else
|
||||
+static inline int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+#endif
|
||||
|
||||
#endif /* AIROHA_ETH_H */
|
||||
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
|
||||
@@ -390,8 +390,8 @@ static u32 airoha_ppe_foe_get_entry_hash
|
||||
return hash;
|
||||
}
|
||||
|
||||
-static struct airoha_foe_entry *
|
||||
-airoha_ppe_foe_get_entry(struct airoha_ppe *ppe, u32 hash)
|
||||
+struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
|
||||
+ u32 hash)
|
||||
{
|
||||
if (hash < PPE_SRAM_NUM_ENTRIES) {
|
||||
u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry);
|
||||
@@ -861,7 +861,7 @@ void airoha_ppe_check_skb(struct airoha_
|
||||
int airoha_ppe_init(struct airoha_eth *eth)
|
||||
{
|
||||
struct airoha_ppe *ppe;
|
||||
- int foe_size;
|
||||
+ int foe_size, err;
|
||||
|
||||
ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL);
|
||||
if (!ppe)
|
||||
@@ -882,7 +882,15 @@ int airoha_ppe_init(struct airoha_eth *e
|
||||
if (!ppe->foe_flow)
|
||||
return -ENOMEM;
|
||||
|
||||
- return rhashtable_init(ð->flow_table, &airoha_flow_table_params);
|
||||
+ err = rhashtable_init(ð->flow_table, &airoha_flow_table_params);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ err = airoha_ppe_debugfs_init(ppe);
|
||||
+ if (err)
|
||||
+ rhashtable_destroy(ð->flow_table);
|
||||
+
|
||||
+ return err;
|
||||
}
|
||||
|
||||
void airoha_ppe_deinit(struct airoha_eth *eth)
|
||||
@@ -898,4 +906,5 @@ void airoha_ppe_deinit(struct airoha_eth
|
||||
rcu_read_unlock();
|
||||
|
||||
rhashtable_destroy(ð->flow_table);
|
||||
+ debugfs_remove(eth->ppe->debugfs_dir);
|
||||
}
|
||||
--- /dev/null
|
||||
+++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
|
||||
@@ -0,0 +1,181 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-only
|
||||
+/*
|
||||
+ * Copyright (c) 2025 AIROHA Inc
|
||||
+ * Author: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
+ */
|
||||
+
|
||||
+#include "airoha_eth.h"
|
||||
+
|
||||
+static void airoha_debugfs_ppe_print_tuple(struct seq_file *m,
|
||||
+ void *src_addr, void *dest_addr,
|
||||
+ u16 *src_port, u16 *dest_port,
|
||||
+ bool ipv6)
|
||||
+{
|
||||
+ __be32 n_addr[IPV6_ADDR_WORDS];
|
||||
+
|
||||
+ if (ipv6) {
|
||||
+ ipv6_addr_cpu_to_be32(n_addr, src_addr);
|
||||
+ seq_printf(m, "%pI6", n_addr);
|
||||
+ } else {
|
||||
+ seq_printf(m, "%pI4h", src_addr);
|
||||
+ }
|
||||
+ if (src_port)
|
||||
+ seq_printf(m, ":%d", *src_port);
|
||||
+
|
||||
+ seq_puts(m, "->");
|
||||
+
|
||||
+ if (ipv6) {
|
||||
+ ipv6_addr_cpu_to_be32(n_addr, dest_addr);
|
||||
+ seq_printf(m, "%pI6", n_addr);
|
||||
+ } else {
|
||||
+ seq_printf(m, "%pI4h", dest_addr);
|
||||
+ }
|
||||
+ if (dest_port)
|
||||
+ seq_printf(m, ":%d", *dest_port);
|
||||
+}
|
||||
+
|
||||
+static int airoha_ppe_debugfs_foe_show(struct seq_file *m, void *private,
|
||||
+ bool bind)
|
||||
+{
|
||||
+ static const char *const ppe_type_str[] = {
|
||||
+ [PPE_PKT_TYPE_IPV4_HNAPT] = "IPv4 5T",
|
||||
+ [PPE_PKT_TYPE_IPV4_ROUTE] = "IPv4 3T",
|
||||
+ [PPE_PKT_TYPE_BRIDGE] = "L2B",
|
||||
+ [PPE_PKT_TYPE_IPV4_DSLITE] = "DS-LITE",
|
||||
+ [PPE_PKT_TYPE_IPV6_ROUTE_3T] = "IPv6 3T",
|
||||
+ [PPE_PKT_TYPE_IPV6_ROUTE_5T] = "IPv6 5T",
|
||||
+ [PPE_PKT_TYPE_IPV6_6RD] = "6RD",
|
||||
+ };
|
||||
+ static const char *const ppe_state_str[] = {
|
||||
+ [AIROHA_FOE_STATE_INVALID] = "INV",
|
||||
+ [AIROHA_FOE_STATE_UNBIND] = "UNB",
|
||||
+ [AIROHA_FOE_STATE_BIND] = "BND",
|
||||
+ [AIROHA_FOE_STATE_FIN] = "FIN",
|
||||
+ };
|
||||
+ struct airoha_ppe *ppe = m->private;
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < PPE_NUM_ENTRIES; i++) {
|
||||
+ const char *state_str, *type_str = "UNKNOWN";
|
||||
+ void *src_addr = NULL, *dest_addr = NULL;
|
||||
+ u16 *src_port = NULL, *dest_port = NULL;
|
||||
+ struct airoha_foe_mac_info_common *l2;
|
||||
+ unsigned char h_source[ETH_ALEN] = {};
|
||||
+ unsigned char h_dest[ETH_ALEN];
|
||||
+ struct airoha_foe_entry *hwe;
|
||||
+ u32 type, state, ib2, data;
|
||||
+ bool ipv6 = false;
|
||||
+
|
||||
+ hwe = airoha_ppe_foe_get_entry(ppe, i);
|
||||
+ if (!hwe)
|
||||
+ continue;
|
||||
+
|
||||
+ state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
|
||||
+ if (!state)
|
||||
+ continue;
|
||||
+
|
||||
+ if (bind && state != AIROHA_FOE_STATE_BIND)
|
||||
+ continue;
|
||||
+
|
||||
+ state_str = ppe_state_str[state % ARRAY_SIZE(ppe_state_str)];
|
||||
+ type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
|
||||
+ if (type < ARRAY_SIZE(ppe_type_str) && ppe_type_str[type])
|
||||
+ type_str = ppe_type_str[type];
|
||||
+
|
||||
+ seq_printf(m, "%05x %s %7s", i, state_str, type_str);
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case PPE_PKT_TYPE_IPV4_HNAPT:
|
||||
+ case PPE_PKT_TYPE_IPV4_DSLITE:
|
||||
+ src_port = &hwe->ipv4.orig_tuple.src_port;
|
||||
+ dest_port = &hwe->ipv4.orig_tuple.dest_port;
|
||||
+ fallthrough;
|
||||
+ case PPE_PKT_TYPE_IPV4_ROUTE:
|
||||
+ src_addr = &hwe->ipv4.orig_tuple.src_ip;
|
||||
+ dest_addr = &hwe->ipv4.orig_tuple.dest_ip;
|
||||
+ break;
|
||||
+ case PPE_PKT_TYPE_IPV6_ROUTE_5T:
|
||||
+ src_port = &hwe->ipv6.src_port;
|
||||
+ dest_port = &hwe->ipv6.dest_port;
|
||||
+ fallthrough;
|
||||
+ case PPE_PKT_TYPE_IPV6_ROUTE_3T:
|
||||
+ case PPE_PKT_TYPE_IPV6_6RD:
|
||||
+ src_addr = &hwe->ipv6.src_ip;
|
||||
+ dest_addr = &hwe->ipv6.dest_ip;
|
||||
+ ipv6 = true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (src_addr && dest_addr) {
|
||||
+ seq_puts(m, " orig=");
|
||||
+ airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr,
|
||||
+ src_port, dest_port, ipv6);
|
||||
+ }
|
||||
+
|
||||
+ switch (type) {
|
||||
+ case PPE_PKT_TYPE_IPV4_HNAPT:
|
||||
+ case PPE_PKT_TYPE_IPV4_DSLITE:
|
||||
+ src_port = &hwe->ipv4.new_tuple.src_port;
|
||||
+ dest_port = &hwe->ipv4.new_tuple.dest_port;
|
||||
+ fallthrough;
|
||||
+ case PPE_PKT_TYPE_IPV4_ROUTE:
|
||||
+ src_addr = &hwe->ipv4.new_tuple.src_ip;
|
||||
+ dest_addr = &hwe->ipv4.new_tuple.dest_ip;
|
||||
+ seq_puts(m, " new=");
|
||||
+ airoha_debugfs_ppe_print_tuple(m, src_addr, dest_addr,
|
||||
+ src_port, dest_port,
|
||||
+ ipv6);
|
||||
+ break;
|
||||
+ default:
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (type >= PPE_PKT_TYPE_IPV6_ROUTE_3T) {
|
||||
+ data = hwe->ipv6.data;
|
||||
+ ib2 = hwe->ipv6.ib2;
|
||||
+ l2 = &hwe->ipv6.l2;
|
||||
+ } else {
|
||||
+ data = hwe->ipv4.data;
|
||||
+ ib2 = hwe->ipv4.ib2;
|
||||
+ l2 = &hwe->ipv4.l2.common;
|
||||
+ *((__be16 *)&h_source[4]) =
|
||||
+ cpu_to_be16(hwe->ipv4.l2.src_mac_lo);
|
||||
+ }
|
||||
+
|
||||
+ *((__be32 *)h_dest) = cpu_to_be32(l2->dest_mac_hi);
|
||||
+ *((__be16 *)&h_dest[4]) = cpu_to_be16(l2->dest_mac_lo);
|
||||
+ *((__be32 *)h_source) = cpu_to_be32(l2->src_mac_hi);
|
||||
+
|
||||
+ seq_printf(m, " eth=%pM->%pM etype=%04x data=%08x"
|
||||
+ " vlan=%d,%d ib1=%08x ib2=%08x\n",
|
||||
+ h_source, h_dest, l2->etype, data,
|
||||
+ l2->vlan1, l2->vlan2, hwe->ib1, ib2);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_ppe_debugfs_foe_all_show(struct seq_file *m, void *private)
|
||||
+{
|
||||
+ return airoha_ppe_debugfs_foe_show(m, private, false);
|
||||
+}
|
||||
+DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_all);
|
||||
+
|
||||
+static int airoha_ppe_debugfs_foe_bind_show(struct seq_file *m, void *private)
|
||||
+{
|
||||
+ return airoha_ppe_debugfs_foe_show(m, private, true);
|
||||
+}
|
||||
+DEFINE_SHOW_ATTRIBUTE(airoha_ppe_debugfs_foe_bind);
|
||||
+
|
||||
+int airoha_ppe_debugfs_init(struct airoha_ppe *ppe)
|
||||
+{
|
||||
+ ppe->debugfs_dir = debugfs_create_dir("ppe", NULL);
|
||||
+ debugfs_create_file("entries", 0444, ppe->debugfs_dir, ppe,
|
||||
+ &airoha_ppe_debugfs_foe_all_fops);
|
||||
+ debugfs_create_file("bind", 0444, ppe->debugfs_dir, ppe,
|
||||
+ &airoha_ppe_debugfs_foe_bind_fops);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
@@ -1,550 +0,0 @@
|
||||
From 42de37f40e1bc818df216dfa0918c114cfb5941d Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Sun, 11 May 2025 20:49:55 +0200
|
||||
Subject: [PATCH] thermal/drivers: Add support for Airoha EN7581 thermal sensor
|
||||
|
||||
Add support for Airoha EN7581 thermal sensor. This provide support for
|
||||
reading the CPU or SoC Package sensor and to setup trip points for hot
|
||||
and critical condition. An interrupt is fired to react on this and
|
||||
doesn't require passive poll to read the temperature.
|
||||
|
||||
The thermal regs provide a way to read the ADC value from an external
|
||||
register placed in the Chip SCU regs. Monitor will read this value and
|
||||
fire an interrupt if the trip condition configured is reached.
|
||||
|
||||
The Thermal Trip and Interrupt logic is conceptually similar to Mediatek
|
||||
LVTS Thermal but differ in register mapping and actual function/bug
|
||||
workaround. The implementation only share some register names but from
|
||||
functionality observation it's very different and used only for the
|
||||
basic function of periodically poll the temp and trip the interrupt.
|
||||
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20250511185003.3754495-2-ansuelsmth@gmail.com
|
||||
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
---
|
||||
drivers/thermal/Kconfig | 9 +
|
||||
drivers/thermal/Makefile | 1 +
|
||||
drivers/thermal/airoha_thermal.c | 489 +++++++++++++++++++++++++++++++
|
||||
3 files changed, 499 insertions(+)
|
||||
create mode 100644 drivers/thermal/airoha_thermal.c
|
||||
|
||||
--- a/drivers/thermal/Kconfig
|
||||
+++ b/drivers/thermal/Kconfig
|
||||
@@ -317,6 +317,15 @@ config QORIQ_THERMAL
|
||||
cpufreq is used as the cooling device to throttle CPUs when the
|
||||
passive trip is crossed.
|
||||
|
||||
+config AIROHA_THERMAL
|
||||
+ tristate "Airoha thermal sensor driver"
|
||||
+ depends on ARCH_AIROHA || COMPILE_TEST
|
||||
+ depends on MFD_SYSCON
|
||||
+ depends on OF
|
||||
+ help
|
||||
+ Enable this to plug the Airoha thermal sensor driver into the Linux
|
||||
+ thermal framework.
|
||||
+
|
||||
config SPEAR_THERMAL
|
||||
tristate "SPEAr thermal sensor driver"
|
||||
depends on PLAT_SPEAR || COMPILE_TEST
|
||||
--- a/drivers/thermal/Makefile
|
||||
+++ b/drivers/thermal/Makefile
|
||||
@@ -34,6 +34,7 @@ obj-$(CONFIG_K3_THERMAL) += k3_bandgap.o
|
||||
# platform thermal drivers
|
||||
obj-y += broadcom/
|
||||
obj-$(CONFIG_THERMAL_MMIO) += thermal_mmio.o
|
||||
+obj-$(CONFIG_AIROHA_THERMAL) += airoha_thermal.o
|
||||
obj-$(CONFIG_SPEAR_THERMAL) += spear_thermal.o
|
||||
obj-$(CONFIG_SUN8I_THERMAL) += sun8i_thermal.o
|
||||
obj-$(CONFIG_ROCKCHIP_THERMAL) += rockchip_thermal.o
|
||||
--- /dev/null
|
||||
+++ b/drivers/thermal/airoha_thermal.c
|
||||
@@ -0,0 +1,489 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/bitfield.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/interrupt.h>
|
||||
+#include <linux/mfd/syscon.h>
|
||||
+#include <linux/of.h>
|
||||
+#include <linux/of_address.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/regmap.h>
|
||||
+#include <linux/thermal.h>
|
||||
+
|
||||
+/* SCU regs */
|
||||
+#define EN7581_PLLRG_PROTECT 0x268
|
||||
+#define EN7581_PWD_TADC 0x2ec
|
||||
+#define EN7581_MUX_TADC GENMASK(3, 1)
|
||||
+#define EN7581_DOUT_TADC 0x2f8
|
||||
+#define EN7581_DOUT_TADC_MASK GENMASK(15, 0)
|
||||
+
|
||||
+/* PTP_THERMAL regs */
|
||||
+#define EN7581_TEMPMONCTL0 0x800
|
||||
+#define EN7581_SENSE3_EN BIT(3)
|
||||
+#define EN7581_SENSE2_EN BIT(2)
|
||||
+#define EN7581_SENSE1_EN BIT(1)
|
||||
+#define EN7581_SENSE0_EN BIT(0)
|
||||
+#define EN7581_TEMPMONCTL1 0x804
|
||||
+/* period unit calculated in BUS clock * 256 scaling-up */
|
||||
+#define EN7581_PERIOD_UNIT GENMASK(9, 0)
|
||||
+#define EN7581_TEMPMONCTL2 0x808
|
||||
+#define EN7581_FILT_INTERVAL GENMASK(25, 16)
|
||||
+#define EN7581_SEN_INTERVAL GENMASK(9, 0)
|
||||
+#define EN7581_TEMPMONINT 0x80C
|
||||
+#define EN7581_STAGE3_INT_EN BIT(31)
|
||||
+#define EN7581_STAGE2_INT_EN BIT(30)
|
||||
+#define EN7581_STAGE1_INT_EN BIT(29)
|
||||
+#define EN7581_FILTER_INT_EN_3 BIT(28)
|
||||
+#define EN7581_IMMD_INT_EN3 BIT(27)
|
||||
+#define EN7581_NOHOTINTEN3 BIT(26)
|
||||
+#define EN7581_HOFSINTEN3 BIT(25)
|
||||
+#define EN7581_LOFSINTEN3 BIT(24)
|
||||
+#define EN7581_HINTEN3 BIT(23)
|
||||
+#define EN7581_CINTEN3 BIT(22)
|
||||
+#define EN7581_FILTER_INT_EN_2 BIT(21)
|
||||
+#define EN7581_FILTER_INT_EN_1 BIT(20)
|
||||
+#define EN7581_FILTER_INT_EN_0 BIT(19)
|
||||
+#define EN7581_IMMD_INT_EN2 BIT(18)
|
||||
+#define EN7581_IMMD_INT_EN1 BIT(17)
|
||||
+#define EN7581_IMMD_INT_EN0 BIT(16)
|
||||
+#define EN7581_TIME_OUT_INT_EN BIT(15)
|
||||
+#define EN7581_NOHOTINTEN2 BIT(14)
|
||||
+#define EN7581_HOFSINTEN2 BIT(13)
|
||||
+#define EN7581_LOFSINTEN2 BIT(12)
|
||||
+#define EN7581_HINTEN2 BIT(11)
|
||||
+#define EN7581_CINTEN2 BIT(10)
|
||||
+#define EN7581_NOHOTINTEN1 BIT(9)
|
||||
+#define EN7581_HOFSINTEN1 BIT(8)
|
||||
+#define EN7581_LOFSINTEN1 BIT(7)
|
||||
+#define EN7581_HINTEN1 BIT(6)
|
||||
+#define EN7581_CINTEN1 BIT(5)
|
||||
+#define EN7581_NOHOTINTEN0 BIT(4)
|
||||
+/* Similar to COLD and HOT also these seems to be swapped in documentation */
|
||||
+#define EN7581_LOFSINTEN0 BIT(3) /* In documentation: BIT(2) */
|
||||
+#define EN7581_HOFSINTEN0 BIT(2) /* In documentation: BIT(3) */
|
||||
+/* It seems documentation have these swapped as the HW
|
||||
+ * - Fire BIT(1) when lower than EN7581_COLD_THRE
|
||||
+ * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or
|
||||
+ * EN7581_HOT_THRE
|
||||
+ */
|
||||
+#define EN7581_CINTEN0 BIT(1) /* In documentation: BIT(0) */
|
||||
+#define EN7581_HINTEN0 BIT(0) /* In documentation: BIT(1) */
|
||||
+#define EN7581_TEMPMONINTSTS 0x810
|
||||
+#define EN7581_STAGE3_INT_STAT BIT(31)
|
||||
+#define EN7581_STAGE2_INT_STAT BIT(30)
|
||||
+#define EN7581_STAGE1_INT_STAT BIT(29)
|
||||
+#define EN7581_FILTER_INT_STAT_3 BIT(28)
|
||||
+#define EN7581_IMMD_INT_STS3 BIT(27)
|
||||
+#define EN7581_NOHOTINTSTS3 BIT(26)
|
||||
+#define EN7581_HOFSINTSTS3 BIT(25)
|
||||
+#define EN7581_LOFSINTSTS3 BIT(24)
|
||||
+#define EN7581_HINTSTS3 BIT(23)
|
||||
+#define EN7581_CINTSTS3 BIT(22)
|
||||
+#define EN7581_FILTER_INT_STAT_2 BIT(21)
|
||||
+#define EN7581_FILTER_INT_STAT_1 BIT(20)
|
||||
+#define EN7581_FILTER_INT_STAT_0 BIT(19)
|
||||
+#define EN7581_IMMD_INT_STS2 BIT(18)
|
||||
+#define EN7581_IMMD_INT_STS1 BIT(17)
|
||||
+#define EN7581_IMMD_INT_STS0 BIT(16)
|
||||
+#define EN7581_TIME_OUT_INT_STAT BIT(15)
|
||||
+#define EN7581_NOHOTINTSTS2 BIT(14)
|
||||
+#define EN7581_HOFSINTSTS2 BIT(13)
|
||||
+#define EN7581_LOFSINTSTS2 BIT(12)
|
||||
+#define EN7581_HINTSTS2 BIT(11)
|
||||
+#define EN7581_CINTSTS2 BIT(10)
|
||||
+#define EN7581_NOHOTINTSTS1 BIT(9)
|
||||
+#define EN7581_HOFSINTSTS1 BIT(8)
|
||||
+#define EN7581_LOFSINTSTS1 BIT(7)
|
||||
+#define EN7581_HINTSTS1 BIT(6)
|
||||
+#define EN7581_CINTSTS1 BIT(5)
|
||||
+#define EN7581_NOHOTINTSTS0 BIT(4)
|
||||
+/* Similar to COLD and HOT also these seems to be swapped in documentation */
|
||||
+#define EN7581_LOFSINTSTS0 BIT(3) /* In documentation: BIT(2) */
|
||||
+#define EN7581_HOFSINTSTS0 BIT(2) /* In documentation: BIT(3) */
|
||||
+/* It seems documentation have these swapped as the HW
|
||||
+ * - Fire BIT(1) when lower than EN7581_COLD_THRE
|
||||
+ * - Fire BIT(0) and BIT(5) when higher than EN7581_HOT2NORMAL_THRE or
|
||||
+ * EN7581_HOT_THRE
|
||||
+ *
|
||||
+ * To clear things, we swap the define but we keep them documented here.
|
||||
+ */
|
||||
+#define EN7581_CINTSTS0 BIT(1) /* In documentation: BIT(0) */
|
||||
+#define EN7581_HINTSTS0 BIT(0) /* In documentation: BIT(1)*/
|
||||
+/* Monitor will take the bigger threshold between HOT2NORMAL and HOT
|
||||
+ * and will fire both HOT2NORMAL and HOT interrupt when higher than the 2
|
||||
+ *
|
||||
+ * It has also been observed that not setting HOT2NORMAL makes the monitor
|
||||
+ * treat COLD threshold as HOT2NORMAL.
|
||||
+ */
|
||||
+#define EN7581_TEMPH2NTHRE 0x824
|
||||
+/* It seems HOT2NORMAL is actually NORMAL2HOT */
|
||||
+#define EN7581_HOT2NORMAL_THRE GENMASK(11, 0)
|
||||
+#define EN7581_TEMPHTHRE 0x828
|
||||
+#define EN7581_HOT_THRE GENMASK(11, 0)
|
||||
+/* Monitor will use this as HOT2NORMAL (fire interrupt when lower than...)*/
|
||||
+#define EN7581_TEMPCTHRE 0x82c
|
||||
+#define EN7581_COLD_THRE GENMASK(11, 0)
|
||||
+/* Also LOW and HIGH offset register are swapped */
|
||||
+#define EN7581_TEMPOFFSETL 0x830 /* In documentation: 0x834 */
|
||||
+#define EN7581_LOW_OFFSET GENMASK(11, 0)
|
||||
+#define EN7581_TEMPOFFSETH 0x834 /* In documentation: 0x830 */
|
||||
+#define EN7581_HIGH_OFFSET GENMASK(11, 0)
|
||||
+#define EN7581_TEMPMSRCTL0 0x838
|
||||
+#define EN7581_MSRCTL3 GENMASK(11, 9)
|
||||
+#define EN7581_MSRCTL2 GENMASK(8, 6)
|
||||
+#define EN7581_MSRCTL1 GENMASK(5, 3)
|
||||
+#define EN7581_MSRCTL0 GENMASK(2, 0)
|
||||
+#define EN7581_TEMPADCVALIDADDR 0x878
|
||||
+#define EN7581_ADC_VALID_ADDR GENMASK(31, 0)
|
||||
+#define EN7581_TEMPADCVOLTADDR 0x87c
|
||||
+#define EN7581_ADC_VOLT_ADDR GENMASK(31, 0)
|
||||
+#define EN7581_TEMPRDCTRL 0x880
|
||||
+/*
|
||||
+ * NOTICE: AHB have this set to 0 by default. Means that
|
||||
+ * the same addr is used for ADC volt and valid reading.
|
||||
+ * In such case, VALID ADDR is used and volt addr is ignored.
|
||||
+ */
|
||||
+#define EN7581_RD_CTRL_DIFF BIT(0)
|
||||
+#define EN7581_TEMPADCVALIDMASK 0x884
|
||||
+#define EN7581_ADV_RD_VALID_POLARITY BIT(5)
|
||||
+#define EN7581_ADV_RD_VALID_POS GENMASK(4, 0)
|
||||
+#define EN7581_TEMPADCVOLTAGESHIFT 0x888
|
||||
+#define EN7581_ADC_VOLTAGE_SHIFT GENMASK(4, 0)
|
||||
+/*
|
||||
+ * Same values for each CTL.
|
||||
+ * Can operate in:
|
||||
+ * - 1 sample
|
||||
+ * - 2 sample and make average of them
|
||||
+ * - 4,6,10,16 sample, drop max and min and make avgerage of them
|
||||
+ */
|
||||
+#define EN7581_MSRCTL_1SAMPLE 0x0
|
||||
+#define EN7581_MSRCTL_AVG2SAMPLE 0x1
|
||||
+#define EN7581_MSRCTL_4SAMPLE_MAX_MIX_AVG2 0x2
|
||||
+#define EN7581_MSRCTL_6SAMPLE_MAX_MIX_AVG4 0x3
|
||||
+#define EN7581_MSRCTL_10SAMPLE_MAX_MIX_AVG8 0x4
|
||||
+#define EN7581_MSRCTL_18SAMPLE_MAX_MIX_AVG16 0x5
|
||||
+#define EN7581_TEMPAHBPOLL 0x840
|
||||
+#define EN7581_ADC_POLL_INTVL GENMASK(31, 0)
|
||||
+/* PTPSPARE0,2 reg are used to store efuse info for calibrated temp offset */
|
||||
+#define EN7581_EFUSE_TEMP_OFFSET_REG 0xf20 /* PTPSPARE0 */
|
||||
+#define EN7581_EFUSE_TEMP_OFFSET GENMASK(31, 16)
|
||||
+#define EN7581_PTPSPARE1 0xf24 /* PTPSPARE1 */
|
||||
+#define EN7581_EFUSE_TEMP_CPU_SENSOR_REG 0xf28 /* PTPSPARE2 */
|
||||
+
|
||||
+#define EN7581_SLOPE_X100_DIO_DEFAULT 5645
|
||||
+#define EN7581_SLOPE_X100_DIO_AVS 5645
|
||||
+
|
||||
+#define EN7581_INIT_TEMP_CPK_X10 300
|
||||
+#define EN7581_INIT_TEMP_FTK_X10 620
|
||||
+#define EN7581_INIT_TEMP_NONK_X10 550
|
||||
+
|
||||
+#define EN7581_SCU_THERMAL_PROTECT_KEY 0x12
|
||||
+#define EN7581_SCU_THERMAL_MUX_DIODE1 0x7
|
||||
+
|
||||
+/* 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) + \
|
||||
+ (priv)->default_offset)
|
||||
+
|
||||
+/* Convert raw to temp ((((temp - offset) * 1000) / slope + init) * 100) */
|
||||
+#define RAW_TO_TEMP(priv, raw) (((((raw) - (priv)->default_offset) * 1000) / \
|
||||
+ (priv)->default_slope + \
|
||||
+ (priv)->init_temp) * 100)
|
||||
+
|
||||
+#define AIROHA_MAX_SAMPLES 6
|
||||
+
|
||||
+struct airoha_thermal_priv {
|
||||
+ void __iomem *base;
|
||||
+ struct regmap *chip_scu;
|
||||
+ struct resource scu_adc_res;
|
||||
+
|
||||
+ struct thermal_zone_device *tz;
|
||||
+ int init_temp;
|
||||
+ int default_slope;
|
||||
+ int default_offset;
|
||||
+};
|
||||
+
|
||||
+static int airoha_get_thermal_ADC(struct airoha_thermal_priv *priv)
|
||||
+{
|
||||
+ u32 val;
|
||||
+
|
||||
+ regmap_read(priv->chip_scu, EN7581_DOUT_TADC, &val);
|
||||
+ return FIELD_GET(EN7581_DOUT_TADC_MASK, val);
|
||||
+}
|
||||
+
|
||||
+static void airoha_init_thermal_ADC_mode(struct airoha_thermal_priv *priv)
|
||||
+{
|
||||
+ u32 adc_mux, pllrg;
|
||||
+
|
||||
+ /* Save PLLRG current value */
|
||||
+ 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);
|
||||
+ adc_mux = FIELD_PREP(EN7581_MUX_TADC, EN7581_SCU_THERMAL_MUX_DIODE1);
|
||||
+ regmap_write(priv->chip_scu, EN7581_PWD_TADC, adc_mux);
|
||||
+
|
||||
+ /* Restore PLLRG value on exit */
|
||||
+ regmap_write(priv->chip_scu, EN7581_PLLRG_PROTECT, pllrg);
|
||||
+}
|
||||
+
|
||||
+static int airoha_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;
|
||||
+ int i;
|
||||
+
|
||||
+ avg_value = 0;
|
||||
+ min_value = INT_MAX;
|
||||
+ max_value = INT_MIN;
|
||||
+
|
||||
+ for (i = 0; i < AIROHA_MAX_SAMPLES; i++) {
|
||||
+ value = airoha_get_thermal_ADC(priv);
|
||||
+ min_value = min(value, min_value);
|
||||
+ max_value = max(value, max_value);
|
||||
+ avg_value += value;
|
||||
+ }
|
||||
+
|
||||
+ /* Drop min and max and average for the remaining sample */
|
||||
+ avg_value -= (min_value + max_value);
|
||||
+ avg_value /= AIROHA_MAX_SAMPLES - 2;
|
||||
+
|
||||
+ *temp = RAW_TO_TEMP(priv, avg_value);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int airoha_thermal_set_trips(struct thermal_zone_device *tz, int low,
|
||||
+ int high)
|
||||
+{
|
||||
+ struct airoha_thermal_priv *priv = thermal_zone_device_priv(tz);
|
||||
+ bool enable_monitor = false;
|
||||
+
|
||||
+ if (high != INT_MAX) {
|
||||
+ /* Validate high and clamp it a supported value */
|
||||
+ high = clamp_t(int, high, RAW_TO_TEMP(priv, 0),
|
||||
+ 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);
|
||||
+
|
||||
+ enable_monitor = true;
|
||||
+ }
|
||||
+
|
||||
+ if (low != -INT_MAX) {
|
||||
+ /* Validate low and clamp it to a supported value */
|
||||
+ low = clamp_t(int, high, RAW_TO_TEMP(priv, 0),
|
||||
+ 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);
|
||||
+
|
||||
+ enable_monitor = true;
|
||||
+ }
|
||||
+
|
||||
+ /* Enable sensor 0 monitor after trip are set */
|
||||
+ if (enable_monitor)
|
||||
+ writel(EN7581_SENSE0_EN, priv->base + EN7581_TEMPMONCTL0);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct thermal_zone_device_ops thdev_ops = {
|
||||
+ .get_temp = airoha_thermal_get_temp,
|
||||
+ .set_trips = airoha_thermal_set_trips,
|
||||
+};
|
||||
+
|
||||
+static irqreturn_t airoha_thermal_irq(int irq, void *data)
|
||||
+{
|
||||
+ struct airoha_thermal_priv *priv = data;
|
||||
+ enum thermal_notify_event event;
|
||||
+ bool update = false;
|
||||
+ u32 status;
|
||||
+
|
||||
+ status = readl(priv->base + EN7581_TEMPMONINTSTS);
|
||||
+ switch (status & (EN7581_HOFSINTSTS0 | EN7581_LOFSINTSTS0)) {
|
||||
+ case EN7581_HOFSINTSTS0:
|
||||
+ event = THERMAL_TRIP_VIOLATED;
|
||||
+ update = true;
|
||||
+ break;
|
||||
+ case EN7581_LOFSINTSTS0:
|
||||
+ event = THERMAL_EVENT_UNSPECIFIED;
|
||||
+ update = true;
|
||||
+ break;
|
||||
+ default:
|
||||
+ /* Should be impossible as we enable only these Interrupt */
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ /* Reset Interrupt */
|
||||
+ writel(status, priv->base + EN7581_TEMPMONINTSTS);
|
||||
+
|
||||
+ if (update)
|
||||
+ thermal_zone_device_update(priv->tz, event);
|
||||
+
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
+static void airoha_thermal_setup_adc_val(struct device *dev,
|
||||
+ struct airoha_thermal_priv *priv)
|
||||
+{
|
||||
+ 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);
|
||||
+
|
||||
+ efuse_calib_info = readl(priv->base + EN7581_EFUSE_TEMP_OFFSET_REG);
|
||||
+ 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);
|
||||
+ if (cpu_sensor) {
|
||||
+ priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT;
|
||||
+ priv->init_temp = EN7581_INIT_TEMP_FTK_X10;
|
||||
+ } else {
|
||||
+ priv->default_slope = EN7581_SLOPE_X100_DIO_AVS;
|
||||
+ priv->init_temp = EN7581_INIT_TEMP_CPK_X10;
|
||||
+ }
|
||||
+ } else {
|
||||
+ priv->default_offset = airoha_get_thermal_ADC(priv);
|
||||
+ priv->default_slope = EN7581_SLOPE_X100_DIO_DEFAULT;
|
||||
+ priv->init_temp = EN7581_INIT_TEMP_NONK_X10;
|
||||
+ dev_info(dev, "missing thermal calibrarion EFUSE, using non calibrated value\n");
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+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);
|
||||
+
|
||||
+ /*
|
||||
+ * Configure ADC valid reading addr
|
||||
+ * The AHB temp monitor system doesn't have direct access to the
|
||||
+ * thermal sensor. It does instead work by providing all kind of
|
||||
+ * address to configure how to access and setup an ADC for the
|
||||
+ * sensor. EN7581 supports only one sensor hence the
|
||||
+ * implementation is greatly simplified but the AHB supports
|
||||
+ * up to 4 different sensor from the same ADC that can be
|
||||
+ * switched by tuning the ADC mux or wiriting address.
|
||||
+ *
|
||||
+ * 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);
|
||||
+
|
||||
+ /*
|
||||
+ * 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);
|
||||
+
|
||||
+ /*
|
||||
+ * AHB supports max 12 bytes for ADC voltage. Shift the read
|
||||
+ * value 4 bit to the right. Precision lost by this is minimal
|
||||
+ * 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);
|
||||
+
|
||||
+ /* BUS clock is 300MHz counting unit is 3 * 68.64 * 256 = 52.715us */
|
||||
+ writel(FIELD_PREP(EN7581_PERIOD_UNIT, 3),
|
||||
+ priv->base + EN7581_TEMPMONCTL1);
|
||||
+
|
||||
+ /*
|
||||
+ * 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);
|
||||
+
|
||||
+ /* AHB poll is set to 146 * 68.64 = 10.02us */
|
||||
+ writel(FIELD_PREP(EN7581_ADC_POLL_INTVL, 146),
|
||||
+ priv->base + EN7581_TEMPAHBPOLL);
|
||||
+}
|
||||
+
|
||||
+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;
|
||||
+ 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);
|
||||
+
|
||||
+ chip_scu_np = of_parse_phandle(dev->of_node, "airoha,chip-scu", 0);
|
||||
+ if (!chip_scu_np)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ priv->chip_scu = syscon_node_to_regmap(chip_scu_np);
|
||||
+ if (IS_ERR(priv->chip_scu))
|
||||
+ return PTR_ERR(priv->chip_scu);
|
||||
+
|
||||
+ of_address_to_resource(chip_scu_np, 0, &priv->scu_adc_res);
|
||||
+ of_node_put(chip_scu_np);
|
||||
+
|
||||
+ irq = platform_get_irq(pdev, 0);
|
||||
+ if (irq < 0)
|
||||
+ return irq;
|
||||
+
|
||||
+ ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
|
||||
+ airoha_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);
|
||||
+
|
||||
+ /* register of thermal sensor and get info from DT */
|
||||
+ priv->tz = devm_thermal_of_zone_register(dev, 0, priv, &thdev_ops);
|
||||
+ if (IS_ERR(priv->tz)) {
|
||||
+ dev_err(dev, "register thermal zone sensor failed\n");
|
||||
+ return PTR_ERR(priv->tz);
|
||||
+ }
|
||||
+
|
||||
+ platform_set_drvdata(pdev, priv);
|
||||
+
|
||||
+ /* Enable LOW and HIGH interrupt */
|
||||
+ writel(EN7581_HOFSINTEN0 | EN7581_LOFSINTEN0,
|
||||
+ priv->base + EN7581_TEMPMONINT);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct of_device_id airoha_thermal_match[] = {
|
||||
+ { .compatible = "airoha,en7581-thermal" },
|
||||
+ {},
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(of, airoha_thermal_match);
|
||||
+
|
||||
+static struct platform_driver airoha_thermal_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "airoha-thermal",
|
||||
+ .of_match_table = airoha_thermal_match,
|
||||
+ },
|
||||
+ .probe = airoha_thermal_probe,
|
||||
+};
|
||||
+
|
||||
+module_platform_driver(airoha_thermal_driver);
|
||||
+
|
||||
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
|
||||
+MODULE_DESCRIPTION("Airoha thermal driver");
|
||||
+MODULE_LICENSE("GPL");
|
@@ -1,44 +0,0 @@
|
||||
From e23cba0ab49a9cf95e9bc3a86cfbf336b0e285f6 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Wed, 14 May 2025 23:39:12 +0200
|
||||
Subject: [PATCH] thermal/drivers/airoha: Fix spelling mistake
|
||||
|
||||
Fix various spelling mistake in airoha_thermal_setup_monitor() and
|
||||
define.
|
||||
|
||||
Reported-by: Alok Tiwari <alok.a.tiwari@oracle.com>
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://lore.kernel.org/r/20250514213919.2321490-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||
---
|
||||
drivers/thermal/airoha_thermal.c | 10 +++++-----
|
||||
1 file changed, 5 insertions(+), 5 deletions(-)
|
||||
|
||||
--- a/drivers/thermal/airoha_thermal.c
|
||||
+++ b/drivers/thermal/airoha_thermal.c
|
||||
@@ -155,7 +155,7 @@
|
||||
* Can operate in:
|
||||
* - 1 sample
|
||||
* - 2 sample and make average of them
|
||||
- * - 4,6,10,16 sample, drop max and min and make avgerage of them
|
||||
+ * - 4,6,10,16 sample, drop max and min and make average of them
|
||||
*/
|
||||
#define EN7581_MSRCTL_1SAMPLE 0x0
|
||||
#define EN7581_MSRCTL_AVG2SAMPLE 0x1
|
||||
@@ -365,12 +365,12 @@ static void airoha_thermal_setup_monitor
|
||||
/*
|
||||
* Configure ADC valid reading addr
|
||||
* The AHB temp monitor system doesn't have direct access to the
|
||||
- * thermal sensor. It does instead work by providing all kind of
|
||||
- * address to configure how to access and setup an ADC for the
|
||||
+ * thermal sensor. It does instead work by providing various
|
||||
+ * addresses to configure how to access and setup an ADC for the
|
||||
* sensor. EN7581 supports only one sensor hence the
|
||||
* implementation is greatly simplified but the AHB supports
|
||||
- * up to 4 different sensor from the same ADC that can be
|
||||
- * switched by tuning the ADC mux or wiriting address.
|
||||
+ * up to 4 different sensors from the same ADC that can be
|
||||
+ * switched by tuning the ADC mux or writing address.
|
||||
*
|
||||
* We set valid instead of volt as we don't enable valid/volt
|
||||
* split reading and AHB read valid addr in such case.
|
@@ -1,435 +0,0 @@
|
||||
From 457d9772e8a5cdae64f66b5f7d5b0247365191ec Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Tue, 1 Apr 2025 15:50:21 +0200
|
||||
Subject: [PATCH] pinctrl: airoha: fix wrong PHY LED mapping and PHY2 LED
|
||||
defines
|
||||
|
||||
The current PHY2 LED define are wrong and actually set BITs outside the
|
||||
related mask. Fix it and set the correct value. While at it, also use
|
||||
FIELD_PREP_CONST macro to make it simple to understand what values are
|
||||
actually applied for the mask.
|
||||
|
||||
Also fix wrong PHY LED mapping. The SoC Switch supports up to 4 port but
|
||||
the register define mapping for 5 PHY port, starting from 0. The mapping
|
||||
was wrongly defined starting from PHY1. Reorder the function group to
|
||||
start from PHY0. PHY4 is actually never supported as we don't have a
|
||||
GPIO pin to assign.
|
||||
|
||||
Cc: stable@vger.kernel.org
|
||||
Fixes: 1c8ace2d0725 ("pinctrl: airoha: Add support for EN7581 SoC")
|
||||
Reviewed-by: Benjamin Larsson <benjamin.larsson@genexis.eu>
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Acked-by: Lorenzo Bianconi <lorenzo@kernel.org>
|
||||
Link: https://lore.kernel.org/20250401135026.18018-1-ansuelsmth@gmail.com
|
||||
Signed-off-by: Linus Walleij <linus.walleij@linaro.org>
|
||||
---
|
||||
drivers/pinctrl/mediatek/pinctrl-airoha.c | 159 ++++++++++------------
|
||||
1 file changed, 70 insertions(+), 89 deletions(-)
|
||||
|
||||
--- a/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
+++ b/drivers/pinctrl/mediatek/pinctrl-airoha.c
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
#include <dt-bindings/pinctrl/mt65xx.h>
|
||||
+#include <linux/bitfield.h>
|
||||
#include <linux/bits.h>
|
||||
#include <linux/cleanup.h>
|
||||
#include <linux/gpio/driver.h>
|
||||
@@ -106,39 +107,19 @@
|
||||
#define REG_LAN_LED1_MAPPING 0x0280
|
||||
|
||||
#define LAN4_LED_MAPPING_MASK GENMASK(18, 16)
|
||||
-#define LAN4_PHY4_LED_MAP BIT(18)
|
||||
-#define LAN4_PHY2_LED_MAP BIT(17)
|
||||
-#define LAN4_PHY1_LED_MAP BIT(16)
|
||||
-#define LAN4_PHY0_LED_MAP 0
|
||||
-#define LAN4_PHY3_LED_MAP GENMASK(17, 16)
|
||||
+#define LAN4_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN4_LED_MAPPING_MASK, (_n))
|
||||
|
||||
#define LAN3_LED_MAPPING_MASK GENMASK(14, 12)
|
||||
-#define LAN3_PHY4_LED_MAP BIT(14)
|
||||
-#define LAN3_PHY2_LED_MAP BIT(13)
|
||||
-#define LAN3_PHY1_LED_MAP BIT(12)
|
||||
-#define LAN3_PHY0_LED_MAP 0
|
||||
-#define LAN3_PHY3_LED_MAP GENMASK(13, 12)
|
||||
+#define LAN3_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN3_LED_MAPPING_MASK, (_n))
|
||||
|
||||
#define LAN2_LED_MAPPING_MASK GENMASK(10, 8)
|
||||
-#define LAN2_PHY4_LED_MAP BIT(12)
|
||||
-#define LAN2_PHY2_LED_MAP BIT(11)
|
||||
-#define LAN2_PHY1_LED_MAP BIT(10)
|
||||
-#define LAN2_PHY0_LED_MAP 0
|
||||
-#define LAN2_PHY3_LED_MAP GENMASK(11, 10)
|
||||
+#define LAN2_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN2_LED_MAPPING_MASK, (_n))
|
||||
|
||||
#define LAN1_LED_MAPPING_MASK GENMASK(6, 4)
|
||||
-#define LAN1_PHY4_LED_MAP BIT(6)
|
||||
-#define LAN1_PHY2_LED_MAP BIT(5)
|
||||
-#define LAN1_PHY1_LED_MAP BIT(4)
|
||||
-#define LAN1_PHY0_LED_MAP 0
|
||||
-#define LAN1_PHY3_LED_MAP GENMASK(5, 4)
|
||||
+#define LAN1_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN1_LED_MAPPING_MASK, (_n))
|
||||
|
||||
#define LAN0_LED_MAPPING_MASK GENMASK(2, 0)
|
||||
-#define LAN0_PHY4_LED_MAP BIT(3)
|
||||
-#define LAN0_PHY2_LED_MAP BIT(2)
|
||||
-#define LAN0_PHY1_LED_MAP BIT(1)
|
||||
-#define LAN0_PHY0_LED_MAP 0
|
||||
-#define LAN0_PHY3_LED_MAP GENMASK(2, 1)
|
||||
+#define LAN0_PHY_LED_MAP(_n) FIELD_PREP_CONST(LAN0_LED_MAPPING_MASK, (_n))
|
||||
|
||||
/* CONF */
|
||||
#define REG_I2C_SDA_E2 0x001c
|
||||
@@ -1470,8 +1451,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY1_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1485,8 +1466,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY1_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1500,8 +1481,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY1_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1515,8 +1496,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY1_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1534,8 +1515,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY2_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1549,8 +1530,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY2_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1564,8 +1545,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY2_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1579,8 +1560,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY2_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1598,8 +1579,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY3_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1613,8 +1594,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY3_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1628,8 +1609,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY3_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1643,8 +1624,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY3_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1662,8 +1643,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY4_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1677,8 +1658,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY4_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1692,8 +1673,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY4_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1707,8 +1688,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED0_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY4_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1726,8 +1707,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY1_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1741,8 +1722,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY1_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1756,8 +1737,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY1_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1771,8 +1752,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY1_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(0)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1790,8 +1771,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY2_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1805,8 +1786,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY2_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1820,8 +1801,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY2_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1835,8 +1816,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY2_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(1)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1854,8 +1835,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY3_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1869,8 +1850,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY3_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1884,8 +1865,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY3_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1899,8 +1880,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY3_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(2)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
||||
@@ -1918,8 +1899,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN1_LED_MAPPING_MASK,
|
||||
- LAN1_PHY4_LED_MAP
|
||||
+ LAN0_LED_MAPPING_MASK,
|
||||
+ LAN0_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1933,8 +1914,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN2_LED_MAPPING_MASK,
|
||||
- LAN2_PHY4_LED_MAP
|
||||
+ LAN1_LED_MAPPING_MASK,
|
||||
+ LAN1_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1948,8 +1929,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN3_LED_MAPPING_MASK,
|
||||
- LAN3_PHY4_LED_MAP
|
||||
+ LAN2_LED_MAPPING_MASK,
|
||||
+ LAN2_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
}, {
|
||||
@@ -1963,8 +1944,8 @@ static const struct airoha_pinctrl_func_
|
||||
.regmap[1] = {
|
||||
AIROHA_FUNC_MUX,
|
||||
REG_LAN_LED1_MAPPING,
|
||||
- LAN4_LED_MAPPING_MASK,
|
||||
- LAN4_PHY4_LED_MAP
|
||||
+ LAN3_LED_MAPPING_MASK,
|
||||
+ LAN3_PHY_LED_MAP(3)
|
||||
},
|
||||
.regmap_size = 2,
|
||||
},
|
@@ -1,129 +0,0 @@
|
||||
From 6a325aed130bb68790e765f923e76ec5669d2da7 Mon Sep 17 00:00:00 2001
|
||||
From: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Date: Thu, 10 Apr 2025 12:04:04 +0200
|
||||
Subject: [PATCH 2/2] net: phy: mediatek: add Airoha PHY ID to SoC driver
|
||||
|
||||
Airoha AN7581 SoC ship with a Switch based on the MT753x Switch embedded
|
||||
in other SoC like the MT7581 and the MT7988. Similar to these they
|
||||
require configuring some pin to enable LED PHYs.
|
||||
|
||||
Add support for the PHY ID for the Airoha embedded Switch and define a
|
||||
simple probe function to toggle these pins. Also fill the LED functions
|
||||
and add dedicated function to define LED polarity.
|
||||
|
||||
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
|
||||
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
|
||||
Link: https://patch.msgid.link/20250410100410.348-2-ansuelsmth@gmail.com
|
||||
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
|
||||
---
|
||||
drivers/net/phy/mediatek/Kconfig | 4 +-
|
||||
drivers/net/phy/mediatek/mtk-ge-soc.c | 62 +++++++++++++++++++++++++++
|
||||
2 files changed, 65 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/drivers/net/phy/mediatek/Kconfig
|
||||
+++ b/drivers/net/phy/mediatek/Kconfig
|
||||
@@ -15,7 +15,9 @@ config MEDIATEK_GE_PHY
|
||||
|
||||
config MEDIATEK_GE_SOC_PHY
|
||||
tristate "MediaTek SoC Ethernet PHYs"
|
||||
- depends on (ARM64 && ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || COMPILE_TEST
|
||||
+ depends on ARM64 || COMPILE_TEST
|
||||
+ depends on ARCH_AIROHA || (ARCH_MEDIATEK && NVMEM_MTK_EFUSE) || \
|
||||
+ COMPILE_TEST
|
||||
select MTK_NET_PHYLIB
|
||||
help
|
||||
Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
|
||||
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||
@@ -10,8 +10,11 @@
|
||||
|
||||
#include "mtk.h"
|
||||
|
||||
+#define MTK_PHY_MAX_LEDS 2
|
||||
+
|
||||
#define MTK_GPHY_ID_MT7981 0x03a29461
|
||||
#define MTK_GPHY_ID_MT7988 0x03a29481
|
||||
+#define MTK_GPHY_ID_AN7581 0x03a294c1
|
||||
|
||||
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||
#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||
@@ -1405,6 +1408,53 @@ static int mt7981_phy_probe(struct phy_d
|
||||
return mt798x_phy_calibration(phydev);
|
||||
}
|
||||
|
||||
+static int an7581_phy_probe(struct phy_device *phydev)
|
||||
+{
|
||||
+ struct mtk_socphy_priv *priv;
|
||||
+ struct pinctrl *pinctrl;
|
||||
+
|
||||
+ /* Toggle pinctrl to enable PHY LED */
|
||||
+ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
|
||||
+ if (IS_ERR(pinctrl))
|
||||
+ dev_err(&phydev->mdio.bus->dev,
|
||||
+ "Failed to setup PHY LED pinctrl\n");
|
||||
+
|
||||
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(*priv), GFP_KERNEL);
|
||||
+ if (!priv)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ phydev->priv = priv;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int an7581_phy_led_polarity_set(struct phy_device *phydev, int index,
|
||||
+ unsigned long modes)
|
||||
+{
|
||||
+ u32 mode;
|
||||
+ u16 val;
|
||||
+
|
||||
+ if (index >= MTK_PHY_MAX_LEDS)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ for_each_set_bit(mode, &modes, __PHY_LED_MODES_NUM) {
|
||||
+ switch (mode) {
|
||||
+ case PHY_LED_ACTIVE_LOW:
|
||||
+ val = MTK_PHY_LED_ON_POLARITY;
|
||||
+ break;
|
||||
+ case PHY_LED_ACTIVE_HIGH:
|
||||
+ val = 0;
|
||||
+ break;
|
||||
+ default:
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||
+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
|
||||
+ MTK_PHY_LED_ON_POLARITY, val);
|
||||
+}
|
||||
+
|
||||
static struct phy_driver mtk_socphy_driver[] = {
|
||||
{
|
||||
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
|
||||
@@ -1440,6 +1490,17 @@ static struct phy_driver mtk_socphy_driv
|
||||
.led_hw_control_set = mt798x_phy_led_hw_control_set,
|
||||
.led_hw_control_get = mt798x_phy_led_hw_control_get,
|
||||
},
|
||||
+ {
|
||||
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581),
|
||||
+ .name = "Airoha AN7581 PHY",
|
||||
+ .probe = an7581_phy_probe,
|
||||
+ .led_blink_set = mt798x_phy_led_blink_set,
|
||||
+ .led_brightness_set = mt798x_phy_led_brightness_set,
|
||||
+ .led_hw_is_supported = mt798x_phy_led_hw_is_supported,
|
||||
+ .led_hw_control_set = mt798x_phy_led_hw_control_set,
|
||||
+ .led_hw_control_get = mt798x_phy_led_hw_control_get,
|
||||
+ .led_polarity_set = an7581_phy_led_polarity_set,
|
||||
+ },
|
||||
};
|
||||
|
||||
module_phy_driver(mtk_socphy_driver);
|
||||
@@ -1447,6 +1508,7 @@ module_phy_driver(mtk_socphy_driver);
|
||||
static struct mdio_device_id __maybe_unused mtk_socphy_tbl[] = {
|
||||
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981) },
|
||||
{ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988) },
|
||||
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_AN7581) },
|
||||
{ }
|
||||
};
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user