qualcommax: drop 6.12 support

No point in keeping 6.12 on qualcommax anymore.

Signed-off-by: Robert Marko <robimarko@gmail.com>
This commit is contained in:
Robert Marko 2026-08-02 19:39:22 +02:00
parent b8f0e12a8d
commit 55a7d7c45f
119 changed files with 0 additions and 26238 deletions

View file

@ -1,626 +0,0 @@
CONFIG_64BIT=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_HIBERNATION_POSSIBLE=y
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_PKEY_BITS=3
CONFIG_ARCH_PROC_KCORE_TEXT=y
CONFIG_ARCH_QCOM=y
CONFIG_ARCH_SPARSEMEM_ENABLE=y
CONFIG_ARCH_STACKWALK=y
CONFIG_ARCH_SUSPEND_POSSIBLE=y
CONFIG_ARCH_WANTS_EXECMEM_LATE=y
CONFIG_ARCH_WANTS_NO_INSTR=y
CONFIG_ARCH_WANTS_THP_SWAP=y
CONFIG_ARM64=y
CONFIG_ARM64_4K_PAGES=y
CONFIG_ARM64_ERRATUM_1165522=y
CONFIG_ARM64_ERRATUM_1286807=y
CONFIG_ARM64_ERRATUM_2051678=y
CONFIG_ARM64_ERRATUM_2054223=y
CONFIG_ARM64_ERRATUM_2067961=y
CONFIG_ARM64_ERRATUM_2077057=y
CONFIG_ARM64_ERRATUM_2658417=y
CONFIG_ARM64_LD_HAS_FIX_ERRATUM_843419=y
CONFIG_ARM64_PA_BITS=48
CONFIG_ARM64_PA_BITS_48=y
CONFIG_ARM64_PLATFORM_DEVICES=y
CONFIG_ARM64_PTR_AUTH=y
CONFIG_ARM64_PTR_AUTH_KERNEL=y
CONFIG_ARM64_SVE=y
CONFIG_ARM64_TAGGED_ADDR_ABI=y
CONFIG_ARM64_VA_BITS=39
CONFIG_ARM64_VA_BITS_39=y
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI=y
CONFIG_ARM64_WORKAROUND_SPECULATIVE_AT=y
CONFIG_ARM64_WORKAROUND_TSB_FLUSH_FAILURE=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_MHU_V2 is not set
# CONFIG_ARM_MHU_V3 is not set
CONFIG_ARM_PSCI_CPUIDLE=y
CONFIG_ARM_PSCI_FW=y
# CONFIG_ARM_QCOM_CPUFREQ_HW is not set
CONFIG_ARM_QCOM_CPUFREQ_NVMEM=y
CONFIG_AT803X_PHY=y
CONFIG_AUDIT_ARCH_COMPAT_GENERIC=y
CONFIG_AUXILIARY_BUS=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_SD=y
CONFIG_BLK_MQ_PCI=y
CONFIG_BLK_MQ_VIRTIO=y
CONFIG_BLK_PM=y
CONFIG_BUILTIN_RETURN_ADDRESS_STRIPS_PAC=y
CONFIG_CC_HAVE_SHADOW_CALL_STACK=y
CONFIG_CC_HAVE_STACKPROTECTOR_SYSREG=y
# CONFIG_CLK_QCM2290_GPUCC is not set
# CONFIG_CLK_X1E80100_CAMCC is not set
# CONFIG_CLK_X1E80100_DISPCC is not set
# CONFIG_CLK_X1E80100_GCC is not set
# CONFIG_CLK_X1E80100_GPUCC is not set
# CONFIG_CLK_X1E80100_TCSRCC is not set
CONFIG_CLONE_BACKWARDS=y
CONFIG_COMMON_CLK=y
CONFIG_COMMON_CLK_QCOM=y
CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
# CONFIG_COMPAT_32BIT_TIME is not set
CONFIG_CONTEXT_TRACKING=y
CONFIG_CONTEXT_TRACKING_IDLE=y
CONFIG_COREDUMP=y
CONFIG_CPUFREQ_DT=y
CONFIG_CPUFREQ_DT_PLATDEV=y
CONFIG_CPU_FREQ=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_SCHEDUTIL=y
CONFIG_CPU_FREQ_GOV_ATTR_SET=y
# CONFIG_CPU_FREQ_GOV_CONSERVATIVE is not set
# CONFIG_CPU_FREQ_GOV_ONDEMAND is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
# CONFIG_CPU_FREQ_GOV_POWERSAVE is not set
CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y
# CONFIG_CPU_FREQ_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_STAT=y
CONFIG_CPU_FREQ_THERMAL=y
CONFIG_CPU_IDLE=y
CONFIG_CPU_IDLE_GOV_MENU=y
CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
CONFIG_CPU_LITTLE_ENDIAN=y
CONFIG_CPU_MITIGATIONS=y
CONFIG_CPU_PM=y
CONFIG_CPU_RMAP=y
CONFIG_CPU_THERMAL=y
CONFIG_CRC16=y
CONFIG_CRC8=y
CONFIG_CRYPTO_AUTHENC=y
CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_DEFLATE=y
CONFIG_CRYPTO_DEV_QCOM_RNG=y
CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_HASH_INFO=y
CONFIG_CRYPTO_HW=y
CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
CONFIG_CRYPTO_LIB_DES=y
CONFIG_CRYPTO_LIB_GF128MUL=y
CONFIG_CRYPTO_LIB_SHA256=y
CONFIG_CRYPTO_LIB_UTILS=y
CONFIG_CRYPTO_LZO=y
CONFIG_CRYPTO_RNG=y
CONFIG_CRYPTO_SHA1=y
CONFIG_CRYPTO_SHA256=y
CONFIG_CRYPTO_XTS=y
CONFIG_CRYPTO_ZSTD=y
CONFIG_DCACHE_WORD_ACCESS=y
CONFIG_DEBUG_BUGVERBOSE=y
CONFIG_DEBUG_INFO=y
CONFIG_DEV_COREDUMP=y
CONFIG_DMADEVICES=y
CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y
CONFIG_DMA_DIRECT_REMAP=y
CONFIG_DMA_ENGINE=y
CONFIG_DMA_NEED_SYNC=y
CONFIG_DMA_OF=y
CONFIG_DMA_VIRTUAL_CHANNELS=y
CONFIG_DTC=y
CONFIG_DT_IDLE_STATES=y
CONFIG_EDAC_SUPPORT=y
CONFIG_EXCLUSIVE_SYSTEM_RAM=y
CONFIG_FIXED_PHY=y
CONFIG_FIX_EARLYCON_MEM=y
CONFIG_FRAME_POINTER=y
CONFIG_FS_IOMAP=y
CONFIG_FUNCTION_ALIGNMENT=4
CONFIG_FUNCTION_ALIGNMENT_4B=y
CONFIG_FWNODE_MDIO=y
CONFIG_FWNODE_PCS=y
CONFIG_FW_LOADER_PAGED_BUF=y
CONFIG_FW_LOADER_SYSFS=y
CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE_WITH_ARGS=y
CONFIG_GENERIC_ALLOCATOR=y
CONFIG_GENERIC_ARCH_TOPOLOGY=y
CONFIG_GENERIC_BUG=y
CONFIG_GENERIC_BUG_RELATIVE_POINTERS=y
CONFIG_GENERIC_CLOCKEVENTS=y
CONFIG_GENERIC_CLOCKEVENTS_BROADCAST=y
CONFIG_GENERIC_CPU_AUTOPROBE=y
CONFIG_GENERIC_CPU_DEVICES=y
CONFIG_GENERIC_CPU_VULNERABILITIES=y
CONFIG_GENERIC_CSUM=y
CONFIG_GENERIC_EARLY_IOREMAP=y
CONFIG_GENERIC_GETTIMEOFDAY=y
CONFIG_GENERIC_IDLE_POLL_SETUP=y
CONFIG_GENERIC_IOREMAP=y
CONFIG_GENERIC_IRQ_EFFECTIVE_AFF_MASK=y
CONFIG_GENERIC_IRQ_KEXEC_CLEAR_VM_FORWARD=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_WATCHDOG=y
# CONFIG_GPIO_WATCHDOG_ARCH_INITCALL is not set
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_HWMON=y
CONFIG_HWSPINLOCK=y
CONFIG_HWSPINLOCK_QCOM=y
CONFIG_HW_RANDOM=y
CONFIG_I2C=y
CONFIG_I2C_BOARDINFO=y
CONFIG_I2C_CHARDEV=y
CONFIG_I2C_HELPER_AUTO=y
# CONFIG_I2C_QCOM_CCI is not set
CONFIG_I2C_QUP=y
CONFIG_IIO=y
CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
CONFIG_INITRAMFS_SOURCE=""
CONFIG_INTERCONNECT=y
CONFIG_INTERCONNECT_CLK=y
# CONFIG_INTERCONNECT_QCOM is not set
CONFIG_IPQ_APSS_6018=y
CONFIG_IPQ_APSS_PLL=y
# CONFIG_IPQ_CMN_PLL is not set
# CONFIG_IPQ_GCC_4019 is not set
# CONFIG_IPQ_GCC_5018 is not set
# CONFIG_IPQ_GCC_5332 is not set
# CONFIG_IPQ_GCC_6018 is not set
# CONFIG_IPQ_GCC_8074 is not set
# CONFIG_IPQ_GCC_9574 is not set
# CONFIG_IPQ_NSSCC_QCA8K is not set
CONFIG_IRQCHIP=y
CONFIG_IRQ_DOMAIN=y
CONFIG_IRQ_DOMAIN_HIERARCHY=y
CONFIG_IRQ_FASTEOI_HIERARCHY_HANDLERS=y
CONFIG_IRQ_FORCED_THREADING=y
CONFIG_IRQ_MSI_LIB=y
CONFIG_IRQ_WORK=y
# CONFIG_KPSS_XCC is not set
CONFIG_LEDS_TLC591XX=y
CONFIG_LIBFDT=y
CONFIG_LOCK_DEBUGGING_SUPPORT=y
CONFIG_LOCK_SPIN_ON_OWNER=y
CONFIG_LRU_GEN_WALKS_MMU=y
CONFIG_LZO_COMPRESS=y
CONFIG_LZO_DECOMPRESS=y
CONFIG_MAILBOX=y
# CONFIG_MAILBOX_TEST is not set
CONFIG_MDIO_BUS=y
CONFIG_MDIO_DEVICE=y
CONFIG_MDIO_DEVRES=y
CONFIG_MDIO_IPQ4019=y
# CONFIG_MFD_QCOM_RPM is not set
CONFIG_MFD_SYSCON=y
CONFIG_MIGRATION=y
# CONFIG_MITIGATE_SPECTRE_BRANCH_HISTORY is not set
CONFIG_MMC=y
CONFIG_MMC_BLOCK=y
CONFIG_MMC_BLOCK_MINORS=32
CONFIG_MMC_CQHCI=y
CONFIG_MMC_SDHCI=y
CONFIG_MMC_SDHCI_IO_ACCESSORS=y
CONFIG_MMC_SDHCI_MSM=y
CONFIG_MMC_SDHCI_PLTFM=y
CONFIG_MMU_LAZY_TLB_REFCOUNT=y
CONFIG_MODULES_USE_ELF_RELA=y
# CONFIG_MSM_GCC_8916 is not set
# CONFIG_MSM_GCC_8917 is not set
# CONFIG_MSM_GCC_8939 is not set
# CONFIG_MSM_GCC_8976 is not set
# CONFIG_MSM_GCC_8994 is not set
# CONFIG_MSM_GCC_8996 is not set
# CONFIG_MSM_GCC_8998 is not set
# CONFIG_MSM_GPUCC_8998 is not set
# CONFIG_MSM_MMCC_8996 is not set
# CONFIG_MSM_MMCC_8998 is not set
CONFIG_MTD_NAND_CORE=y
CONFIG_MTD_NAND_ECC=y
CONFIG_MTD_NAND_ECC_SW_HAMMING=y
CONFIG_MTD_NAND_QCOM=y
CONFIG_MTD_QCOMSMEM_PARTS=y
CONFIG_MTD_RAW_NAND=y
CONFIG_MTD_SPI_NOR=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_DEVLINK=y
CONFIG_NET_DSA=y
CONFIG_NET_DSA_TAG_OOB=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=4
# CONFIG_NSM is not set
CONFIG_NVMEM=y
CONFIG_NVMEM_LAYOUTS=y
CONFIG_NVMEM_LAYOUT_ASCII_ENV=y
CONFIG_NVMEM_LAYOUT_U_BOOT_ENV=y
CONFIG_NVMEM_QCOM_QFPROM=y
# CONFIG_NVMEM_QCOM_SEC_QFPROM is not set
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_PADATA=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=y
# CONFIG_PCIEASPM_PERFORMANCE is not set
# CONFIG_PCIEASPM_POWERSAVE is not set
# CONFIG_PCIEASPM_POWER_SUPERSAVE is not set
CONFIG_PCIEPORTBUS=y
CONFIG_PCIE_DW=y
CONFIG_PCIE_DW_HOST=y
CONFIG_PCIE_PME=y
CONFIG_PCIE_QCOM=y
CONFIG_PCIE_QCOM_COMMON=y
CONFIG_PCI_DOMAINS=y
CONFIG_PCI_DOMAINS_GENERIC=y
CONFIG_PCI_MSI=y
CONFIG_PCS_QCA_UNIPHY=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_QCOM_APQ8064_SATA is not set
# CONFIG_PHY_QCOM_EDP is not set
# CONFIG_PHY_QCOM_EUSB2_REPEATER is not set
# CONFIG_PHY_QCOM_IPQ4019_USB is not set
# CONFIG_PHY_QCOM_IPQ806X_SATA is not set
# CONFIG_PHY_QCOM_IPQ806X_USB is not set
# CONFIG_PHY_QCOM_M31_USB is not set
# CONFIG_PHY_QCOM_PCIE2 is not set
CONFIG_PHY_QCOM_QMP=y
CONFIG_PHY_QCOM_QMP_COMBO=y
CONFIG_PHY_QCOM_QMP_PCIE=y
CONFIG_PHY_QCOM_QMP_PCIE_8996=y
CONFIG_PHY_QCOM_QMP_UFS=y
CONFIG_PHY_QCOM_QMP_USB=y
# CONFIG_PHY_QCOM_QMP_USB_LEGACY is not set
CONFIG_PHY_QCOM_QUSB2=y
# CONFIG_PHY_QCOM_SGMII_ETH is not set
# CONFIG_PHY_QCOM_SNPS_EUSB2 is not set
# CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP is not set
# CONFIG_PHY_QCOM_USB_HS_28NM is not set
# CONFIG_PHY_QCOM_USB_SNPS_FEMTO_V2 is not set
# CONFIG_PHY_QCOM_USB_SS is not set
CONFIG_PINCTRL=y
CONFIG_PINCTRL_AW9523=y
# CONFIG_PINCTRL_IPQ5018 is not set
# CONFIG_PINCTRL_IPQ5332 is not set
# CONFIG_PINCTRL_IPQ6018 is not set
# CONFIG_PINCTRL_IPQ8074 is not set
# CONFIG_PINCTRL_IPQ9574 is not set
CONFIG_PINCTRL_MSM=y
# CONFIG_PINCTRL_MSM8916 is not set
# CONFIG_PINCTRL_MSM8976 is not set
# CONFIG_PINCTRL_MSM8994 is not set
# CONFIG_PINCTRL_MSM8996 is not set
# CONFIG_PINCTRL_MSM8998 is not set
# CONFIG_PINCTRL_QCM2290 is not set
# CONFIG_PINCTRL_QCOM_SSBI_PMIC is not set
# CONFIG_PINCTRL_QCS404 is not set
# CONFIG_PINCTRL_QDU1000 is not set
# CONFIG_PINCTRL_SA8775P is not set
# CONFIG_PINCTRL_SC7180 is not set
# CONFIG_PINCTRL_SC8280XP is not set
# CONFIG_PINCTRL_SDM660 is not set
# CONFIG_PINCTRL_SDM670 is not set
# CONFIG_PINCTRL_SDM845 is not set
# CONFIG_PINCTRL_SDX75 is not set
# CONFIG_PINCTRL_SM4450 is not set
# CONFIG_PINCTRL_SM6350 is not set
# CONFIG_PINCTRL_SM6375 is not set
# CONFIG_PINCTRL_SM7150 is not set
# CONFIG_PINCTRL_SM8150 is not set
# CONFIG_PINCTRL_SM8250 is not set
# CONFIG_PINCTRL_SM8450 is not set
# CONFIG_PINCTRL_SM8550 is not set
# CONFIG_PINCTRL_SM8650 is not set
# CONFIG_PINCTRL_X1E80100 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_GPIO=y
# CONFIG_POWER_RESET_MSM is not set
CONFIG_POWER_SUPPLY=y
CONFIG_PRINTK_TIME=y
CONFIG_PTP_1588_CLOCK_OPTIONAL=y
CONFIG_QCA807X_PHY=y
CONFIG_QCA808X_PHY=y
# CONFIG_QCM_DISPCC_2290 is not set
# CONFIG_QCM_GCC_2290 is not set
# CONFIG_QCOM_80211AX_PPE is not set
# CONFIG_QCOM_A53PLL is not set
# CONFIG_QCOM_AOSS_QMP is not set
CONFIG_QCOM_APCS_IPC=y
# CONFIG_QCOM_APM is not set
# CONFIG_QCOM_APR is not set
CONFIG_QCOM_BAM_DMA=y
# CONFIG_QCOM_CLK_APCC_MSM8996 is not set
# CONFIG_QCOM_CLK_APCS_MSM8916 is not set
# CONFIG_QCOM_COMMAND_DB is not set
# CONFIG_QCOM_CPR is not set
# CONFIG_QCOM_CPUCP_MBOX is not set
# CONFIG_QCOM_EBI2 is not set
# CONFIG_QCOM_EDMA is not set
# CONFIG_QCOM_FASTRPC is not set
# CONFIG_QCOM_GENI_SE is not set
# CONFIG_QCOM_GSBI is not set
# CONFIG_QCOM_HFPLL is not set
# CONFIG_QCOM_ICC_BWMON is not set
# CONFIG_QCOM_IPA is not set
# CONFIG_QCOM_IPCC is not set
# CONFIG_QCOM_LLCC is not set
CONFIG_QCOM_MDT_LOADER=y
# CONFIG_QCOM_MPM is not set
CONFIG_QCOM_NET_PHYLIB=y
# CONFIG_QCOM_OCMEM is not set
# CONFIG_QCOM_PDC is not set
CONFIG_QCOM_PIL_INFO=y
# CONFIG_QCOM_Q6V5_ADSP is not set
CONFIG_QCOM_Q6V5_COMMON=y
# CONFIG_QCOM_Q6V5_MPD is not set
# CONFIG_QCOM_Q6V5_MSS is not set
# CONFIG_QCOM_Q6V5_PAS is not set
CONFIG_QCOM_Q6V5_WCSS=y
# CONFIG_QCOM_Q6V5_WCSS_SEC is not set
# CONFIG_QCOM_QSEECOM is not set
# CONFIG_QCOM_RAMP_CTRL is not set
# CONFIG_QCOM_RMTFS_MEM is not set
# CONFIG_QCOM_RPMH is not set
# CONFIG_QCOM_RPM_MASTER_STATS is not set
CONFIG_QCOM_RPROC_COMMON=y
CONFIG_QCOM_SCM=y
# CONFIG_QCOM_SMD_RPM is not set
CONFIG_QCOM_SMEM=y
CONFIG_QCOM_SMEM_STATE=y
CONFIG_QCOM_SMP2P=y
# CONFIG_QCOM_SMSM is not set
CONFIG_QCOM_SOCINFO=y
# CONFIG_QCOM_SPM is not set
# CONFIG_QCOM_STATS is not set
# CONFIG_QCOM_SYSMON is not set
# CONFIG_QCOM_TMEL_QMP_MAILBOX is not set
CONFIG_QCOM_TSENS=y
CONFIG_QCOM_TZMEM=y
CONFIG_QCOM_TZMEM_MODE_GENERIC=y
# CONFIG_QCOM_TZMEM_MODE_SHMBRIDGE is not set
# CONFIG_QCOM_WCNSS_CTRL is not set
# CONFIG_QCOM_WCNSS_PIL is not set
CONFIG_QCOM_WDT=y
# CONFIG_QCS_GCC_404 is not set
# CONFIG_QCS_Q6SSTOP_404 is not set
# CONFIG_QCS_TURING_404 is not set
# CONFIG_QDU_ECPRICC_1000 is not set
# CONFIG_QDU_GCC_1000 is not set
CONFIG_QUEUED_RWLOCKS=y
CONFIG_QUEUED_SPINLOCKS=y
CONFIG_RANDSTRUCT_NONE=y
CONFIG_RAS=y
CONFIG_RATIONAL=y
CONFIG_REGMAP=y
CONFIG_REGMAP_I2C=y
CONFIG_REGMAP_MMIO=y
CONFIG_REGULATOR=y
# CONFIG_REGULATOR_CPR3 is not set
CONFIG_REGULATOR_FIXED_VOLTAGE=y
# CONFIG_REGULATOR_VQMMC_IPQ4019 is not set
CONFIG_RELOCATABLE=y
CONFIG_REMOTEPROC=y
CONFIG_REMOTEPROC_CDEV=y
CONFIG_RESET_CONTROLLER=y
# CONFIG_RESET_QCOM_AOSS is not set
# CONFIG_RESET_QCOM_PDC is not set
CONFIG_RFS_ACCEL=y
CONFIG_RODATA_FULL_DEFAULT_ENABLED=y
CONFIG_RPMSG=y
CONFIG_RPMSG_CHAR=y
# CONFIG_RPMSG_CTRL is not set
# CONFIG_RPMSG_NS is not set
CONFIG_RPMSG_QCOM_GLINK=y
CONFIG_RPMSG_QCOM_GLINK_RPM=y
CONFIG_RPMSG_QCOM_GLINK_SMEM=y
CONFIG_RPMSG_QCOM_SMD=y
# CONFIG_RPMSG_TTY is not set
CONFIG_RPS=y
CONFIG_RTC_CLASS=y
CONFIG_RTC_I2C_AND_SPI=y
CONFIG_RWSEM_SPIN_ON_OWNER=y
# CONFIG_SA_GCC_8775P is not set
# CONFIG_SA_GPUCC_8775P is not set
# CONFIG_SCHED_CORE is not set
CONFIG_SCHED_HW_PRESSURE=y
CONFIG_SCHED_MC=y
CONFIG_SCHED_SMT=y
CONFIG_SCSI=y
CONFIG_SCSI_COMMON=y
# CONFIG_SCSI_LOWLEVEL is not set
# CONFIG_SCSI_PROC_FS is not set
# CONFIG_SC_CAMCC_7280 is not set
# CONFIG_SC_CAMCC_8280XP is not set
# CONFIG_SC_DISPCC_7180 is not set
# CONFIG_SC_DISPCC_8280XP is not set
# CONFIG_SC_GCC_7180 is not set
# CONFIG_SC_GCC_8280XP is not set
# CONFIG_SC_GPUCC_7180 is not set
# CONFIG_SC_LPASSCC_7280 is not set
# CONFIG_SC_LPASSCC_8280XP is not set
# CONFIG_SC_LPASS_CORECC_7180 is not set
# CONFIG_SC_LPASS_CORECC_7280 is not set
# CONFIG_SC_VIDEOCC_7180 is not set
# CONFIG_SDM_CAMCC_845 is not set
# CONFIG_SDM_DISPCC_845 is not set
# CONFIG_SDM_GCC_660 is not set
# CONFIG_SDM_GCC_845 is not set
# CONFIG_SDM_GPUCC_845 is not set
# CONFIG_SDM_LPASSCC_845 is not set
# CONFIG_SDM_VIDEOCC_845 is not set
# CONFIG_SDX_GCC_75 is not set
CONFIG_SERIAL_8250_FSL=y
CONFIG_SERIAL_MCTRL_GPIO=y
CONFIG_SERIAL_MSM=y
CONFIG_SERIAL_MSM_CONSOLE=y
CONFIG_SGL_ALLOC=y
CONFIG_SG_POOL=y
CONFIG_SKB_EXTENSIONS=y
CONFIG_SMP=y
# CONFIG_SM_CAMCC_4450 is not set
# CONFIG_SM_CAMCC_6350 is not set
# CONFIG_SM_CAMCC_7150 is not set
# CONFIG_SM_CAMCC_8150 is not set
# CONFIG_SM_CAMCC_8450 is not set
# CONFIG_SM_CAMCC_8550 is not set
# CONFIG_SM_CAMCC_8650 is not set
# CONFIG_SM_GCC_4450 is not set
# CONFIG_SM_GCC_7150 is not set
# CONFIG_SM_GCC_8150 is not set
# CONFIG_SM_GCC_8250 is not set
# CONFIG_SM_GCC_8450 is not set
# CONFIG_SM_GCC_8550 is not set
# CONFIG_SM_GCC_8650 is not set
# CONFIG_SM_GPUCC_4450 is not set
# CONFIG_SM_GPUCC_6115 is not set
# CONFIG_SM_GPUCC_6125 is not set
# CONFIG_SM_GPUCC_6350 is not set
# CONFIG_SM_GPUCC_6375 is not set
# CONFIG_SM_GPUCC_8150 is not set
# CONFIG_SM_GPUCC_8250 is not set
# CONFIG_SM_GPUCC_8350 is not set
# CONFIG_SM_GPUCC_8450 is not set
# CONFIG_SM_GPUCC_8550 is not set
# CONFIG_SM_GPUCC_8650 is not set
# CONFIG_SM_TCSRCC_8550 is not set
# CONFIG_SM_TCSRCC_8650 is not set
# CONFIG_SM_VIDEOCC_7150 is not set
# CONFIG_SM_VIDEOCC_8150 is not set
# CONFIG_SM_VIDEOCC_8250 is not set
# CONFIG_SM_VIDEOCC_8350 is not set
# CONFIG_SM_VIDEOCC_8450 is not set
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_MASTER=y
CONFIG_SPI_MEM=y
# CONFIG_SPI_QPIC_SNAND is not set
CONFIG_SPI_QUP=y
CONFIG_SPLIT_PMD_PTLOCKS=y
CONFIG_SPLIT_PTE_PTLOCKS=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_HWMON=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_UBIFS_FS_ADVANCED_COMPR=y
# CONFIG_UCLAMP_TASK is not set
CONFIG_UNMAP_KERNEL_AT_EL0=y
CONFIG_USB=y
CONFIG_USB_COMMON=y
CONFIG_USB_SUPPORT=y
CONFIG_USER_STACKTRACE_SUPPORT=y
CONFIG_VDSO_GETRANDOM=y
CONFIG_VIRTIO=y
CONFIG_VIRTIO_ANCHOR=y
# CONFIG_VIRTIO_BLK is not set
# CONFIG_VIRTIO_DEBUG is not set
# CONFIG_VIRTIO_NET is not set
CONFIG_VMAP_STACK=y
CONFIG_WANT_DEV_COREDUMP=y
CONFIG_WATCHDOG_CORE=y
CONFIG_WATCHDOG_SYSFS=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

View file

@ -1,381 +0,0 @@
From 6f8c1ed25809181c187a59b1caaa1521756924bf Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Date: Tue, 22 Oct 2024 17:47:26 +0200
Subject: [PATCH] arm64: dts: qcom: ipq: change labels to lower-case
DTS coding style expects labels to be lowercase. No functional impact.
Verified with comparing decompiled DTB (dtx_diff and fdtdump+diff).
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20241022-dts-qcom-label-v3-1-0505bc7d2c56@linaro.org
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 10 +++---
arch/arm64/boot/dts/qcom/ipq5332.dtsi | 18 +++++-----
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 26 +++++++-------
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 18 +++++-----
arch/arm64/boot/dts/qcom/ipq9574.dtsi | 50 +++++++++++++--------------
5 files changed, 61 insertions(+), 61 deletions(-)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -31,27 +31,27 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-size = <0x80000>;
--- a/arch/arm64/boot/dts/qcom/ipq5332.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5332.dtsi
@@ -31,47 +31,47 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x2>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x3>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -34,12 +34,12 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -47,12 +47,12 @@
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x1>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -60,12 +60,12 @@
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -73,12 +73,12 @@
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -86,7 +86,7 @@
#cooling-cells = <2>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -1015,10 +1015,10 @@
cooling-maps {
map0 {
trip = <&cpu_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -32,39 +32,39 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a53";
reg = <0x0>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
enable-method = "psci";
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x1>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x2>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a53";
enable-method = "psci";
reg = <0x3>;
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
--- a/arch/arm64/boot/dts/qcom/ipq9574.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq9574.dtsi
@@ -34,12 +34,12 @@
#address-cells = <1>;
#size-cells = <0>;
- CPU0: cpu@0 {
+ cpu0: cpu@0 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x0>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -47,12 +47,12 @@
#cooling-cells = <2>;
};
- CPU1: cpu@1 {
+ cpu1: cpu@1 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x1>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -60,12 +60,12 @@
#cooling-cells = <2>;
};
- CPU2: cpu@2 {
+ cpu2: cpu@2 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x2>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -73,12 +73,12 @@
#cooling-cells = <2>;
};
- CPU3: cpu@3 {
+ cpu3: cpu@3 {
device_type = "cpu";
compatible = "arm,cortex-a73";
reg = <0x3>;
enable-method = "psci";
- next-level-cache = <&L2_0>;
+ next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
@@ -86,7 +86,7 @@
#cooling-cells = <2>;
};
- L2_0: l2-cache {
+ l2_0: l2-cache {
compatible = "cache";
cache-level = <2>;
cache-unified;
@@ -865,10 +865,10 @@
cooling-maps {
map0 {
trip = <&cpu0_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -893,10 +893,10 @@
cooling-maps {
map0 {
trip = <&cpu1_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -921,10 +921,10 @@
cooling-maps {
map0 {
trip = <&cpu2_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};
@@ -949,10 +949,10 @@
cooling-maps {
map0 {
trip = <&cpu3_alert>;
- cooling-device = <&CPU0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
- <&CPU3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu2 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu3 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
};
};
};

View file

@ -1,33 +0,0 @@
From 144230e5840c09984ad743c3df9de5fb443159a9 Mon Sep 17 00:00:00 2001
From: Chukun Pan <amadeus@jmu.edu.cn>
Date: Mon, 10 Feb 2025 15:01:18 +0800
Subject: [PATCH] arm64: dts: qcom: ipq6018: add 1.2GHz CPU Frequency
The final version of IPQ6000 (SoC id: IPQ6000, SBL version:
BOOT.XF.0.3-00086-IPQ60xxLZB-1) has a max design frequency
of 1.2GHz, so add this CPU frequency.
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250210070122.208842-2-amadeus@jmu.edu.cn
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -119,6 +119,13 @@
clock-latency-ns = <200000>;
};
+ opp-1200000000 {
+ opp-hz = /bits/ 64 <1200000000>;
+ opp-microvolt = <850000>;
+ opp-supported-hw = <0x4>;
+ clock-latency-ns = <200000>;
+ };
+
opp-1320000000 {
opp-hz = /bits/ 64 <1320000000>;
opp-microvolt = <862500>;

View file

@ -1,33 +0,0 @@
From a96e765a7b3f64429f7eec3471a2093355ab041e Mon Sep 17 00:00:00 2001
From: Chukun Pan <amadeus@jmu.edu.cn>
Date: Mon, 10 Feb 2025 15:01:19 +0800
Subject: [PATCH] arm64: dts: qcom: ipq6018: add 1.5GHz CPU Frequency
The early version of IPQ6000 (SoC id: IPQ6018, SBL version:
BOOT.XF.0.3-00077-IPQ60xxLZB-2) and IPQ6005 SoCs can reach
a max frequency of 1.5GHz, so add this CPU frequency.
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Reviewed-by: Konrad Dybcio <konrad.dybcio@linaro.org>
Link: https://lore.kernel.org/r/20250210070122.208842-3-amadeus@jmu.edu.cn
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 7 +++++++
1 file changed, 7 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -140,6 +140,13 @@
clock-latency-ns = <200000>;
};
+ opp-1512000000 {
+ opp-hz = /bits/ 64 <1512000000>;
+ opp-microvolt = <937500>;
+ opp-supported-hw = <0x2>;
+ clock-latency-ns = <200000>;
+ };
+
opp-1608000000 {
opp-hz = /bits/ 64 <1608000000>;
opp-microvolt = <987500>;

View file

@ -1,120 +0,0 @@
From 0c4c0f14b7d704bcb728d018a74788771dc9286b Mon Sep 17 00:00:00 2001
From: Chukun Pan <amadeus@jmu.edu.cn>
Date: Mon, 10 Feb 2025 15:01:20 +0800
Subject: [PATCH] arm64: dts: qcom: ipq6018: move mp5496 regulator out of soc dtsi
Some IPQ60xx SoCs don't come with the mp5496 pmic chip. The mp5496
pmic was never part of the IPQ60xx SoC, it's optional, so we moved
it out of the soc dtsi.
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/20250210070122.208842-4-amadeus@jmu.edu.cn
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts | 2 +-
arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi | 35 ++++++++++++++++++++++++++++
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 14 -----------
3 files changed, 36 insertions(+), 15 deletions(-)
create mode 100644 arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
--- a/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
+++ b/arch/arm64/boot/dts/qcom/ipq6018-cp01-c1.dts
@@ -7,7 +7,7 @@
/dts-v1/;
-#include "ipq6018.dtsi"
+#include "ipq6018-mp5496.dtsi"
/ {
model = "Qualcomm Technologies, Inc. IPQ6018/AP-CP01-C1";
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
+/*
+ * ipq6018-mp5496.dtsi describes common properties (e.g. regulators) that
+ * apply to most devices that make use of the IPQ6018 SoC and MP5496 PMIC.
+ */
+
+#include "ipq6018.dtsi"
+
+&cpu0 {
+ cpu-supply = <&ipq6018_s2>;
+};
+
+&cpu1 {
+ cpu-supply = <&ipq6018_s2>;
+};
+
+&cpu2 {
+ cpu-supply = <&ipq6018_s2>;
+};
+
+&cpu3 {
+ cpu-supply = <&ipq6018_s2>;
+};
+
+&rpm_requests {
+ regulators {
+ compatible = "qcom,rpm-mp5496-regulators";
+
+ ipq6018_s2: s2 {
+ regulator-min-microvolt = <725000>;
+ regulator-max-microvolt = <1062500>;
+ regulator-always-on;
+ };
+ };
+};
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -43,7 +43,6 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
- cpu-supply = <&ipq6018_s2>;
#cooling-cells = <2>;
};
@@ -56,7 +55,6 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
- cpu-supply = <&ipq6018_s2>;
#cooling-cells = <2>;
};
@@ -69,7 +67,6 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
- cpu-supply = <&ipq6018_s2>;
#cooling-cells = <2>;
};
@@ -82,7 +79,6 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
operating-points-v2 = <&cpu_opp_table>;
- cpu-supply = <&ipq6018_s2>;
#cooling-cells = <2>;
};
@@ -184,16 +180,6 @@
rpm_requests: rpm-requests {
compatible = "qcom,rpm-ipq6018", "qcom,glink-smd-rpm";
qcom,glink-channels = "rpm_requests";
-
- regulators {
- compatible = "qcom,rpm-mp5496-regulators";
-
- ipq6018_s2: s2 {
- regulator-min-microvolt = <725000>;
- regulator-max-microvolt = <1062500>;
- regulator-always-on;
- };
- };
};
};
};

View file

@ -1,50 +0,0 @@
From e60f872c2dc4c1d9227977c8714373fe6328699c Mon Sep 17 00:00:00 2001
From: Chukun Pan <amadeus@jmu.edu.cn>
Date: Mon, 10 Feb 2025 15:01:21 +0800
Subject: [PATCH] arm64: dts: qcom: ipq6018: rename labels of mp5496 regulator
Change the labels of mp5496 regulator from ipq6018 to mp5496.
Suggested-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Suggested-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Link: https://lore.kernel.org/r/20250210070122.208842-5-amadeus@jmu.edu.cn
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
@@ -7,26 +7,26 @@
#include "ipq6018.dtsi"
&cpu0 {
- cpu-supply = <&ipq6018_s2>;
+ cpu-supply = <&mp5496_s2>;
};
&cpu1 {
- cpu-supply = <&ipq6018_s2>;
+ cpu-supply = <&mp5496_s2>;
};
&cpu2 {
- cpu-supply = <&ipq6018_s2>;
+ cpu-supply = <&mp5496_s2>;
};
&cpu3 {
- cpu-supply = <&ipq6018_s2>;
+ cpu-supply = <&mp5496_s2>;
};
&rpm_requests {
regulators {
compatible = "qcom,rpm-mp5496-regulators";
- ipq6018_s2: s2 {
+ mp5496_s2: s2 {
regulator-min-microvolt = <725000>;
regulator-max-microvolt = <1062500>;
regulator-always-on;

View file

@ -1,33 +0,0 @@
From a566fb9ba8ffecb56c50729390a9ea076f5c9532 Mon Sep 17 00:00:00 2001
From: Chukun Pan <amadeus@jmu.edu.cn>
Date: Mon, 10 Feb 2025 15:01:22 +0800
Subject: [PATCH] arm64: dts: qcom: ipq6018: add LDOA2 regulator
Add LDOA2 regulator from MP5496 to support SDCC voltage scaling.
Suggested-by: Robert Marko <robimarko@gmail.com>
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250210070122.208842-6-amadeus@jmu.edu.cn
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018-mp5496.dtsi
@@ -31,5 +31,14 @@
regulator-max-microvolt = <1062500>;
regulator-always-on;
};
+
+ mp5496_l2: l2 {
+ regulator-min-microvolt = <1800000>;
+ regulator-max-microvolt = <3300000>;
+ };
};
};
+
+&sdhc {
+ vqmmc-supply = <&mp5496_l2>;
+};

View file

@ -1,340 +0,0 @@
From 74badb8b0b146668cc6c03eb58e2a814f9463d02 Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Thu, 20 Feb 2025 15:12:46 +0530
Subject: [PATCH] phy: qcom: Introduce PCIe UNIPHY 28LP driver
Add Qualcomm PCIe UNIPHY 28LP driver support present in Qualcomm IPQ5332
SoC and the phy init sequence.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: Varadarajan Narayanan <quic_varada@quicinc.com>
Link: https://lore.kernel.org/r/20250220094251.230936-3-quic_varada@quicinc.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/phy/qualcomm/Kconfig | 12 +
drivers/phy/qualcomm/Makefile | 1 +
.../phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c | 286 ++++++++++++++++++
3 files changed, 299 insertions(+)
create mode 100644 drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
--- a/drivers/phy/qualcomm/Kconfig
+++ b/drivers/phy/qualcomm/Kconfig
@@ -154,6 +154,18 @@ config PHY_QCOM_M31_USB
management. This driver is required even for peripheral only or
host only mode configurations.
+config PHY_QCOM_UNIPHY_PCIE_28LP
+ bool "PCIE UNIPHY 28LP PHY driver"
+ depends on ARCH_QCOM
+ depends on HAS_IOMEM
+ depends on OF
+ select GENERIC_PHY
+ help
+ Enable this to support the PCIe UNIPHY 28LP phy transceiver that
+ is used with PCIe controllers on Qualcomm IPQ5332 chips. It
+ handles PHY initialization, clock management required after
+ resetting the hardware and power management.
+
config PHY_QCOM_USB_HS
tristate "Qualcomm USB HS PHY module"
depends on USB_ULPI_BUS
--- a/drivers/phy/qualcomm/Makefile
+++ b/drivers/phy/qualcomm/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_PHY_QCOM_QMP_USB_LEGACY) +=
obj-$(CONFIG_PHY_QCOM_QUSB2) += phy-qcom-qusb2.o
obj-$(CONFIG_PHY_QCOM_SNPS_EUSB2) += phy-qcom-snps-eusb2.o
obj-$(CONFIG_PHY_QCOM_EUSB2_REPEATER) += phy-qcom-eusb2-repeater.o
+obj-$(CONFIG_PHY_QCOM_UNIPHY_PCIE_28LP) += phy-qcom-uniphy-pcie-28lp.o
obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o
obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o
obj-$(CONFIG_PHY_QCOM_USB_HS_28NM) += phy-qcom-usb-hs-28nm.o
--- /dev/null
+++ b/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
@@ -0,0 +1,286 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (c) 2025, The Linux Foundation. All rights reserved.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of.h>
+#include <linux/phy/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/reset.h>
+#include <linux/units.h>
+
+#define RST_ASSERT_DELAY_MIN_US 100
+#define RST_ASSERT_DELAY_MAX_US 150
+#define PIPE_CLK_DELAY_MIN_US 5000
+#define PIPE_CLK_DELAY_MAX_US 5100
+#define CLK_EN_DELAY_MIN_US 30
+#define CLK_EN_DELAY_MAX_US 50
+#define CDR_CTRL_REG_1 0x80
+#define CDR_CTRL_REG_2 0x84
+#define CDR_CTRL_REG_3 0x88
+#define CDR_CTRL_REG_4 0x8c
+#define CDR_CTRL_REG_5 0x90
+#define CDR_CTRL_REG_6 0x94
+#define CDR_CTRL_REG_7 0x98
+#define SSCG_CTRL_REG_1 0x9c
+#define SSCG_CTRL_REG_2 0xa0
+#define SSCG_CTRL_REG_3 0xa4
+#define SSCG_CTRL_REG_4 0xa8
+#define SSCG_CTRL_REG_5 0xac
+#define SSCG_CTRL_REG_6 0xb0
+#define PCS_INTERNAL_CONTROL_2 0x2d8
+
+#define PHY_CFG_PLLCFG 0x220
+#define PHY_CFG_EIOS_DTCT_REG 0x3e4
+#define PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME 0x3e8
+
+enum qcom_uniphy_pcie_type {
+ PHY_TYPE_PCIE = 1,
+ PHY_TYPE_PCIE_GEN2,
+ PHY_TYPE_PCIE_GEN3,
+};
+
+struct qcom_uniphy_pcie_regs {
+ u32 offset;
+ u32 val;
+};
+
+struct qcom_uniphy_pcie_data {
+ int lane_offset; /* offset between the lane register bases */
+ u32 phy_type;
+ const struct qcom_uniphy_pcie_regs *init_seq;
+ u32 init_seq_num;
+ u32 pipe_clk_rate;
+};
+
+struct qcom_uniphy_pcie {
+ struct phy phy;
+ struct device *dev;
+ const struct qcom_uniphy_pcie_data *data;
+ struct clk_bulk_data *clks;
+ int num_clks;
+ struct reset_control *resets;
+ void __iomem *base;
+ int lanes;
+};
+
+#define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy)
+
+static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
+ {
+ .offset = PHY_CFG_PLLCFG,
+ .val = 0x30,
+ }, {
+ .offset = PHY_CFG_EIOS_DTCT_REG,
+ .val = 0x53ef,
+ }, {
+ .offset = PHY_CFG_GEN3_ALIGN_HOLDOFF_TIME,
+ .val = 0xcf,
+ },
+};
+
+static const struct qcom_uniphy_pcie_data ipq5332_data = {
+ .lane_offset = 0x800,
+ .phy_type = PHY_TYPE_PCIE_GEN3,
+ .init_seq = ipq5332_regs,
+ .init_seq_num = ARRAY_SIZE(ipq5332_regs),
+ .pipe_clk_rate = 250 * MEGA,
+};
+
+static void qcom_uniphy_pcie_init(struct qcom_uniphy_pcie *phy)
+{
+ const struct qcom_uniphy_pcie_data *data = phy->data;
+ const struct qcom_uniphy_pcie_regs *init_seq;
+ void __iomem *base = phy->base;
+ int lane, i;
+
+ for (lane = 0; lane < phy->lanes; lane++) {
+ init_seq = data->init_seq;
+
+ for (i = 0; i < data->init_seq_num; i++)
+ writel(init_seq[i].val, base + init_seq[i].offset);
+
+ base += data->lane_offset;
+ }
+}
+
+static int qcom_uniphy_pcie_power_off(struct phy *x)
+{
+ struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
+
+ clk_bulk_disable_unprepare(phy->num_clks, phy->clks);
+
+ return reset_control_assert(phy->resets);
+}
+
+static int qcom_uniphy_pcie_power_on(struct phy *x)
+{
+ struct qcom_uniphy_pcie *phy = phy_get_drvdata(x);
+ int ret;
+
+ ret = reset_control_assert(phy->resets);
+ if (ret) {
+ dev_err(phy->dev, "reset assert failed (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(RST_ASSERT_DELAY_MIN_US, RST_ASSERT_DELAY_MAX_US);
+
+ ret = reset_control_deassert(phy->resets);
+ if (ret) {
+ dev_err(phy->dev, "reset deassert failed (%d)\n", ret);
+ return ret;
+ }
+
+ usleep_range(PIPE_CLK_DELAY_MIN_US, PIPE_CLK_DELAY_MAX_US);
+
+ ret = clk_bulk_prepare_enable(phy->num_clks, phy->clks);
+ if (ret) {
+ dev_err(phy->dev, "clk prepare and enable failed %d\n", ret);
+ return ret;
+ }
+
+ usleep_range(CLK_EN_DELAY_MIN_US, CLK_EN_DELAY_MAX_US);
+
+ qcom_uniphy_pcie_init(phy);
+
+ return 0;
+}
+
+static inline int qcom_uniphy_pcie_get_resources(struct platform_device *pdev,
+ struct qcom_uniphy_pcie *phy)
+{
+ struct resource *res;
+
+ phy->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
+ if (IS_ERR(phy->base))
+ return PTR_ERR(phy->base);
+
+ phy->num_clks = devm_clk_bulk_get_all(phy->dev, &phy->clks);
+ if (phy->num_clks < 0)
+ return phy->num_clks;
+
+ phy->resets = devm_reset_control_array_get_exclusive(phy->dev);
+ if (IS_ERR(phy->resets))
+ return PTR_ERR(phy->resets);
+
+ return 0;
+}
+
+/*
+ * Register a fixed rate pipe clock.
+ *
+ * The <s>_pipe_clksrc generated by PHY goes to the GCC that gate
+ * controls it. The <s>_pipe_clk coming out of the GCC is requested
+ * by the PHY driver for its operations.
+ * We register the <s>_pipe_clksrc here. The gcc driver takes care
+ * of assigning this <s>_pipe_clksrc as parent to <s>_pipe_clk.
+ * Below picture shows this relationship.
+ *
+ * +---------------+
+ * | PHY block |<<---------------------------------------+
+ * | | |
+ * | +-------+ | +-----+ |
+ * I/P---^-->| PLL |---^--->pipe_clksrc--->| GCC |--->pipe_clk---+
+ * clk | +-------+ | +-----+
+ * +---------------+
+ */
+static inline int phy_pipe_clk_register(struct qcom_uniphy_pcie *phy, int id)
+{
+ const struct qcom_uniphy_pcie_data *data = phy->data;
+ struct clk_hw *hw;
+ char name[64];
+
+ snprintf(name, sizeof(name), "phy%d_pipe_clk_src", id);
+ hw = devm_clk_hw_register_fixed_rate(phy->dev, name, NULL, 0,
+ data->pipe_clk_rate);
+ if (IS_ERR(hw))
+ return dev_err_probe(phy->dev, PTR_ERR(hw),
+ "Unable to register %s\n", name);
+
+ return devm_of_clk_add_hw_provider(phy->dev, of_clk_hw_simple_get, hw);
+}
+
+static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
+ {
+ .compatible = "qcom,ipq5332-uniphy-pcie-phy",
+ .data = &ipq5332_data,
+ }, {
+ /* Sentinel */
+ },
+};
+MODULE_DEVICE_TABLE(of, qcom_uniphy_pcie_id_table);
+
+static const struct phy_ops pcie_ops = {
+ .power_on = qcom_uniphy_pcie_power_on,
+ .power_off = qcom_uniphy_pcie_power_off,
+ .owner = THIS_MODULE,
+};
+
+static int qcom_uniphy_pcie_probe(struct platform_device *pdev)
+{
+ struct phy_provider *phy_provider;
+ struct device *dev = &pdev->dev;
+ struct qcom_uniphy_pcie *phy;
+ struct phy *generic_phy;
+ int ret;
+
+ phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
+ if (!phy)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, phy);
+ phy->dev = &pdev->dev;
+
+ phy->data = of_device_get_match_data(dev);
+ if (!phy->data)
+ return -EINVAL;
+
+ ret = of_property_read_u32(dev_of_node(dev), "num-lanes", &phy->lanes);
+ if (ret)
+ return dev_err_probe(dev, ret, "Couldn't read num-lanes\n");
+
+ ret = qcom_uniphy_pcie_get_resources(pdev, phy);
+ if (ret < 0)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to get resources: %d\n", ret);
+
+ generic_phy = devm_phy_create(phy->dev, NULL, &pcie_ops);
+ if (IS_ERR(generic_phy))
+ return PTR_ERR(generic_phy);
+
+ phy_set_drvdata(generic_phy, phy);
+
+ ret = phy_pipe_clk_register(phy, generic_phy->id);
+ if (ret)
+ dev_err(&pdev->dev, "failed to register phy pipe clk\n");
+
+ phy_provider = devm_of_phy_provider_register(phy->dev,
+ of_phy_simple_xlate);
+ if (IS_ERR(phy_provider))
+ return PTR_ERR(phy_provider);
+
+ return 0;
+}
+
+static struct platform_driver qcom_uniphy_pcie_driver = {
+ .probe = qcom_uniphy_pcie_probe,
+ .driver = {
+ .name = "qcom-uniphy-pcie",
+ .of_match_table = qcom_uniphy_pcie_id_table,
+ },
+};
+
+module_platform_driver(qcom_uniphy_pcie_driver);
+
+MODULE_DESCRIPTION("PCIE QCOM UNIPHY driver");
+MODULE_LICENSE("GPL");

View file

@ -1,86 +0,0 @@
From dfc820d2f8a8ea90bbc02269b5362e3678e58cac Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Wed, 26 Mar 2025 12:10:56 +0400
Subject: [PATCH] phy: qualcomm: qcom-uniphy-pcie 28LP add support for IPQ5018
The Qualcomm UNIPHY PCIe PHY 28LP is found on both IPQ5332 and IPQ5018.
Adding the PHY init sequence, pipe clock rate, and compatible for IPQ5018.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250326-ipq5018-pcie-v7-2-e1828fef06c9@outlook.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
.../phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c | 45 +++++++++++++++++++
1 file changed, 45 insertions(+)
--- a/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
+++ b/drivers/phy/qualcomm/phy-qcom-uniphy-pcie-28lp.c
@@ -75,6 +75,40 @@ struct qcom_uniphy_pcie {
#define phy_to_dw_phy(x) container_of((x), struct qca_uni_pcie_phy, phy)
+static const struct qcom_uniphy_pcie_regs ipq5018_regs[] = {
+ {
+ .offset = SSCG_CTRL_REG_4,
+ .val = 0x1cb9,
+ }, {
+ .offset = SSCG_CTRL_REG_5,
+ .val = 0x023a,
+ }, {
+ .offset = SSCG_CTRL_REG_3,
+ .val = 0xd360,
+ }, {
+ .offset = SSCG_CTRL_REG_1,
+ .val = 0x1,
+ }, {
+ .offset = SSCG_CTRL_REG_2,
+ .val = 0xeb,
+ }, {
+ .offset = CDR_CTRL_REG_4,
+ .val = 0x3f9,
+ }, {
+ .offset = CDR_CTRL_REG_5,
+ .val = 0x1c9,
+ }, {
+ .offset = CDR_CTRL_REG_2,
+ .val = 0x419,
+ }, {
+ .offset = CDR_CTRL_REG_1,
+ .val = 0x200,
+ }, {
+ .offset = PCS_INTERNAL_CONTROL_2,
+ .val = 0xf101,
+ },
+};
+
static const struct qcom_uniphy_pcie_regs ipq5332_regs[] = {
{
.offset = PHY_CFG_PLLCFG,
@@ -88,6 +122,14 @@ static const struct qcom_uniphy_pcie_reg
},
};
+static const struct qcom_uniphy_pcie_data ipq5018_data = {
+ .lane_offset = 0x800,
+ .phy_type = PHY_TYPE_PCIE_GEN2,
+ .init_seq = ipq5018_regs,
+ .init_seq_num = ARRAY_SIZE(ipq5018_regs),
+ .pipe_clk_rate = 125 * MEGA,
+};
+
static const struct qcom_uniphy_pcie_data ipq5332_data = {
.lane_offset = 0x800,
.phy_type = PHY_TYPE_PCIE_GEN3,
@@ -212,6 +254,9 @@ static inline int phy_pipe_clk_register(
static const struct of_device_id qcom_uniphy_pcie_id_table[] = {
{
+ .compatible = "qcom,ipq5018-uniphy-pcie-phy",
+ .data = &ipq5018_data,
+ }, {
.compatible = "qcom,ipq5332-uniphy-pcie-phy",
.data = &ipq5332_data,
}, {

View file

@ -1,31 +0,0 @@
From 3e5127469a8d41153fb30031a271788f52dd17ec Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Wed, 26 Mar 2025 12:10:58 +0400
Subject: [PATCH] PCI: qcom: Add support for IPQ5018
Add IPQ5018 platform with is based on Qcom IP rev. 2.9.0 and Synopsys IP
rev. 5.00a.
The platform itself has two PCIe Gen2 controllers: one single-lane and
one dual-lane. So add the IPQ5018 compatible and re-use 2_9_0 ops.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: Sricharan R <quic_srichara@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Link: https://patch.msgid.link/20250326-ipq5018-pcie-v7-4-e1828fef06c9@outlook.com
---
drivers/pci/controller/dwc/pcie-qcom.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/pci/controller/dwc/pcie-qcom.c
+++ b/drivers/pci/controller/dwc/pcie-qcom.c
@@ -1838,6 +1838,7 @@ static const struct of_device_id qcom_pc
{ .compatible = "qcom,pcie-apq8064", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-apq8084", .data = &cfg_1_0_0 },
{ .compatible = "qcom,pcie-ipq4019", .data = &cfg_2_4_0 },
+ { .compatible = "qcom,pcie-ipq5018", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-ipq6018", .data = &cfg_2_9_0 },
{ .compatible = "qcom,pcie-ipq8064", .data = &cfg_2_1_0 },
{ .compatible = "qcom,pcie-ipq8064-v2", .data = &cfg_2_1_0 },

View file

@ -1,286 +0,0 @@
From 18a5bf00a02ca54d51266b861518f2844c4f08d7 Mon Sep 17 00:00:00 2001
From: Nitheesh Sekar <quic_nsekar@quicinc.com>
Date: Wed, 14 May 2025 09:52:13 +0400
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add PCIe related nodes
Add phy and controller nodes for a 2-lane Gen2 and
a 1-lane Gen2 PCIe bus. IPQ5018 has 8 MSI SPI interrupts and
one global interrupt.
NOTE: the PCIe controller supports gen3, yet the phy is limited to gen2.
Signed-off-by: Nitheesh Sekar <quic_nsekar@quicinc.com>
Signed-off-by: Sricharan R <quic_srichara@quicinc.com>
Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250514-ipq5018-pcie-v10-1-5b42a8eff7ea@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 240 +++++++++++++++++++++++++-
1 file changed, 238 insertions(+), 2 deletions(-)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -147,6 +147,40 @@
status = "disabled";
};
+ pcie1_phy: phy@7e000 {
+ compatible = "qcom,ipq5018-uniphy-pcie-phy";
+ reg = <0x0007e000 0x800>;
+
+ clocks = <&gcc GCC_PCIE1_PIPE_CLK>;
+
+ resets = <&gcc GCC_PCIE1_PHY_BCR>,
+ <&gcc GCC_PCIE1PHY_PHY_BCR>;
+
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+
+ num-lanes = <1>;
+
+ status = "disabled";
+ };
+
+ pcie0_phy: phy@86000 {
+ compatible = "qcom,ipq5018-uniphy-pcie-phy";
+ reg = <0x00086000 0x1000>;
+
+ clocks = <&gcc GCC_PCIE0_PIPE_CLK>;
+
+ resets = <&gcc GCC_PCIE0_PHY_BCR>,
+ <&gcc GCC_PCIE0PHY_PHY_BCR>;
+
+ #clock-cells = <0>;
+ #phy-cells = <0>;
+
+ num-lanes = <2>;
+
+ status = "disabled";
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq5018-tlmm";
reg = <0x01000000 0x300000>;
@@ -170,8 +204,8 @@
reg = <0x01800000 0x80000>;
clocks = <&xo_board_clk>,
<&sleep_clk>,
- <0>,
- <0>,
+ <&pcie0_phy>,
+ <&pcie1_phy>,
<0>,
<0>,
<0>,
@@ -387,6 +421,208 @@
status = "disabled";
};
};
+
+ pcie1: pcie@80000000 {
+ compatible = "qcom,pcie-ipq5018";
+ reg = <0x80000000 0xf1d>,
+ <0x80000f20 0xa8>,
+ <0x80001000 0x1000>,
+ <0x00078000 0x3000>,
+ <0x80100000 0x1000>,
+ <0x0007b000 0x1000>;
+ reg-names = "dbi",
+ "elbi",
+ "atu",
+ "parf",
+ "config",
+ "mhi";
+ device_type = "pci";
+ linux,pci-domain = <1>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <1>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ /* The controller supports Gen3, but the connected PHY is Gen2-capable */
+ max-link-speed = <2>;
+
+ phys = <&pcie1_phy>;
+ phy-names ="pciephy";
+
+ ranges = <0x01000000 0 0x00000000 0x80200000 0 0x00100000>,
+ <0x02000000 0 0x80300000 0x80300000 0 0x10000000>;
+
+ msi-map = <0x0 &v2m0 0x0 0xff8>;
+
+ interrupts = <GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0",
+ "msi1",
+ "msi2",
+ "msi3",
+ "msi4",
+ "msi5",
+ "msi6",
+ "msi7",
+ "global";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 142 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 143 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 144 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 145 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_SYS_NOC_PCIE1_AXI_CLK>,
+ <&gcc GCC_PCIE1_AXI_M_CLK>,
+ <&gcc GCC_PCIE1_AXI_S_CLK>,
+ <&gcc GCC_PCIE1_AHB_CLK>,
+ <&gcc GCC_PCIE1_AUX_CLK>,
+ <&gcc GCC_PCIE1_AXI_S_BRIDGE_CLK>;
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "aux",
+ "axi_bridge";
+
+ resets = <&gcc GCC_PCIE1_PIPE_ARES>,
+ <&gcc GCC_PCIE1_SLEEP_ARES>,
+ <&gcc GCC_PCIE1_CORE_STICKY_ARES>,
+ <&gcc GCC_PCIE1_AXI_MASTER_ARES>,
+ <&gcc GCC_PCIE1_AXI_SLAVE_ARES>,
+ <&gcc GCC_PCIE1_AHB_ARES>,
+ <&gcc GCC_PCIE1_AXI_MASTER_STICKY_ARES>,
+ <&gcc GCC_PCIE1_AXI_SLAVE_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky",
+ "axi_s_sticky";
+
+ status = "disabled";
+
+ pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ bus-range = <0x01 0xff>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+ };
+
+ pcie0: pcie@a0000000 {
+ compatible = "qcom,pcie-ipq5018";
+ reg = <0xa0000000 0xf1d>,
+ <0xa0000f20 0xa8>,
+ <0xa0001000 0x1000>,
+ <0x00080000 0x3000>,
+ <0xa0100000 0x1000>,
+ <0x00083000 0x1000>;
+ reg-names = "dbi",
+ "elbi",
+ "atu",
+ "parf",
+ "config",
+ "mhi";
+ device_type = "pci";
+ linux,pci-domain = <0>;
+ bus-range = <0x00 0xff>;
+ num-lanes = <2>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+
+ /* The controller supports Gen3, but the connected PHY is Gen2-capable */
+ max-link-speed = <2>;
+
+ phys = <&pcie0_phy>;
+ phy-names ="pciephy";
+
+ ranges = <0x01000000 0 0x00000000 0xa0200000 0 0x00100000>,
+ <0x02000000 0 0xa0300000 0xa0300000 0 0x10000000>;
+
+ msi-map = <0x0 &v2m0 0x0 0xff8>;
+
+ interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 56 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 59 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 63 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 68 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 72 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 51 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "msi0",
+ "msi1",
+ "msi2",
+ "msi3",
+ "msi4",
+ "msi5",
+ "msi6",
+ "msi7",
+ "global";
+
+ #interrupt-cells = <1>;
+ interrupt-map-mask = <0 0 0 0x7>;
+ interrupt-map = <0 0 0 1 &intc 0 0 75 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 2 &intc 0 0 78 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 3 &intc 0 0 79 IRQ_TYPE_LEVEL_HIGH>,
+ <0 0 0 4 &intc 0 0 83 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_SYS_NOC_PCIE0_AXI_CLK>,
+ <&gcc GCC_PCIE0_AXI_M_CLK>,
+ <&gcc GCC_PCIE0_AXI_S_CLK>,
+ <&gcc GCC_PCIE0_AHB_CLK>,
+ <&gcc GCC_PCIE0_AUX_CLK>,
+ <&gcc GCC_PCIE0_AXI_S_BRIDGE_CLK>;
+ clock-names = "iface",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "aux",
+ "axi_bridge";
+
+ resets = <&gcc GCC_PCIE0_PIPE_ARES>,
+ <&gcc GCC_PCIE0_SLEEP_ARES>,
+ <&gcc GCC_PCIE0_CORE_STICKY_ARES>,
+ <&gcc GCC_PCIE0_AXI_MASTER_ARES>,
+ <&gcc GCC_PCIE0_AXI_SLAVE_ARES>,
+ <&gcc GCC_PCIE0_AHB_ARES>,
+ <&gcc GCC_PCIE0_AXI_MASTER_STICKY_ARES>,
+ <&gcc GCC_PCIE0_AXI_SLAVE_STICKY_ARES>;
+ reset-names = "pipe",
+ "sleep",
+ "sticky",
+ "axi_m",
+ "axi_s",
+ "ahb",
+ "axi_m_sticky",
+ "axi_s_sticky";
+
+ status = "disabled";
+
+ pcie@0 {
+ device_type = "pci";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ bus-range = <0x01 0xff>;
+
+ #address-cells = <3>;
+ #size-cells = <2>;
+ ranges;
+ };
+ };
};
timer {

View file

@ -1,38 +0,0 @@
From 43fefd6c71291b5793e7c4052b6e3e54d1d87715 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 12 May 2025 18:36:47 +0400
Subject: [PATCH] arm64: dts: qcom: ipq5018: enable the download mode support
Enable support for download mode to collect RAM dumps in case of a
system crash, allowing post mortem analysis.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250512-ipq5018-syscon-v1-2-eb1ad2414c3c@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 6 ++++++
1 file changed, 6 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -79,6 +79,7 @@
firmware {
scm {
compatible = "qcom,scm-ipq5018", "qcom,scm";
+ qcom,dload-mode = <&tcsr 0x6100>;
qcom,sdi-enabled;
};
};
@@ -221,6 +222,11 @@
#hwlock-cells = <1>;
};
+ tcsr: syscon@1937000 {
+ compatible = "qcom,tcsr-ipq5018", "syscon";
+ reg = <0x01937000 0x21000>;
+ };
+
sdhc_1: mmc@7804000 {
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
reg = <0x7804000 0x1000>;

View file

@ -1,297 +0,0 @@
From ff0cf0ab9073727a67f9902dba77a758654ae895 Mon Sep 17 00:00:00 2001
From: Praveenkumar I <quic_ipkumar@quicinc.com>
Date: Mon, 10 Feb 2025 17:34:32 +0530
Subject: [PATCH] thermal/drivers/tsens: Add TSENS enable and calibration
support for V2
SoCs without RPM need to enable sensors and calibrate them from the kernel.
The IPQ5332 and IPQ5424 use the tsens v2.3.3 IP and do not have RPM.
Therefore, add a new calibration function for V2, as the tsens.c calib
function only supports V1. Also add new feature_config, ops and data for
IPQ5332, IPQ5424.
Although the TSENS IP supports 16 sensors, not all are used. The hw_id
is used to enable the relevant sensors.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Praveenkumar I <quic_ipkumar@quicinc.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Link: https://lore.kernel.org/r/20250210120436.821684-3-quic_mmanikan@quicinc.com
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/thermal/qcom/tsens-v2.c | 178 ++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 8 +-
drivers/thermal/qcom/tsens.h | 3 +
3 files changed, 188 insertions(+), 1 deletion(-)
--- a/drivers/thermal/qcom/tsens-v2.c
+++ b/drivers/thermal/qcom/tsens-v2.c
@@ -4,13 +4,32 @@
* Copyright (c) 2018, Linaro Limited
*/
+#include <linux/bitfield.h>
#include <linux/bitops.h>
+#include <linux/nvmem-consumer.h>
#include <linux/regmap.h>
#include "tsens.h"
/* ----- SROT ------ */
#define SROT_HW_VER_OFF 0x0000
#define SROT_CTRL_OFF 0x0004
+#define SROT_MEASURE_PERIOD 0x0008
+#define SROT_Sn_CONVERSION 0x0060
+#define V2_SHIFT_DEFAULT 0x0003
+#define V2_SLOPE_DEFAULT 0x0cd0
+#define V2_CZERO_DEFAULT 0x016a
+#define ONE_PT_SLOPE 0x0cd0
+#define TWO_PT_SHIFTED_GAIN 921600
+#define ONE_PT_CZERO_CONST 94
+#define SW_RST_DEASSERT 0x0
+#define SW_RST_ASSERT 0x1
+#define MEASURE_PERIOD_2mSEC 0x1
+#define RESULT_FORMAT_TEMP 0x1
+#define TSENS_ENABLE 0x1
+#define SENSOR_CONVERSION(n) (((n) * 4) + SROT_Sn_CONVERSION)
+#define CONVERSION_SHIFT_MASK GENMASK(24, 23)
+#define CONVERSION_SLOPE_MASK GENMASK(22, 10)
+#define CONVERSION_CZERO_MASK GENMASK(9, 0)
/* ----- TM ------ */
#define TM_INT_EN_OFF 0x0004
@@ -50,6 +69,17 @@ static struct tsens_features ipq8074_fea
.trip_max_temp = 204000,
};
+static struct tsens_features ipq5332_feat = {
+ .ver_major = VER_2_X_NO_RPM,
+ .crit_int = 1,
+ .combo_int = 1,
+ .adc = 0,
+ .srot_split = 1,
+ .max_sensors = 16,
+ .trip_min_temp = 0,
+ .trip_max_temp = 204000,
+};
+
static const struct reg_field tsens_v2_regfields[MAX_REGFIELDS] = {
/* ----- SROT ------ */
/* VERSION */
@@ -59,6 +89,10 @@ static const struct reg_field tsens_v2_r
/* CTRL_OFF */
[TSENS_EN] = REG_FIELD(SROT_CTRL_OFF, 0, 0),
[TSENS_SW_RST] = REG_FIELD(SROT_CTRL_OFF, 1, 1),
+ [SENSOR_EN] = REG_FIELD(SROT_CTRL_OFF, 3, 18),
+ [CODE_OR_TEMP] = REG_FIELD(SROT_CTRL_OFF, 21, 21),
+
+ [MAIN_MEASURE_PERIOD] = REG_FIELD(SROT_MEASURE_PERIOD, 0, 7),
/* ----- TM ------ */
/* INTERRUPT ENABLE */
@@ -104,6 +138,128 @@ static const struct reg_field tsens_v2_r
[TRDY] = REG_FIELD(TM_TRDY_OFF, 0, 0),
};
+static int tsens_v2_calibrate_sensor(struct device *dev, struct tsens_sensor *sensor,
+ struct regmap *map, u32 mode, u32 base0, u32 base1)
+{
+ u32 shift = V2_SHIFT_DEFAULT;
+ u32 slope = V2_SLOPE_DEFAULT;
+ u32 czero = V2_CZERO_DEFAULT;
+ char name[20];
+ u32 val;
+ int ret;
+
+ /* Read offset value */
+ ret = snprintf(name, sizeof(name), "tsens_sens%d_off", sensor->hw_id);
+ if (ret < 0)
+ return ret;
+
+ ret = nvmem_cell_read_variable_le_u32(dev, name, &sensor->offset);
+ if (ret)
+ return ret;
+
+ /* Based on calib mode, program SHIFT, SLOPE and CZERO */
+ switch (mode) {
+ case TWO_PT_CALIB:
+ slope = (TWO_PT_SHIFTED_GAIN / (base1 - base0));
+
+ czero = (base0 + sensor->offset - ((base1 - base0) / 3));
+
+ break;
+ case ONE_PT_CALIB2:
+ czero = base0 + sensor->offset - ONE_PT_CZERO_CONST;
+
+ slope = ONE_PT_SLOPE;
+
+ break;
+ default:
+ dev_dbg(dev, "calibrationless mode\n");
+ }
+
+ val = FIELD_PREP(CONVERSION_SHIFT_MASK, shift) |
+ FIELD_PREP(CONVERSION_SLOPE_MASK, slope) |
+ FIELD_PREP(CONVERSION_CZERO_MASK, czero);
+
+ regmap_write(map, SENSOR_CONVERSION(sensor->hw_id), val);
+
+ return 0;
+}
+
+static int tsens_v2_calibration(struct tsens_priv *priv)
+{
+ struct device *dev = priv->dev;
+ u32 mode, base0, base1;
+ int i, ret;
+
+ if (priv->num_sensors > MAX_SENSORS)
+ return -EINVAL;
+
+ ret = nvmem_cell_read_variable_le_u32(priv->dev, "mode", &mode);
+ if (ret == -ENOENT)
+ dev_warn(priv->dev, "Calibration data not present in DT\n");
+ if (ret < 0)
+ return ret;
+
+ dev_dbg(priv->dev, "calibration mode is %d\n", mode);
+
+ ret = nvmem_cell_read_variable_le_u32(priv->dev, "base0", &base0);
+ if (ret < 0)
+ return ret;
+
+ ret = nvmem_cell_read_variable_le_u32(priv->dev, "base1", &base1);
+ if (ret < 0)
+ return ret;
+
+ /* Calibrate each sensor */
+ for (i = 0; i < priv->num_sensors; i++) {
+ ret = tsens_v2_calibrate_sensor(dev, &priv->sensor[i], priv->srot_map,
+ mode, base0, base1);
+ if (ret < 0)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __init init_tsens_v2_no_rpm(struct tsens_priv *priv)
+{
+ struct device *dev = priv->dev;
+ int i, ret;
+ u32 val = 0;
+
+ ret = init_common(priv);
+ if (ret < 0)
+ return ret;
+
+ priv->rf[CODE_OR_TEMP] = devm_regmap_field_alloc(dev, priv->srot_map,
+ priv->fields[CODE_OR_TEMP]);
+ if (IS_ERR(priv->rf[CODE_OR_TEMP]))
+ return PTR_ERR(priv->rf[CODE_OR_TEMP]);
+
+ priv->rf[MAIN_MEASURE_PERIOD] = devm_regmap_field_alloc(dev, priv->srot_map,
+ priv->fields[MAIN_MEASURE_PERIOD]);
+ if (IS_ERR(priv->rf[MAIN_MEASURE_PERIOD]))
+ return PTR_ERR(priv->rf[MAIN_MEASURE_PERIOD]);
+
+ regmap_field_write(priv->rf[TSENS_SW_RST], SW_RST_ASSERT);
+
+ regmap_field_write(priv->rf[MAIN_MEASURE_PERIOD], MEASURE_PERIOD_2mSEC);
+
+ /* Enable available sensors */
+ for (i = 0; i < priv->num_sensors; i++)
+ val |= 1 << priv->sensor[i].hw_id;
+
+ regmap_field_write(priv->rf[SENSOR_EN], val);
+
+ /* Select temperature format, unit is deci-Celsius */
+ regmap_field_write(priv->rf[CODE_OR_TEMP], RESULT_FORMAT_TEMP);
+
+ regmap_field_write(priv->rf[TSENS_SW_RST], SW_RST_DEASSERT);
+
+ regmap_field_write(priv->rf[TSENS_EN], TSENS_ENABLE);
+
+ return 0;
+}
+
static const struct tsens_ops ops_generic_v2 = {
.init = init_common,
.get_temp = get_temp_tsens_valid,
@@ -122,6 +278,28 @@ struct tsens_plat_data data_ipq8074 = {
.fields = tsens_v2_regfields,
};
+static const struct tsens_ops ops_ipq5332 = {
+ .init = init_tsens_v2_no_rpm,
+ .get_temp = get_temp_tsens_valid,
+ .calibrate = tsens_v2_calibration,
+};
+
+const struct tsens_plat_data data_ipq5332 = {
+ .num_sensors = 5,
+ .ops = &ops_ipq5332,
+ .hw_ids = (unsigned int []){11, 12, 13, 14, 15},
+ .feat = &ipq5332_feat,
+ .fields = tsens_v2_regfields,
+};
+
+const struct tsens_plat_data data_ipq5424 = {
+ .num_sensors = 7,
+ .ops = &ops_ipq5332,
+ .hw_ids = (unsigned int []){9, 10, 11, 12, 13, 14, 15},
+ .feat = &ipq5332_feat,
+ .fields = tsens_v2_regfields,
+};
+
/* Kept around for backward compatibility with old msm8996.dtsi */
struct tsens_plat_data data_8996 = {
.num_sensors = 13,
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -975,7 +975,7 @@ int __init init_common(struct tsens_priv
ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
if (ret)
goto err_put_device;
- if (!enabled) {
+ if (!enabled && (tsens_version(priv) != VER_2_X_NO_RPM)) {
dev_err(dev, "%s: device not enabled\n", __func__);
ret = -ENODEV;
goto err_put_device;
@@ -1102,6 +1102,12 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, t
static const struct of_device_id tsens_table[] = {
{
+ .compatible = "qcom,ipq5332-tsens",
+ .data = &data_ipq5332,
+ }, {
+ .compatible = "qcom,ipq5424-tsens",
+ .data = &data_ipq5424,
+ }, {
.compatible = "qcom,ipq8064-tsens",
.data = &data_8960,
}, {
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -35,6 +35,7 @@ enum tsens_ver {
VER_0_1,
VER_1_X,
VER_2_X,
+ VER_2_X_NO_RPM,
};
enum tsens_irq_type {
@@ -168,6 +169,7 @@ enum regfield_ids {
TSENS_SW_RST,
SENSOR_EN,
CODE_OR_TEMP,
+ MAIN_MEASURE_PERIOD,
/* ----- TM ------ */
/* TRDY */
@@ -651,5 +653,6 @@ extern struct tsens_plat_data data_tsens
/* TSENS v2 targets */
extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
+extern const struct tsens_plat_data data_ipq5332, data_ipq5424;
#endif /* __QCOM_TSENS_H__ */

View file

@ -1,69 +0,0 @@
From e3f90f167a49902cda2408f7e91cca0dcfd5040a Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 28 Feb 2025 09:11:36 +0400
Subject: [PATCH] thermal/drivers/qcom/tsens: Update conditions to strictly
evaluate for IP v2+
TSENS v2.0+ leverage features not available to prior versions such as
updated interrupts init routine, masked interrupts, and watchdog.
Currently, the checks in place evaluate whether the IP version is greater
than v1 which invalidates when updates to v1 or v1 minor versions are
implemented. As such, update the conditional statements to strictly
evaluate whether the version is greater than or equal to v2 (inclusive).
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Amit Kucheria <amitk@kernel.org>
Link: https://lore.kernel.org/r/DS7PR19MB8883434CAA053648E22AA8AC9DCC2@DS7PR19MB8883.namprd19.prod.outlook.com
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/thermal/qcom/tsens.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -447,7 +447,7 @@ static void tsens_set_interrupt(struct t
dev_dbg(priv->dev, "[%u] %s: %s -> %s\n", hw_id, __func__,
irq_type ? ((irq_type == 1) ? "UP" : "CRITICAL") : "LOW",
enable ? "en" : "dis");
- if (tsens_version(priv) > VER_1_X)
+ if (tsens_version(priv) >= VER_2_X)
tsens_set_interrupt_v2(priv, hw_id, irq_type, enable);
else
tsens_set_interrupt_v1(priv, hw_id, irq_type, enable);
@@ -499,7 +499,7 @@ static int tsens_read_irq_state(struct t
ret = regmap_field_read(priv->rf[LOW_INT_CLEAR_0 + hw_id], &d->low_irq_clear);
if (ret)
return ret;
- if (tsens_version(priv) > VER_1_X) {
+ if (tsens_version(priv) >= VER_2_X) {
ret = regmap_field_read(priv->rf[UP_INT_MASK_0 + hw_id], &d->up_irq_mask);
if (ret)
return ret;
@@ -543,7 +543,7 @@ static int tsens_read_irq_state(struct t
static inline u32 masked_irq(u32 hw_id, u32 mask, enum tsens_ver ver)
{
- if (ver > VER_1_X)
+ if (ver >= VER_2_X)
return mask & (1 << hw_id);
/* v1, v0.1 don't have a irq mask register */
@@ -733,7 +733,7 @@ static int tsens_set_trips(struct therma
static int tsens_enable_irq(struct tsens_priv *priv)
{
int ret;
- int val = tsens_version(priv) > VER_1_X ? 7 : 1;
+ int val = tsens_version(priv) >= VER_2_X ? 7 : 1;
ret = regmap_field_write(priv->rf[INT_EN], val);
if (ret < 0)
@@ -1040,7 +1040,7 @@ int __init init_common(struct tsens_priv
}
}
- if (tsens_version(priv) > VER_1_X && ver_minor > 2) {
+ if (tsens_version(priv) >= VER_2_X && ver_minor > 2) {
/* Watchdog is present only on v2.3+ */
priv->feat->has_watchdog = 1;
for (i = WDOG_BARK_STATUS; i <= CC_MON_MASK; i++) {

View file

@ -1,121 +0,0 @@
From 19f9b02ebc8fe3babefbe76a37c74c5f4c174de1 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 28 Feb 2025 09:11:37 +0400
Subject: [PATCH] thermal/drivers/qcom/tsens: Add support for tsens v1 without
RPM
Adding generic support for SoCs with tsens v1.0 IP with no RPM.
Due to lack of RPM, tsens has to be reset and enabled in the driver
init. SoCs can have support for more sensors than those which will
actually be enabled. As such, init will only enable those explicitly
added to the hw_ids array.
Co-developed-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Link: https://lore.kernel.org/r/DS7PR19MB8883C5D7974C7735E23923769DCC2@DS7PR19MB8883.namprd19.prod.outlook.com
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/thermal/qcom/tsens-v1.c | 48 +++++++++++++++++++++++++++++++++
drivers/thermal/qcom/tsens.c | 14 +++++++---
drivers/thermal/qcom/tsens.h | 1 +
3 files changed, 59 insertions(+), 4 deletions(-)
--- a/drivers/thermal/qcom/tsens-v1.c
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -79,6 +79,17 @@ static struct tsens_features tsens_v1_fe
.trip_max_temp = 120000,
};
+static struct tsens_features tsens_v1_no_rpm_feat = {
+ .ver_major = VER_1_X_NO_RPM,
+ .crit_int = 0,
+ .combo_int = 0,
+ .adc = 1,
+ .srot_split = 1,
+ .max_sensors = 11,
+ .trip_min_temp = -40000,
+ .trip_max_temp = 120000,
+};
+
static const struct reg_field tsens_v1_regfields[MAX_REGFIELDS] = {
/* ----- SROT ------ */
/* VERSION */
@@ -150,6 +161,43 @@ static int __init init_8956(struct tsens
return init_common(priv);
}
+static int __init init_tsens_v1_no_rpm(struct tsens_priv *priv)
+{
+ int i, ret;
+ u32 mask = 0;
+
+ ret = init_common(priv);
+ if (ret < 0) {
+ dev_err(priv->dev, "Init common failed %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_field_write(priv->rf[TSENS_SW_RST], 1);
+ if (ret) {
+ dev_err(priv->dev, "Reset failed\n");
+ return ret;
+ }
+
+ for (i = 0; i < priv->num_sensors; i++)
+ mask |= BIT(priv->sensor[i].hw_id);
+
+ ret = regmap_field_update_bits(priv->rf[SENSOR_EN], mask, mask);
+ if (ret) {
+ dev_err(priv->dev, "Sensor Enable failed\n");
+ return ret;
+ }
+
+ ret = regmap_field_write(priv->rf[TSENS_EN], 1);
+ if (ret) {
+ dev_err(priv->dev, "Enable failed\n");
+ return ret;
+ }
+
+ ret = regmap_field_write(priv->rf[TSENS_SW_RST], 0);
+
+ return ret;
+}
+
static const struct tsens_ops ops_generic_v1 = {
.init = init_common,
.calibrate = calibrate_v1,
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -975,10 +975,16 @@ int __init init_common(struct tsens_priv
ret = regmap_field_read(priv->rf[TSENS_EN], &enabled);
if (ret)
goto err_put_device;
- if (!enabled && (tsens_version(priv) != VER_2_X_NO_RPM)) {
- dev_err(dev, "%s: device not enabled\n", __func__);
- ret = -ENODEV;
- goto err_put_device;
+ if (!enabled) {
+ switch (tsens_version(priv)) {
+ case VER_1_X_NO_RPM:
+ case VER_2_X_NO_RPM:
+ break;
+ default:
+ dev_err(dev, "%s: device not enabled\n", __func__);
+ ret = -ENODEV;
+ goto err_put_device;
+ }
}
priv->rf[SENSOR_EN] = devm_regmap_field_alloc(dev, priv->srot_map,
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -34,6 +34,7 @@ enum tsens_ver {
VER_0 = 0,
VER_0_1,
VER_1_X,
+ VER_1_X_NO_RPM,
VER_2_X,
VER_2_X_NO_RPM,
};

View file

@ -1,64 +0,0 @@
From 04b31cc53fe0df0e87a37d18a3c0363d7dee218f Mon Sep 17 00:00:00 2001
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Date: Fri, 28 Feb 2025 09:11:38 +0400
Subject: [PATCH] thermal/drivers/qcom/tsens: Add support for IPQ5018 tsens
IPQ5018 has tsens IP V1.0, 5 sensors of which 4 are in use and 1
interrupt. The IP does not have a RPM, hence use init routine for
tsens v1.0 without RPM which does not early enable.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/DS7PR19MB8883BD0E36C08DD1D03CE1CB9DCC2@DS7PR19MB8883.namprd19.prod.outlook.com
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/thermal/qcom/tsens-v1.c | 14 ++++++++++++++
drivers/thermal/qcom/tsens.c | 3 +++
drivers/thermal/qcom/tsens.h | 3 +++
3 files changed, 20 insertions(+)
--- a/drivers/thermal/qcom/tsens-v1.c
+++ b/drivers/thermal/qcom/tsens-v1.c
@@ -242,3 +242,17 @@ struct tsens_plat_data data_8976 = {
.feat = &tsens_v1_feat,
.fields = tsens_v1_regfields,
};
+
+const struct tsens_ops ops_ipq5018 = {
+ .init = init_tsens_v1_no_rpm,
+ .calibrate = tsens_calibrate_common,
+ .get_temp = get_temp_tsens_valid,
+};
+
+const struct tsens_plat_data data_ipq5018 = {
+ .num_sensors = 5,
+ .ops = &ops_ipq5018,
+ .hw_ids = (unsigned int []){0, 1, 2, 3, 4},
+ .feat = &tsens_v1_no_rpm_feat,
+ .fields = tsens_v1_regfields,
+};
--- a/drivers/thermal/qcom/tsens.c
+++ b/drivers/thermal/qcom/tsens.c
@@ -1108,6 +1108,9 @@ static SIMPLE_DEV_PM_OPS(tsens_pm_ops, t
static const struct of_device_id tsens_table[] = {
{
+ .compatible = "qcom,ipq5018-tsens",
+ .data = &data_ipq5018,
+ }, {
.compatible = "qcom,ipq5332-tsens",
.data = &data_ipq5332,
}, {
--- a/drivers/thermal/qcom/tsens.h
+++ b/drivers/thermal/qcom/tsens.h
@@ -652,6 +652,9 @@ extern struct tsens_plat_data data_8226,
/* TSENS v1 targets */
extern struct tsens_plat_data data_tsens_v1, data_8937, data_8976, data_8956;
+/* TSENS v1 with no RPM targets */
+extern const struct tsens_plat_data data_ipq5018;
+
/* TSENS v2 targets */
extern struct tsens_plat_data data_8996, data_ipq8074, data_tsens_v2;
extern const struct tsens_plat_data data_ipq5332, data_ipq5424;

View file

@ -1,240 +0,0 @@
From 450a80623e3b8bb5dae59e0d56046fc3d0a88f3b Mon Sep 17 00:00:00 2001
From: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Date: Thu, 12 Jun 2025 10:46:14 +0400
Subject: arm64: dts: qcom: ipq5018: Add tsens node
IPQ5018 has tsens V1.0 IP with 5 sensors, though 4 are in use.
There is no RPM, so tsens has to be manually enabled. Adding the tsens
and nvmem nodes and adding 4 thermal sensors (zones). The critical trip
temperature is set to 120'C with an action to reboot.
In addition, adding a cooling device to the CPU thermal zone which uses
CPU frequency scaling.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Signed-off-by: Sricharan Ramabadhran <quic_srichara@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
[bjorn: Added tsens-v1 fallback compatible, per binding]
Link: https://lore.kernel.org/r/20250612-ipq5018-tsens-v13-2-a210f3683240@outlook.com
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 178 ++++++++++++++++++++++++++++++++++
1 file changed, 178 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
+#include <dt-bindings/thermal/thermal.h>
/ {
interrupt-parent = <&intc>;
@@ -39,6 +40,7 @@
next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
+ #cooling-cells = <2>;
};
cpu1: cpu@1 {
@@ -49,6 +51,7 @@
next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
operating-points-v2 = <&cpu_opp_table>;
+ #cooling-cells = <2>;
};
l2_0: l2-cache {
@@ -182,6 +185,117 @@
status = "disabled";
};
+ qfprom: qfprom@a0000 {
+ compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
+ reg = <0x000a0000 0x1000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ tsens_mode: mode@249 {
+ reg = <0x249 0x1>;
+ bits = <0 3>;
+ };
+
+ tsens_base1: base1@249 {
+ reg = <0x249 0x2>;
+ bits = <3 8>;
+ };
+
+ tsens_base2: base2@24a {
+ reg = <0x24a 0x2>;
+ bits = <3 8>;
+ };
+
+ tsens_s0_p1: s0-p1@24b {
+ reg = <0x24b 0x2>;
+ bits = <2 6>;
+ };
+
+ tsens_s0_p2: s0-p2@24c {
+ reg = <0x24c 0x1>;
+ bits = <1 6>;
+ };
+
+ tsens_s1_p1: s1-p1@24c {
+ reg = <0x24c 0x2>;
+ bits = <7 6>;
+ };
+
+ tsens_s1_p2: s1-p2@24d {
+ reg = <0x24d 0x2>;
+ bits = <5 6>;
+ };
+
+ tsens_s2_p1: s2-p1@24e {
+ reg = <0x24e 0x2>;
+ bits = <3 6>;
+ };
+
+ tsens_s2_p2: s2-p2@24f {
+ reg = <0x24f 0x1>;
+ bits = <1 6>;
+ };
+
+ tsens_s3_p1: s3-p1@24f {
+ reg = <0x24f 0x2>;
+ bits = <7 6>;
+ };
+
+ tsens_s3_p2: s3-p2@250 {
+ reg = <0x250 0x2>;
+ bits = <5 6>;
+ };
+
+ tsens_s4_p1: s4-p1@251 {
+ reg = <0x251 0x2>;
+ bits = <3 6>;
+ };
+
+ tsens_s4_p2: s4-p2@254 {
+ reg = <0x254 0x1>;
+ bits = <0 6>;
+ };
+ };
+
+ tsens: thermal-sensor@4a9000 {
+ compatible = "qcom,ipq5018-tsens", "qcom,tsens-v1";
+ reg = <0x004a9000 0x1000>,
+ <0x004a8000 0x1000>;
+
+ nvmem-cells = <&tsens_mode>,
+ <&tsens_base1>,
+ <&tsens_base2>,
+ <&tsens_s0_p1>,
+ <&tsens_s0_p2>,
+ <&tsens_s1_p1>,
+ <&tsens_s1_p2>,
+ <&tsens_s2_p1>,
+ <&tsens_s2_p2>,
+ <&tsens_s3_p1>,
+ <&tsens_s3_p2>,
+ <&tsens_s4_p1>,
+ <&tsens_s4_p2>;
+
+ nvmem-cell-names = "mode",
+ "base1",
+ "base2",
+ "s0_p1",
+ "s0_p2",
+ "s1_p1",
+ "s1_p2",
+ "s2_p1",
+ "s2_p2",
+ "s3_p1",
+ "s3_p2",
+ "s4_p1",
+ "s4_p2";
+
+ interrupts = <GIC_SPI 184 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "uplow";
+ #qcom,sensors = <5>;
+ #thermal-sensor-cells = <1>;
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq5018-tlmm";
reg = <0x01000000 0x300000>;
@@ -630,6 +744,70 @@
};
};
};
+
+ thermal-zones {
+ cpu-thermal {
+ thermal-sensors = <&tsens 2>;
+
+ trips {
+ cpu-critical {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+
+ cpu_alert: cpu-passive {
+ temperature = <100000>;
+ hysteresis = <1000>;
+ type = "passive";
+ };
+ };
+
+ cooling-maps {
+ map0 {
+ trip = <&cpu_alert>;
+ cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>,
+ <&cpu1 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>;
+ };
+ };
+ };
+
+ gephy-thermal {
+ thermal-sensors = <&tsens 4>;
+
+ trips {
+ gephy-critical {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ top-glue-thermal {
+ thermal-sensors = <&tsens 3>;
+
+ trips {
+ top-glue-critical {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+
+ ubi32-thermal {
+ thermal-sensors = <&tsens 1>;
+
+ trips {
+ ubi32-critical {
+ temperature = <120000>;
+ hysteresis = <1000>;
+ type = "critical";
+ };
+ };
+ };
+ };
timer {
compatible = "arm,armv8-timer";

View file

@ -1,33 +0,0 @@
From f6a4a55ae5d99f865e106916a9295548e381de47 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 30 Jun 2025 16:35:00 +0400
Subject: clk: qcom: gcc-ipq5018: fix GE PHY reset
The MISC reset is supposed to trigger a resets across the MDC, DSP, and
RX & TX clocks of the IPQ5018 internal GE PHY. So let's set the bitmask
of the reset definition accordingly in the GCC as per the downstream
driver.
Link: https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/00743c3e82fa87cba4460e7a2ba32f473a9ce932
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250630-ipq5018-ge-phy-v6-1-01be06378c15@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/gcc-ipq5018.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'drivers/clk/qcom/gcc-ipq5018.c')
--- a/drivers/clk/qcom/gcc-ipq5018.c
+++ b/drivers/clk/qcom/gcc-ipq5018.c
@@ -3661,7 +3661,7 @@ static const struct qcom_reset_map gcc_i
[GCC_WCSS_AXI_S_ARES] = { 0x59008, 6 },
[GCC_WCSS_Q6_BCR] = { 0x18004, 0 },
[GCC_WCSSAON_RESET] = { 0x59010, 0},
- [GCC_GEPHY_MISC_ARES] = { 0x56004, 0 },
+ [GCC_GEPHY_MISC_ARES] = { 0x56004, .bitmask = GENMASK(3, 0) },
};
static const struct of_device_id gcc_ipq5018_match_table[] = {

View file

@ -1,243 +0,0 @@
From d46502279a11b48ede1d8bf65a229c8231bf0602 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 13 Jun 2025 05:55:08 +0400
Subject: net: phy: qcom: at803x: Add Qualcomm IPQ5018 Internal PHY support
The IPQ5018 SoC contains a single internal Gigabit Ethernet PHY which
provides an MDI interface directly to an RJ45 connector or an external
switch over a PHY to PHY link.
The PHY supports 10BASE-T/100BASE-TX/1000BASE-T link modes in SGMII
interface mode, CDT, auto-negotiation and 802.3az EEE.
Let's add support for this PHY in the at803x driver as it falls within
the Qualcomm Atheros OUI.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://patch.msgid.link/20250613-ipq5018-ge-phy-v5-2-9af06e34ea6b@outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/qcom/at803x.c | 167 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 167 insertions(+)
(limited to 'drivers/net/phy/qcom/at803x.c')
--- a/drivers/net/phy/qcom/at803x.c
+++ b/drivers/net/phy/qcom/at803x.c
@@ -19,6 +19,7 @@
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/phylink.h>
+#include <linux/reset.h>
#include <linux/sfp.h>
#include <dt-bindings/net/qca-ar803x.h>
@@ -93,6 +94,8 @@
#define ATH8035_PHY_ID 0x004dd072
#define AT8030_PHY_ID_MASK 0xffffffef
+#define IPQ5018_PHY_ID 0x004dd0c0
+
#define QCA9561_PHY_ID 0x004dd042
#define AT803X_PAGE_FIBER 0
@@ -105,6 +108,48 @@
/* disable hibernation mode */
#define AT803X_DISABLE_HIBERNATION_MODE BIT(2)
+#define IPQ5018_PHY_FIFO_CONTROL 0x19
+#define IPQ5018_PHY_FIFO_RESET GENMASK(1, 0)
+
+#define IPQ5018_PHY_DEBUG_EDAC 0x4380
+#define IPQ5018_PHY_MMD1_MDAC 0x8100
+#define IPQ5018_PHY_DAC_MASK GENMASK(15, 8)
+
+/* MDAC and EDAC values for short cable length */
+#define IPQ5018_PHY_DEBUG_EDAC_VAL 0x10
+#define IPQ5018_PHY_MMD1_MDAC_VAL 0x10
+
+#define IPQ5018_PHY_MMD1_MSE_THRESH1 0x1000
+#define IPQ5018_PHY_MMD1_MSE_THRESH2 0x1001
+#define IPQ5018_PHY_PCS_EEE_TX_TIMER 0x8008
+#define IPQ5018_PHY_PCS_EEE_RX_TIMER 0x8009
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL3 0x8074
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL4 0x8075
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL5 0x8076
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL6 0x8077
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL7 0x8078
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL9 0x807a
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL13 0x807e
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL14 0x807f
+
+#define IPQ5018_PHY_MMD1_MSE_THRESH1_VAL 0xf1
+#define IPQ5018_PHY_MMD1_MSE_THRESH2_VAL 0x1f6
+#define IPQ5018_PHY_PCS_EEE_TX_TIMER_VAL 0x7880
+#define IPQ5018_PHY_PCS_EEE_RX_TIMER_VAL 0xc8
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL3_VAL 0xc040
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL4_VAL 0xa060
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL5_VAL 0xc040
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL6_VAL 0xa060
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL7_VAL 0xc24c
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL9_VAL 0xc060
+#define IPQ5018_PHY_PCS_CDT_THRESH_CTRL13_VAL 0xb060
+#define IPQ5018_PHY_PCS_NEAR_ECHO_THRESH_VAL 0x90b0
+
+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE 0x1
+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK GENMASK(7, 4)
+#define IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT 0x50
+#define IPQ5018_PHY_DEBUG_ANA_DAC_FILTER 0xa080
+
MODULE_DESCRIPTION("Qualcomm Atheros AR803x PHY driver");
MODULE_AUTHOR("Matus Ujhelyi");
MODULE_LICENSE("GPL");
@@ -130,6 +175,11 @@ struct at803x_context {
u16 led_control;
};
+struct ipq5018_priv {
+ struct reset_control *rst;
+ bool set_short_cable_dac;
+};
+
static int at803x_write_page(struct phy_device *phydev, int page)
{
int mask;
@@ -960,6 +1010,109 @@ static int at8035_probe(struct phy_devic
return at8035_parse_dt(phydev);
}
+static int ipq5018_cable_test_start(struct phy_device *phydev)
+{
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL3,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL3_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL4,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL4_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL5,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL5_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL6,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL6_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL7,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL7_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL9,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL9_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL13,
+ IPQ5018_PHY_PCS_CDT_THRESH_CTRL13_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_CDT_THRESH_CTRL3,
+ IPQ5018_PHY_PCS_NEAR_ECHO_THRESH_VAL);
+
+ /* we do all the (time consuming) work later */
+ return 0;
+}
+
+static int ipq5018_config_init(struct phy_device *phydev)
+{
+ struct ipq5018_priv *priv = phydev->priv;
+ u16 val;
+
+ /*
+ * set LDO efuse: first temporarily store ANA_DAC_FILTER value from
+ * debug register as it will be reset once the ANA_LDO_EFUSE register
+ * is written to
+ */
+ val = at803x_debug_reg_read(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER);
+ at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE,
+ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_MASK,
+ IPQ5018_PHY_DEBUG_ANA_LDO_EFUSE_DEFAULT);
+ at803x_debug_reg_write(phydev, IPQ5018_PHY_DEBUG_ANA_DAC_FILTER, val);
+
+ /* set 8023AZ EEE TX and RX timer values */
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_EEE_TX_TIMER,
+ IPQ5018_PHY_PCS_EEE_TX_TIMER_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PCS, IPQ5018_PHY_PCS_EEE_RX_TIMER,
+ IPQ5018_PHY_PCS_EEE_RX_TIMER_VAL);
+
+ /* set MSE threshold values */
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH1,
+ IPQ5018_PHY_MMD1_MSE_THRESH1_VAL);
+ phy_write_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MSE_THRESH2,
+ IPQ5018_PHY_MMD1_MSE_THRESH2_VAL);
+
+ /* PHY DAC values are optional and only set in a PHY to PHY link architecture */
+ if (priv->set_short_cable_dac) {
+ /* setting MDAC (Multi-level Digital-to-Analog Converter) in MMD1 */
+ phy_modify_mmd(phydev, MDIO_MMD_PMAPMD, IPQ5018_PHY_MMD1_MDAC,
+ IPQ5018_PHY_DAC_MASK, IPQ5018_PHY_MMD1_MDAC_VAL);
+
+ /* setting EDAC (Error-detection and Correction) in debug register */
+ at803x_debug_reg_mask(phydev, IPQ5018_PHY_DEBUG_EDAC,
+ IPQ5018_PHY_DAC_MASK, IPQ5018_PHY_DEBUG_EDAC_VAL);
+ }
+
+ return 0;
+}
+
+static void ipq5018_link_change_notify(struct phy_device *phydev)
+{
+ /*
+ * Reset the FIFO buffer upon link disconnects to clear any residual data
+ * which may cause issues with the FIFO which it cannot recover from.
+ */
+ mdiobus_modify_changed(phydev->mdio.bus, phydev->mdio.addr,
+ IPQ5018_PHY_FIFO_CONTROL, IPQ5018_PHY_FIFO_RESET,
+ phydev->link ? IPQ5018_PHY_FIFO_RESET : 0);
+}
+
+static int ipq5018_probe(struct phy_device *phydev)
+{
+ struct device *dev = &phydev->mdio.dev;
+ struct ipq5018_priv *priv;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->set_short_cable_dac = of_property_read_bool(dev->of_node,
+ "qcom,dac-preset-short-cable");
+
+ priv->rst = devm_reset_control_array_get_exclusive(dev);
+ if (IS_ERR(priv->rst))
+ return dev_err_probe(dev, PTR_ERR(priv->rst),
+ "failed to acquire reset\n");
+
+ ret = reset_control_reset(priv->rst);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to reset\n");
+
+ phydev->priv = priv;
+
+ return 0;
+}
+
static struct phy_driver at803x_driver[] = {
{
/* Qualcomm Atheros AR8035 */
@@ -1052,6 +1205,19 @@ static struct phy_driver at803x_driver[]
.soft_reset = genphy_soft_reset,
.config_aneg = at803x_config_aneg,
}, {
+ PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID),
+ .name = "Qualcomm Atheros IPQ5018 internal PHY",
+ .flags = PHY_IS_INTERNAL | PHY_POLL_CABLE_TEST,
+ .probe = ipq5018_probe,
+ .config_init = ipq5018_config_init,
+ .link_change_notify = ipq5018_link_change_notify,
+ .read_status = at803x_read_status,
+ .config_intr = at803x_config_intr,
+ .handle_interrupt = at803x_handle_interrupt,
+ .cable_test_start = ipq5018_cable_test_start,
+ .cable_test_get_status = qca808x_cable_test_get_status,
+ .soft_reset = genphy_soft_reset,
+}, {
/* Qualcomm Atheros QCA9561 */
PHY_ID_MATCH_EXACT(QCA9561_PHY_ID),
.name = "Qualcomm Atheros QCA9561 built-in PHY",
@@ -1077,6 +1243,7 @@ static const struct mdio_device_id __may
{ PHY_ID_MATCH_EXACT(ATH8032_PHY_ID) },
{ PHY_ID_MATCH_EXACT(ATH8035_PHY_ID) },
{ PHY_ID_MATCH_EXACT(ATH9331_PHY_ID) },
+ { PHY_ID_MATCH_EXACT(IPQ5018_PHY_ID) },
{ PHY_ID_MATCH_EXACT(QCA9561_PHY_ID) },
{ }
};

View file

@ -1,55 +0,0 @@
From 1e2261a669a9596ba435c6fe524e026bac0f0e2f Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 30 Jun 2025 16:35:01 +0400
Subject: arm64: dts: qcom: ipq5018: Add MDIO buses
IPQ5018 contains two mdio buses of which one bus is used to control the
SoC's internal GE PHY, while the other bus is connected to external PHYs
or switches.
There's already support for IPQ5018 in the mdio-ipq4019 driver, so let's
simply add the mdio nodes for them.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250630-ipq5018-ge-phy-v6-2-01be06378c15@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -185,6 +185,30 @@
status = "disabled";
};
+ mdio0: mdio@88000 {
+ compatible = "qcom,ipq5018-mdio";
+ reg = <0x00088000 0x64>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&gcc GCC_MDIO0_AHB_CLK>;
+ clock-names = "gcc_mdio_ahb_clk";
+
+ status = "disabled";
+ };
+
+ mdio1: mdio@90000 {
+ compatible = "qcom,ipq5018-mdio";
+ reg = <0x00090000 0x64>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&gcc GCC_MDIO1_AHB_CLK>;
+ clock-names = "gcc_mdio_ahb_clk";
+
+ status = "disabled";
+ };
+
qfprom: qfprom@a0000 {
compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
reg = <0x000a0000 0x1000>;

View file

@ -1,82 +0,0 @@
From f5f2b835e316df29b89e28ed7e467df473932e8d Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 30 Jun 2025 16:35:02 +0400
Subject: arm64: dts: qcom: ipq5018: Add GE PHY to internal mdio bus
The IPQ5018 SoC contains an internal GE PHY, always at phy address 7.
As such, let's add the GE PHY node to the SoC dtsi.
The LDO controller found in the SoC must be enabled to provide constant
low voltages to the PHY. The mdio-ipq4019 driver already has support
for this, so adding the appropriate TCSR register offset.
In addition, the GE PHY outputs both the RX and TX clocks to the GCC
which gate controls them and routes them back to the PHY itself.
So let's create two DT fixed clocks and register them in the GCC node.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250630-ipq5018-ge-phy-v6-3-01be06378c15@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 26 +++++++++++++++++++++++---
1 file changed, 23 insertions(+), 3 deletions(-)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -17,6 +17,18 @@
#size-cells = <2>;
clocks {
+ gephy_rx_clk: gephy-rx-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ #clock-cells = <0>;
+ };
+
+ gephy_tx_clk: gephy-tx-clk {
+ compatible = "fixed-clock";
+ clock-frequency = <125000000>;
+ #clock-cells = <0>;
+ };
+
sleep_clk: sleep-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -187,7 +199,8 @@
mdio0: mdio@88000 {
compatible = "qcom,ipq5018-mdio";
- reg = <0x00088000 0x64>;
+ reg = <0x00088000 0x64>,
+ <0x019475c4 0x4>;
#address-cells = <1>;
#size-cells = <0>;
@@ -195,6 +208,13 @@
clock-names = "gcc_mdio_ahb_clk";
status = "disabled";
+
+ ge_phy: ethernet-phy@7 {
+ compatible = "ethernet-phy-id004d.d0c0";
+ reg = <7>;
+
+ resets = <&gcc GCC_GEPHY_MISC_ARES>;
+ };
};
mdio1: mdio@90000 {
@@ -346,8 +366,8 @@
<&pcie0_phy>,
<&pcie1_phy>,
<0>,
- <0>,
- <0>,
+ <&gephy_rx_clk>,
+ <&gephy_tx_clk>,
<0>,
<0>;
#clock-cells = <1>;

View file

@ -1,64 +0,0 @@
From 8d2a8e8dc448f218b36b3b9f3790c9c0dfaa2b74 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Thu, 1 May 2025 13:20:52 +0400
Subject: arm64: dts: qcom: ipq5018: Add SPI nand support
Add QPIC SPI NAND support for IPQ5018 SoC.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250501-ipq5018-spi-qpic-snand-v1-2-31e01fbb606f@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 38 +++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -436,6 +436,44 @@
status = "disabled";
};
+ qpic_bam: dma-controller@7984000 {
+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
+ reg = <0x07984000 0x1c000>;
+
+ interrupts = <GIC_SPI 146 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_QPIC_AHB_CLK>;
+ clock-names = "bam_clk";
+
+ #dma-cells = <1>;
+ qcom,ee = <0>;
+
+ status = "disabled";
+ };
+
+ qpic_nand: spi@79b0000 {
+ compatible = "qcom,ipq5018-snand", "qcom,ipq9574-snand";
+ reg = <0x079b0000 0x10000>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ clocks = <&gcc GCC_QPIC_CLK>,
+ <&gcc GCC_QPIC_AHB_CLK>,
+ <&gcc GCC_QPIC_IO_MACRO_CLK>;
+ clock-names = "core",
+ "aon",
+ "iom";
+
+ dmas = <&qpic_bam 0>,
+ <&qpic_bam 1>,
+ <&qpic_bam 2>;
+ dma-names = "tx",
+ "rx",
+ "cmd";
+
+ status = "disabled";
+ };
+
usb: usb@8af8800 {
compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
reg = <0x08af8800 0x400>;

View file

@ -1,34 +0,0 @@
From bf258fdaa2bcbafa04bf1ad646e8ed42e13033cb Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 21 Jul 2025 10:30:46 +0400
Subject: arm64: dts: qcom: ipq5018: add PRNG node
PRNG inside of IPQ5018 is already supported, so let's add the node for it.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250721-ipq5018-prng-v1-1-474310e0575d@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 8 ++++++++
1 file changed, 8 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -301,6 +301,14 @@
};
};
+ prng: rng@e3000 {
+ compatible = "qcom,prng-ee";
+ reg = <0x000e3000 0x1000>;
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "core";
+ status = "disabled";
+ };
+
tsens: thermal-sensor@4a9000 {
compatible = "qcom,ipq5018-tsens", "qcom,tsens-v1";
reg = <0x004a9000 0x1000>,

View file

@ -1,58 +0,0 @@
From ed5789ba7c2ce548f01ebbdbd7488dd9cccc4513 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 21 Jul 2025 10:23:15 +0400
Subject: arm64: dts: qcom: ipq5018: Add crypto nodes
IPQ5018 uses Qualcomm QCE crypto engine v5.1 which is already supported.
So let's add the dts nodes for its DMA v1.7.4 and QCE itself.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250721-ipq5018-crypto-v3-1-b9cd9b0ef147@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 30 ++++++++++++++++++++++++++++++
1 file changed, 30 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -348,6 +348,36 @@
#thermal-sensor-cells = <1>;
};
+ cryptobam: dma-controller@704000 {
+ compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
+ reg = <0x00704000 0x20000>;
+ interrupts = <GIC_SPI 207 IRQ_TYPE_LEVEL_HIGH>;
+
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>;
+ clock-names = "bam_clk";
+
+ #dma-cells = <1>;
+ qcom,ee = <1>;
+ qcom,controlled-remotely;
+ };
+
+ crypto: crypto@73a000 {
+ compatible = "qcom,crypto-v5.1";
+ reg = <0x0073a000 0x6000>;
+
+ clocks = <&gcc GCC_CRYPTO_AHB_CLK>,
+ <&gcc GCC_CRYPTO_AXI_CLK>,
+ <&gcc GCC_CRYPTO_CLK>;
+ clock-names = "iface",
+ "bus",
+ "core";
+
+ dmas = <&cryptobam 2>,
+ <&cryptobam 3>;
+ dma-names = "rx",
+ "tx";
+ };
+
tlmm: pinctrl@1000000 {
compatible = "qcom,ipq5018-tlmm";
reg = <0x01000000 0x300000>;

View file

@ -1,132 +0,0 @@
From c0f1cbf795095c21b92a46fa1dc47a7b787ce538 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Fri, 3 Jan 2025 15:31:34 +0800
Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL clock controller for
IPQ SoC
The CMN PLL controller provides clocks to networking hardware blocks
and to GCC on Qualcomm IPQ9574 SoC. It receives input clock from the
on-chip Wi-Fi, and produces output clocks at fixed rates. These output
rates are predetermined, and are unrelated to the input clock rate.
The primary purpose of CMN PLL is to supply clocks to the networking
hardware such as PPE (packet process engine), PCS and the externally
connected switch or PHY device. The CMN PLL block also outputs fixed
rate clocks to GCC, such as 24 MHZ as XO clock and 32 KHZ as sleep
clock supplied to GCC.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-1-c89fb4d4849d@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
.../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 77 +++++++++++++++++++
include/dt-bindings/clock/qcom,ipq-cmn-pll.h | 22 ++++++
2 files changed, 99 insertions(+)
create mode 100644 Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
create mode 100644 include/dt-bindings/clock/qcom,ipq-cmn-pll.h
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
@@ -0,0 +1,77 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/clock/qcom,ipq9574-cmn-pll.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm CMN PLL Clock Controller on IPQ SoC
+
+maintainers:
+ - Bjorn Andersson <andersson@kernel.org>
+ - Luo Jie <quic_luoj@quicinc.com>
+
+description:
+ The CMN (or common) PLL clock controller expects a reference
+ input clock. This reference clock is from the on-board Wi-Fi.
+ The CMN PLL supplies a number of fixed rate output clocks to
+ the devices providing networking functions and to GCC. These
+ networking hardware include PPE (packet process engine), PCS
+ and the externally connected switch or PHY devices. The CMN
+ PLL block also outputs fixed rate clocks to GCC. The PLL's
+ primary function is to enable fixed rate output clocks for
+ networking hardware functions used with the IPQ SoC.
+
+properties:
+ compatible:
+ enum:
+ - qcom,ipq9574-cmn-pll
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: The reference clock. The supported clock rates include
+ 25000000, 31250000, 40000000, 48000000, 50000000 and 96000000 HZ.
+ - description: The AHB clock
+ - description: The SYS clock
+ description:
+ The reference clock is the source clock of CMN PLL, which is from the
+ Wi-Fi. The AHB and SYS clocks must be enabled to access CMN PLL
+ clock registers.
+
+ clock-names:
+ items:
+ - const: ref
+ - const: ahb
+ - const: sys
+
+ "#clock-cells":
+ const: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - "#clock-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
+ #include <dt-bindings/clock/qcom,ipq9574-gcc.h>
+
+ cmn_pll: clock-controller@9b000 {
+ compatible = "qcom,ipq9574-cmn-pll";
+ reg = <0x0009b000 0x800>;
+ clocks = <&cmn_pll_ref_clk>,
+ <&gcc GCC_CMN_12GPLL_AHB_CLK>,
+ <&gcc GCC_CMN_12GPLL_SYS_CLK>;
+ clock-names = "ref", "ahb", "sys";
+ #clock-cells = <1>;
+ assigned-clocks = <&cmn_pll CMN_PLL_CLK>;
+ assigned-clock-rates-u64 = /bits/ 64 <12000000000>;
+ };
+...
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,ipq-cmn-pll.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H
+#define _DT_BINDINGS_CLK_QCOM_IPQ_CMN_PLL_H
+
+/* CMN PLL core clock. */
+#define CMN_PLL_CLK 0
+
+/* The output clocks from CMN PLL of IPQ9574. */
+#define XO_24MHZ_CLK 1
+#define SLEEP_32KHZ_CLK 2
+#define PCS_31P25MHZ_CLK 3
+#define NSS_1200MHZ_CLK 4
+#define PPE_353MHZ_CLK 5
+#define ETH0_50MHZ_CLK 6
+#define ETH1_50MHZ_CLK 7
+#define ETH2_50MHZ_CLK 8
+#define ETH_25MHZ_CLK 9
+#endif

View file

@ -1,500 +0,0 @@
From f81715a4c87c3b75ca2640bb61b6c66506061a64 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Fri, 3 Jan 2025 15:31:35 +0800
Subject: [PATCH] clk: qcom: Add CMN PLL clock controller driver for IPQ SoC
The CMN PLL clock controller supplies clocks to the hardware
blocks that together make up the Ethernet function on Qualcomm
IPQ SoCs and to GCC. The driver is initially supported for
IPQ9574 SoC.
The CMN PLL clock controller expects a reference input clock
from the on-board Wi-Fi block acting as clock source. The input
reference clock needs to be configured to one of the supported
clock rates.
The controller supplies a number of fixed-rate output clocks.
For the IPQ9574, there is one output clock of 353 MHZ to PPE
(Packet Process Engine) hardware block, three 50 MHZ output
clocks and an additional 25 MHZ output clock supplied to the
connected Ethernet devices. The PLL also supplies a 24 MHZ
clock as XO and a 32 KHZ sleep clock to GCC, and one 31.25
MHZ clock to PCS.
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Acked-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20250103-qcom_ipq_cmnpll-v8-2-c89fb4d4849d@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/Kconfig | 9 +
drivers/clk/qcom/Makefile | 1 +
drivers/clk/qcom/ipq-cmn-pll.c | 435 +++++++++++++++++++++++++++++++++
3 files changed, 445 insertions(+)
create mode 100644 drivers/clk/qcom/ipq-cmn-pll.c
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -190,6 +190,15 @@ config IPQ_APSS_6018
Say Y if you want to support CPU frequency scaling on
ipq based devices.
+config IPQ_CMN_PLL
+ tristate "IPQ CMN PLL Clock Controller"
+ help
+ Support for CMN PLL clock controller on IPQ platform. The
+ CMN PLL consumes the AHB/SYS clocks from GCC and supplies
+ the output clocks to the networking hardware and GCC blocks.
+ Say Y or M if you want to support CMN PLL clock on the IPQ
+ based devices.
+
config IPQ_GCC_4019
tristate "IPQ4019 Global Clock Controller"
help
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_CLK_X1E80100_TCSRCC) += tcs
obj-$(CONFIG_CLK_QCM2290_GPUCC) += gpucc-qcm2290.o
obj-$(CONFIG_IPQ_APSS_PLL) += apss-ipq-pll.o
obj-$(CONFIG_IPQ_APSS_6018) += apss-ipq6018.o
+obj-$(CONFIG_IPQ_CMN_PLL) += ipq-cmn-pll.o
obj-$(CONFIG_IPQ_GCC_4019) += gcc-ipq4019.o
obj-$(CONFIG_IPQ_GCC_5018) += gcc-ipq5018.o
obj-$(CONFIG_IPQ_GCC_5332) += gcc-ipq5332.o
--- /dev/null
+++ b/drivers/clk/qcom/ipq-cmn-pll.c
@@ -0,0 +1,435 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+/*
+ * CMN PLL block expects the reference clock from on-board Wi-Fi block,
+ * and supplies fixed rate clocks as output to the networking hardware
+ * blocks and to GCC. The networking related blocks include PPE (packet
+ * process engine), the externally connected PHY or switch devices, and
+ * the PCS.
+ *
+ * On the IPQ9574 SoC, there are three clocks with 50 MHZ and one clock
+ * with 25 MHZ which are output from the CMN PLL to Ethernet PHY (or switch),
+ * and one clock with 353 MHZ to PPE. The other fixed rate output clocks
+ * are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS
+ * with 31.25 MHZ.
+ *
+ * +---------+
+ * | GCC |
+ * +--+---+--+
+ * AHB CLK| |SYS CLK
+ * V V
+ * +-------+---+------+
+ * | +-------------> eth0-50mhz
+ * REF CLK | IPQ9574 |
+ * -------->+ +-------------> eth1-50mhz
+ * | CMN PLL block |
+ * | +-------------> eth2-50mhz
+ * | |
+ * +----+----+----+---+-------------> eth-25mhz
+ * | | |
+ * V V V
+ * GCC PCS NSS/PPE
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm_clock.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
+
+#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
+#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8)
+
+#define CMN_PLL_LOCKED 0x64
+#define CMN_PLL_CLKS_LOCKED BIT(8)
+
+#define CMN_PLL_POWER_ON_AND_RESET 0x780
+#define CMN_ANA_EN_SW_RSTN BIT(6)
+
+#define CMN_PLL_REFCLK_CONFIG 0x784
+#define CMN_PLL_REFCLK_EXTERNAL BIT(9)
+#define CMN_PLL_REFCLK_DIV GENMASK(8, 4)
+#define CMN_PLL_REFCLK_INDEX GENMASK(3, 0)
+
+#define CMN_PLL_CTRL 0x78c
+#define CMN_PLL_CTRL_LOCK_DETECT_EN BIT(15)
+
+#define CMN_PLL_DIVIDER_CTRL 0x794
+#define CMN_PLL_DIVIDER_CTRL_FACTOR GENMASK(9, 0)
+
+/**
+ * struct cmn_pll_fixed_output_clk - CMN PLL output clocks information
+ * @id: Clock specifier to be supplied
+ * @name: Clock name to be registered
+ * @rate: Clock rate
+ */
+struct cmn_pll_fixed_output_clk {
+ unsigned int id;
+ const char *name;
+ unsigned long rate;
+};
+
+/**
+ * struct clk_cmn_pll - CMN PLL hardware specific data
+ * @regmap: hardware regmap.
+ * @hw: handle between common and hardware-specific interfaces
+ */
+struct clk_cmn_pll {
+ struct regmap *regmap;
+ struct clk_hw hw;
+};
+
+#define CLK_PLL_OUTPUT(_id, _name, _rate) { \
+ .id = _id, \
+ .name = _name, \
+ .rate = _rate, \
+}
+
+#define to_clk_cmn_pll(_hw) container_of(_hw, struct clk_cmn_pll, hw)
+
+static const struct regmap_config ipq_cmn_pll_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = 0x7fc,
+ .fast_io = true,
+};
+
+static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = {
+ CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
+ CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
+ CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL),
+ CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL),
+ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL),
+ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
+};
+
+/*
+ * CMN PLL has the single parent clock, which supports the several
+ * possible parent clock rates, each parent clock rate is reflected
+ * by the specific reference index value in the hardware.
+ */
+static int ipq_cmn_pll_find_freq_index(unsigned long parent_rate)
+{
+ int index = -EINVAL;
+
+ switch (parent_rate) {
+ case 25000000:
+ index = 3;
+ break;
+ case 31250000:
+ index = 4;
+ break;
+ case 40000000:
+ index = 6;
+ break;
+ case 48000000:
+ case 96000000:
+ /*
+ * Parent clock rate 48 MHZ and 96 MHZ take the same value
+ * of reference clock index. 96 MHZ needs the source clock
+ * divider to be programmed as 2.
+ */
+ index = 7;
+ break;
+ case 50000000:
+ index = 8;
+ break;
+ default:
+ break;
+ }
+
+ return index;
+}
+
+static unsigned long clk_cmn_pll_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw);
+ u32 val, factor;
+
+ /*
+ * The value of CMN_PLL_DIVIDER_CTRL_FACTOR is automatically adjusted
+ * by HW according to the parent clock rate.
+ */
+ regmap_read(cmn_pll->regmap, CMN_PLL_DIVIDER_CTRL, &val);
+ factor = FIELD_GET(CMN_PLL_DIVIDER_CTRL_FACTOR, val);
+
+ return parent_rate * 2 * factor;
+}
+
+static int clk_cmn_pll_determine_rate(struct clk_hw *hw,
+ struct clk_rate_request *req)
+{
+ int ret;
+
+ /* Validate the rate of the single parent clock. */
+ ret = ipq_cmn_pll_find_freq_index(req->best_parent_rate);
+
+ return ret < 0 ? ret : 0;
+}
+
+/*
+ * This function is used to initialize the CMN PLL to enable the fixed
+ * rate output clocks. It is expected to be configured once.
+ */
+static int clk_cmn_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw);
+ int ret, index;
+ u32 val;
+
+ /*
+ * Configure the reference input clock selection as per the given
+ * parent clock. The output clock rates are always of fixed value.
+ */
+ index = ipq_cmn_pll_find_freq_index(parent_rate);
+ if (index < 0)
+ return index;
+
+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG,
+ CMN_PLL_REFCLK_INDEX,
+ FIELD_PREP(CMN_PLL_REFCLK_INDEX, index));
+ if (ret)
+ return ret;
+
+ /*
+ * Update the source clock rate selection and source clock
+ * divider as 2 when the parent clock rate is 96 MHZ.
+ */
+ if (parent_rate == 96000000) {
+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG,
+ CMN_PLL_REFCLK_DIV,
+ FIELD_PREP(CMN_PLL_REFCLK_DIV, 2));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(cmn_pll->regmap, CMN_PLL_REFCLK_SRC_SELECTION,
+ CMN_PLL_REFCLK_SRC_DIV,
+ FIELD_PREP(CMN_PLL_REFCLK_SRC_DIV, 0));
+ if (ret)
+ return ret;
+ }
+
+ /* Enable PLL locked detect. */
+ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_CTRL,
+ CMN_PLL_CTRL_LOCK_DETECT_EN);
+ if (ret)
+ return ret;
+
+ /*
+ * Reset the CMN PLL block to ensure the updated configurations
+ * take effect.
+ */
+ ret = regmap_clear_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET,
+ CMN_ANA_EN_SW_RSTN);
+ if (ret)
+ return ret;
+
+ usleep_range(1000, 1200);
+ ret = regmap_set_bits(cmn_pll->regmap, CMN_PLL_POWER_ON_AND_RESET,
+ CMN_ANA_EN_SW_RSTN);
+ if (ret)
+ return ret;
+
+ /* Stability check of CMN PLL output clocks. */
+ return regmap_read_poll_timeout(cmn_pll->regmap, CMN_PLL_LOCKED, val,
+ (val & CMN_PLL_CLKS_LOCKED),
+ 100, 100 * USEC_PER_MSEC);
+}
+
+static const struct clk_ops clk_cmn_pll_ops = {
+ .recalc_rate = clk_cmn_pll_recalc_rate,
+ .determine_rate = clk_cmn_pll_determine_rate,
+ .set_rate = clk_cmn_pll_set_rate,
+};
+
+static struct clk_hw *ipq_cmn_pll_clk_hw_register(struct platform_device *pdev)
+{
+ struct clk_parent_data pdata = { .index = 0 };
+ struct device *dev = &pdev->dev;
+ struct clk_init_data init = {};
+ struct clk_cmn_pll *cmn_pll;
+ struct regmap *regmap;
+ void __iomem *base;
+ int ret;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return ERR_CAST(base);
+
+ regmap = devm_regmap_init_mmio(dev, base, &ipq_cmn_pll_regmap_config);
+ if (IS_ERR(regmap))
+ return ERR_CAST(regmap);
+
+ cmn_pll = devm_kzalloc(dev, sizeof(*cmn_pll), GFP_KERNEL);
+ if (!cmn_pll)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = "cmn_pll";
+ init.parent_data = &pdata;
+ init.num_parents = 1;
+ init.ops = &clk_cmn_pll_ops;
+
+ cmn_pll->hw.init = &init;
+ cmn_pll->regmap = regmap;
+
+ ret = devm_clk_hw_register(dev, &cmn_pll->hw);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &cmn_pll->hw;
+}
+
+static int ipq_cmn_pll_register_clks(struct platform_device *pdev)
+{
+ const struct cmn_pll_fixed_output_clk *fixed_clk;
+ struct clk_hw_onecell_data *hw_data;
+ struct device *dev = &pdev->dev;
+ struct clk_hw *cmn_pll_hw;
+ unsigned int num_clks;
+ struct clk_hw *hw;
+ int ret, i;
+
+ fixed_clk = ipq9574_output_clks;
+ num_clks = ARRAY_SIZE(ipq9574_output_clks);
+
+ hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1),
+ GFP_KERNEL);
+ if (!hw_data)
+ return -ENOMEM;
+
+ /*
+ * Register the CMN PLL clock, which is the parent clock of
+ * the fixed rate output clocks.
+ */
+ cmn_pll_hw = ipq_cmn_pll_clk_hw_register(pdev);
+ if (IS_ERR(cmn_pll_hw))
+ return PTR_ERR(cmn_pll_hw);
+
+ /* Register the fixed rate output clocks. */
+ for (i = 0; i < num_clks; i++) {
+ hw = clk_hw_register_fixed_rate_parent_hw(dev, fixed_clk[i].name,
+ cmn_pll_hw, 0,
+ fixed_clk[i].rate);
+ if (IS_ERR(hw)) {
+ ret = PTR_ERR(hw);
+ goto unregister_fixed_clk;
+ }
+
+ hw_data->hws[fixed_clk[i].id] = hw;
+ }
+
+ /*
+ * Provide the CMN PLL clock. The clock rate of CMN PLL
+ * is configured to 12 GHZ by DT property assigned-clock-rates-u64.
+ */
+ hw_data->hws[CMN_PLL_CLK] = cmn_pll_hw;
+ hw_data->num = num_clks + 1;
+
+ ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, hw_data);
+ if (ret)
+ goto unregister_fixed_clk;
+
+ platform_set_drvdata(pdev, hw_data);
+
+ return 0;
+
+unregister_fixed_clk:
+ while (i > 0)
+ clk_hw_unregister(hw_data->hws[fixed_clk[--i].id]);
+
+ return ret;
+}
+
+static int ipq_cmn_pll_clk_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ int ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ ret = devm_pm_clk_create(dev);
+ if (ret)
+ return ret;
+
+ /*
+ * To access the CMN PLL registers, the GCC AHB & SYS clocks
+ * of CMN PLL block need to be enabled.
+ */
+ ret = pm_clk_add(dev, "ahb");
+ if (ret)
+ return dev_err_probe(dev, ret, "Fail to add AHB clock\n");
+
+ ret = pm_clk_add(dev, "sys");
+ if (ret)
+ return dev_err_probe(dev, ret, "Fail to add SYS clock\n");
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ /* Register CMN PLL clock and fixed rate output clocks. */
+ ret = ipq_cmn_pll_register_clks(pdev);
+ pm_runtime_put(dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Fail to register CMN PLL clocks\n");
+
+ return 0;
+}
+
+static void ipq_cmn_pll_clk_remove(struct platform_device *pdev)
+{
+ struct clk_hw_onecell_data *hw_data = platform_get_drvdata(pdev);
+ int i;
+
+ /*
+ * The clock with index CMN_PLL_CLK is unregistered by
+ * device management.
+ */
+ for (i = 0; i < hw_data->num; i++) {
+ if (i != CMN_PLL_CLK)
+ clk_hw_unregister(hw_data->hws[i]);
+ }
+}
+
+static const struct dev_pm_ops ipq_cmn_pll_pm_ops = {
+ SET_RUNTIME_PM_OPS(pm_clk_suspend, pm_clk_resume, NULL)
+};
+
+static const struct of_device_id ipq_cmn_pll_clk_ids[] = {
+ { .compatible = "qcom,ipq9574-cmn-pll", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids);
+
+static struct platform_driver ipq_cmn_pll_clk_driver = {
+ .probe = ipq_cmn_pll_clk_probe,
+ .remove = ipq_cmn_pll_clk_remove,
+ .driver = {
+ .name = "ipq_cmn_pll",
+ .of_match_table = ipq_cmn_pll_clk_ids,
+ .pm = &ipq_cmn_pll_pm_ops,
+ },
+};
+module_platform_driver(ipq_cmn_pll_clk_driver);
+
+MODULE_DESCRIPTION("Qualcomm Technologies, Inc. IPQ CMN PLL Driver");
+MODULE_LICENSE("GPL");

View file

@ -1,57 +0,0 @@
From 0c25ae62f5dc6a438b563536b5fe7fb6da3612b8 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Tue, 10 Jun 2025 18:35:18 +0800
Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL support for IPQ5424 SoC
The CMN PLL block in the IPQ5424 SoC takes 48 MHZ as the reference
input clock. The output clocks are the same as IPQ9574 SoC, except
for the clock rate of output clocks to PPE and NSS.
Also, add the new header file to export the CMN PLL output clock
specifiers for IPQ5424 SoC.
Acked-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Link: https://lore.kernel.org/r/20250610-qcom_ipq5424_cmnpll-v3-1-ceada8165645@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
.../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 1 +
.../dt-bindings/clock/qcom,ipq5424-cmn-pll.h | 22 +++++++++++++++++++
2 files changed, 23 insertions(+)
create mode 100644 include/dt-bindings/clock/qcom,ipq5424-cmn-pll.h
--- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
@@ -24,6 +24,7 @@ description:
properties:
compatible:
enum:
+ - qcom,ipq5424-cmn-pll
- qcom,ipq9574-cmn-pll
reg:
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,ipq5424-cmn-pll.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ5424_CMN_PLL_H
+#define _DT_BINDINGS_CLK_QCOM_IPQ5424_CMN_PLL_H
+
+/* CMN PLL core clock. */
+#define IPQ5424_CMN_PLL_CLK 0
+
+/* The output clocks from CMN PLL of IPQ5424. */
+#define IPQ5424_XO_24MHZ_CLK 1
+#define IPQ5424_SLEEP_32KHZ_CLK 2
+#define IPQ5424_PCS_31P25MHZ_CLK 3
+#define IPQ5424_NSS_300MHZ_CLK 4
+#define IPQ5424_PPE_375MHZ_CLK 5
+#define IPQ5424_ETH0_50MHZ_CLK 6
+#define IPQ5424_ETH1_50MHZ_CLK 7
+#define IPQ5424_ETH2_50MHZ_CLK 8
+#define IPQ5424_ETH_25MHZ_CLK 9
+#endif

View file

@ -1,104 +0,0 @@
From a2afa4c33f0a7f7f70d54a1bc5110e326753f982 Mon Sep 17 00:00:00 2001
From: Luo Jie <quic_luoj@quicinc.com>
Date: Tue, 10 Jun 2025 18:35:19 +0800
Subject: clk: qcom: cmnpll: Add IPQ5424 SoC support
The CMN PLL in IPQ5424 SoC supplies the fixed clock to NSS at 300 MHZ
and to PPE at 375 MHZ. Other output clocks from CMN PLL on this SoC,
and their rates are same as IPQ9574.
Acked-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Luo Jie <quic_luoj@quicinc.com>
Link: https://lore.kernel.org/r/20250610-qcom_ipq5424_cmnpll-v3-2-ceada8165645@quicinc.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/ipq-cmn-pll.c | 35 ++++++++++++++++++++++++++++++-----
1 file changed, 30 insertions(+), 5 deletions(-)
(limited to 'drivers/clk/qcom/ipq-cmn-pll.c')
--- a/drivers/clk/qcom/ipq-cmn-pll.c
+++ b/drivers/clk/qcom/ipq-cmn-pll.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
*/
/*
@@ -16,6 +16,10 @@
* are supplied to GCC (24 MHZ as XO and 32 KHZ as sleep clock), and to PCS
* with 31.25 MHZ.
*
+ * On the IPQ5424 SoC, there is an output clock from CMN PLL to PPE at 375 MHZ,
+ * and an output clock to NSS (network subsystem) at 300 MHZ. The other output
+ * clocks from CMN PLL on IPQ5424 are the same as IPQ9574.
+ *
* +---------+
* | GCC |
* +--+---+--+
@@ -46,6 +50,7 @@
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
+#include <dt-bindings/clock/qcom,ipq5424-cmn-pll.h>
#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8)
@@ -115,6 +120,20 @@ static const struct cmn_pll_fixed_output
CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
+ { /* Sentinel */ }
+};
+
+static const struct cmn_pll_fixed_output_clk ipq5424_output_clks[] = {
+ CLK_PLL_OUTPUT(IPQ5424_XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
+ CLK_PLL_OUTPUT(IPQ5424_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
+ CLK_PLL_OUTPUT(IPQ5424_PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL),
+ CLK_PLL_OUTPUT(IPQ5424_NSS_300MHZ_CLK, "nss-300mhz", 300000000UL),
+ CLK_PLL_OUTPUT(IPQ5424_PPE_375MHZ_CLK, "ppe-375mhz", 375000000UL),
+ CLK_PLL_OUTPUT(IPQ5424_ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(IPQ5424_ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(IPQ5424_ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(IPQ5424_ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
+ { /* Sentinel */ }
};
/*
@@ -297,7 +316,7 @@ static struct clk_hw *ipq_cmn_pll_clk_hw
static int ipq_cmn_pll_register_clks(struct platform_device *pdev)
{
- const struct cmn_pll_fixed_output_clk *fixed_clk;
+ const struct cmn_pll_fixed_output_clk *p, *fixed_clk;
struct clk_hw_onecell_data *hw_data;
struct device *dev = &pdev->dev;
struct clk_hw *cmn_pll_hw;
@@ -305,8 +324,13 @@ static int ipq_cmn_pll_register_clks(str
struct clk_hw *hw;
int ret, i;
- fixed_clk = ipq9574_output_clks;
- num_clks = ARRAY_SIZE(ipq9574_output_clks);
+ fixed_clk = device_get_match_data(dev);
+ if (!fixed_clk)
+ return -EINVAL;
+
+ num_clks = 0;
+ for (p = fixed_clk; p->name; p++)
+ num_clks++;
hw_data = devm_kzalloc(dev, struct_size(hw_data, hws, num_clks + 1),
GFP_KERNEL);
@@ -415,7 +439,8 @@ static const struct dev_pm_ops ipq_cmn_p
};
static const struct of_device_id ipq_cmn_pll_clk_ids[] = {
- { .compatible = "qcom,ipq9574-cmn-pll", },
+ { .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks },
+ { .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks },
{ }
};
MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids);

View file

@ -1,48 +0,0 @@
From 314b903c30040632db7edd187cd33003b2aee512 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 16 May 2025 16:36:09 +0400
Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL support for IPQ5018 SoC
The CMN PLL block in the IPQ5018 SoC takes 96 MHZ as the reference
input clock. Its output clocks are the XO (24Mhz), sleep (32Khz), and
ethernet (50Mhz) clocks.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250516-ipq5018-cmn-pll-v4-2-389a6b30e504@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
.../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 1 +
include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h | 16 ++++++++++++++++
2 files changed, 17 insertions(+)
create mode 100644 include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h
--- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
@@ -24,6 +24,7 @@ description:
properties:
compatible:
enum:
+ - qcom,ipq5018-cmn-pll
- qcom,ipq5424-cmn-pll
- qcom,ipq9574-cmn-pll
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,ipq5018-cmn-pll.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ5018_CMN_PLL_H
+#define _DT_BINDINGS_CLK_QCOM_IPQ5018_CMN_PLL_H
+
+/* CMN PLL core clock. */
+#define IPQ5018_CMN_PLL_CLK 0
+
+/* The output clocks from CMN PLL of IPQ5018. */
+#define IPQ5018_XO_24MHZ_CLK 1
+#define IPQ5018_SLEEP_32KHZ_CLK 2
+#define IPQ5018_ETH_50MHZ_CLK 3
+#endif

View file

@ -1,102 +0,0 @@
From 25d12630561d8d0906f1f5eceb055da3af67c8c9 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 16 May 2025 16:36:10 +0400
Subject: clk: qcom: ipq-cmn-pll: Add IPQ5018 SoC support
The CMN PLL in IPQ5018 SoC supplies fixed clocks to XO, sleep, and the
ethernet block.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250516-ipq5018-cmn-pll-v4-3-389a6b30e504@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/ipq-cmn-pll.c | 37 +++++++++++++++++++++++--------------
1 file changed, 23 insertions(+), 14 deletions(-)
(limited to 'drivers/clk/qcom/ipq-cmn-pll.c')
--- a/drivers/clk/qcom/ipq-cmn-pll.c
+++ b/drivers/clk/qcom/ipq-cmn-pll.c
@@ -50,6 +50,7 @@
#include <linux/regmap.h>
#include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
+#include <dt-bindings/clock/qcom,ipq5018-cmn-pll.h>
#include <dt-bindings/clock/qcom,ipq5424-cmn-pll.h>
#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
@@ -110,16 +111,10 @@ static const struct regmap_config ipq_cm
.fast_io = true,
};
-static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = {
- CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
- CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
- CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL),
- CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL),
- CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL),
- CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
- CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
- CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
- CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
+static const struct cmn_pll_fixed_output_clk ipq5018_output_clks[] = {
+ CLK_PLL_OUTPUT(IPQ5018_XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
+ CLK_PLL_OUTPUT(IPQ5018_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
+ CLK_PLL_OUTPUT(IPQ5018_ETH_50MHZ_CLK, "eth-50mhz", 50000000UL),
{ /* Sentinel */ }
};
@@ -136,6 +131,19 @@ static const struct cmn_pll_fixed_output
{ /* Sentinel */ }
};
+static const struct cmn_pll_fixed_output_clk ipq9574_output_clks[] = {
+ CLK_PLL_OUTPUT(XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
+ CLK_PLL_OUTPUT(SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
+ CLK_PLL_OUTPUT(PCS_31P25MHZ_CLK, "pcs-31p25mhz", 31250000UL),
+ CLK_PLL_OUTPUT(NSS_1200MHZ_CLK, "nss-1200mhz", 1200000000UL),
+ CLK_PLL_OUTPUT(PPE_353MHZ_CLK, "ppe-353mhz", 353000000UL),
+ CLK_PLL_OUTPUT(ETH0_50MHZ_CLK, "eth0-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(ETH1_50MHZ_CLK, "eth1-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(ETH2_50MHZ_CLK, "eth2-50mhz", 50000000UL),
+ CLK_PLL_OUTPUT(ETH_25MHZ_CLK, "eth-25mhz", 25000000UL),
+ { /* Sentinel */ }
+};
+
/*
* CMN PLL has the single parent clock, which supports the several
* possible parent clock rates, each parent clock rate is reflected
@@ -399,11 +407,11 @@ static int ipq_cmn_pll_clk_probe(struct
*/
ret = pm_clk_add(dev, "ahb");
if (ret)
- return dev_err_probe(dev, ret, "Fail to add AHB clock\n");
+ return dev_err_probe(dev, ret, "Failed to add AHB clock\n");
ret = pm_clk_add(dev, "sys");
if (ret)
- return dev_err_probe(dev, ret, "Fail to add SYS clock\n");
+ return dev_err_probe(dev, ret, "Failed to add SYS clock\n");
ret = pm_runtime_resume_and_get(dev);
if (ret)
@@ -414,7 +422,7 @@ static int ipq_cmn_pll_clk_probe(struct
pm_runtime_put(dev);
if (ret)
return dev_err_probe(dev, ret,
- "Fail to register CMN PLL clocks\n");
+ "Failed to register CMN PLL clocks\n");
return 0;
}
@@ -439,8 +447,9 @@ static const struct dev_pm_ops ipq_cmn_p
};
static const struct of_device_id ipq_cmn_pll_clk_ids[] = {
- { .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks },
+ { .compatible = "qcom,ipq5018-cmn-pll", .data = &ipq5018_output_clks },
{ .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks },
+ { .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks },
{ }
};
MODULE_DEVICE_TABLE(of, ipq_cmn_pll_clk_ids);

View file

@ -1,89 +0,0 @@
From c006b249c54441dd8a3a493c7c87158f441f8178 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 21 Jul 2025 10:04:35 +0400
Subject: arm64: dts: ipq5018: Add CMN PLL node
Add CMN PLL node for enabling output clocks to the networking
hardware blocks on IPQ5018 devices.
The reference clock of CMN PLL is routed from XO to the CMN PLL
through the internal WiFi block.
.XO (48 MHZ) --> WiFi (multiplier/divider)--> 96 MHZ to CMN PLL.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250721-ipq5018-cmn-pll-v5-1-4cbf3479af65@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 33 +++++++++++++++++++++++++++++++--
1 file changed, 31 insertions(+), 2 deletions(-)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -2,12 +2,13 @@
/*
* IPQ5018 SoC device tree source
*
- * Copyright (c) 2023 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2023-2025 The Linux Foundation. All rights reserved.
*/
#include <dt-bindings/clock/qcom,apss-ipq.h>
-#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
+#include <dt-bindings/clock/qcom,ipq5018-cmn-pll.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
#include <dt-bindings/thermal/thermal.h>
@@ -29,6 +30,14 @@
#clock-cells = <0>;
};
+ ref_96mhz_clk: ref-96mhz-clk {
+ compatible = "fixed-factor-clock";
+ clocks = <&xo_clk>;
+ #clock-cells = <0>;
+ clock-div = <1>;
+ clock-mult = <2>;
+ };
+
sleep_clk: sleep-clk {
compatible = "fixed-clock";
#clock-cells = <0>;
@@ -38,6 +47,12 @@
compatible = "fixed-clock";
#clock-cells = <0>;
};
+
+ xo_clk: xo-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <48000000>;
+ };
};
cpus {
@@ -229,6 +244,20 @@
status = "disabled";
};
+ cmn_pll: clock-controller@9b000 {
+ compatible = "qcom,ipq5018-cmn-pll";
+ reg = <0x0009b000 0x800>;
+ clocks = <&ref_96mhz_clk>,
+ <&gcc GCC_CMN_BLK_AHB_CLK>,
+ <&gcc GCC_CMN_BLK_SYS_CLK>;
+ clock-names = "ref",
+ "ahb",
+ "sys";
+ #clock-cells = <1>;
+ assigned-clocks = <&cmn_pll IPQ5018_CMN_PLL_CLK>;
+ assigned-clock-rates-u64 = /bits/ 64 <9600000000>;
+ };
+
qfprom: qfprom@a0000 {
compatible = "qcom,ipq5018-qfprom", "qcom,qfprom";
reg = <0x000a0000 0x1000>;

View file

@ -1,33 +0,0 @@
From 5ca3d42384a66bcb66f91d75da16ec9e9f053aab Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 21 Jul 2025 10:04:36 +0400
Subject: arm64: dts: qcom: Update IPQ5018 xo_board_clk to use fixed factor
clock
The xo_board_clk is fixed to 24 MHZ, which is routed from WiFi output
clock 96 MHZ (also being the reference clock of CMN PLL) divided by 4
to the analog block routing channel. Update the xo_board_clk nodes in
the board DTS files to use clock-div/clock-mult accordingly.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250721-ipq5018-cmn-pll-v5-2-4cbf3479af65@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -44,7 +44,8 @@
};
xo_board_clk: xo-board-clk {
- compatible = "fixed-clock";
+ compatible = "fixed-factor-clock";
+ clocks = <&ref_96mhz_clk>;
#clock-cells = <0>;
};

View file

@ -1,120 +0,0 @@
From patchwork Mon Sep 15 09:24:18 2025
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: George Moussalem <george.moussalem@outlook.com>
X-Patchwork-Id: 14231524
Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org
[10.30.226.201])
(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))
(No client certificate requested)
by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4305E2F49FD;
Mon, 15 Sep 2025 09:24:37 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
arc=none smtp.client-ip=10.30.226.201
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
t=1757928277; cv=none;
b=W4yjWHon01Sh2gBzP90ni3A/PWbNfjtSydk9zppsDHx/BPbANANjeMu4rhkRDwshIs4GuAEKBYZmGwGg0SnK/9N3ricPefdvF3PMI1VApzNpkksjRBlVeyccUbjx/+Y2/Oe/8cA1Oz4jQtocecxzE3CGh9+Kk9vqgpHa635Ky4M=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
s=arc-20240116; t=1757928277; c=relaxed/simple;
bh=RgkgrwRypdT/518CgEj/V8LfEbAO8YRYx2xOm90hzPk=;
h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc;
b=YM1Wxrnb67eDy0s8cezNXKJuM/Asp9L23eC7xAHqaosCV6mlayQFLEkibiqPvm1MRaNc/e2kOWU2I2cQMi88qUSuzlgK/veTaDHx5oePOCR/dZrkkC/bciWsT6CSiTbAbE9WOK2cuxGHzk2PQxCJaBBtFxN3Lg+Kar6d1TWv3Rw=
ARC-Authentication-Results: i=1; smtp.subspace.kernel.org;
dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
header.b=XbapCBXD; arc=none smtp.client-ip=10.30.226.201
Authentication-Results: smtp.subspace.kernel.org;
dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org
header.b="XbapCBXD"
Received: by smtp.kernel.org (Postfix) with ESMTPS id D1D1EC4CEF1;
Mon, 15 Sep 2025 09:24:36 +0000 (UTC)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org;
s=k20201202; t=1757928276;
bh=RgkgrwRypdT/518CgEj/V8LfEbAO8YRYx2xOm90hzPk=;
h=From:Date:Subject:To:Cc:Reply-To:From;
b=XbapCBXDF3N0JCGizjXEEnzD31MMXQC03i/+s2l2R0wZ8miOI4LMi5Gg4yH2GlKd+
Q6p/IdLWuIk3O4m0FpZ5lI2pKF+5siZCyzECvT+Y9LHHb6fMbXp/FNJbrOak3mz8xy
PVdw03eFO4Wj5bF3mCqyGd6HKakkfAR6ZDU9B05omFHE5FzakQMTWdHqjgi51gFOm9
EMzWFnvH1U1qqsNEicMESHpGGGhWu6VHZugCgkGnOZtnELneHxFgJLjJbYkjfZNBUZ
endu4HugvKFXwjcJFtv84yplTu3poxGqmKcC4DtURMjGwFa72IZgv6lJ1c/MXLajAx
7/Y8KfWSDjnpQ==
Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org
(localhost.localdomain [127.0.0.1])
by smtp.lore.kernel.org (Postfix) with ESMTP id C31A1CAC598;
Mon, 15 Sep 2025 09:24:36 +0000 (UTC)
Date: Mon, 15 Sep 2025 13:24:18 +0400
Subject: [PATCH] arm64: dts: qcom: ipq5018: add QUP3 I2C node
Precedence: bulk
X-Mailing-List: linux-arm-msm@vger.kernel.org
List-Id: <linux-arm-msm.vger.kernel.org>
List-Subscribe: <mailto:linux-arm-msm+subscribe@vger.kernel.org>
List-Unsubscribe: <mailto:linux-arm-msm+unsubscribe@vger.kernel.org>
MIME-Version: 1.0
Message-Id: <20250915-ipq5018-i2c-v1-1-46bbf27396d6@outlook.com>
X-B4-Tracking: v=1; b=H4sIAEHbx2gC/x3MQQqAIBBA0avIrBNmBMu6SrSQGms2ZQoRiHdPW
r7F/wUyJ+EMkyqQ+JEs19lAnYL18OfOWrZmMGgsjkRa4m2RnBazavQYPA29ceSgFTFxkPe/zUu
tH1sLzpNdAAAA
X-Change-ID: 20250911-ipq5018-i2c-0a0fa1762818
To: Bjorn Andersson <andersson@kernel.org>,
Konrad Dybcio <konradybcio@kernel.org>, Rob Herring <robh@kernel.org>,
Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>
Cc: linux-arm-msm@vger.kernel.org, devicetree@vger.kernel.org,
linux-kernel@vger.kernel.org,
Vandhiadevan Karunamoorthy <vkarunam@codeaurora.org>,
George Moussalem <george.moussalem@outlook.com>
X-Mailer: b4 0.14.2
X-Developer-Signature: v=1; a=ed25519-sha256; t=1757928274; l=1420;
i=george.moussalem@outlook.com; s=20250321; h=from:subject:message-id;
bh=5AMg7/oGtHNBWL+11z9Q/HGGQ9F6ll9nuoBPaZhI9aM=;
b=YRzjCtxRPYCTIZbfjE7Ch/iQgVk2FPQ2D3Z9XheAftOihKy/1/tmjGVVJNjCCP6dXt51fm4rq
wtSUjXqnECrAN3FPi6I7N+IBTc6A+E6Q/wpYazdNwaMdyxGBj0tyK4f
X-Developer-Key: i=george.moussalem@outlook.com; a=ed25519;
pk=/PuRTSI9iYiHwcc6Nrde8qF4ZDhJBlUgpHdhsIjnqIk=
X-Endpoint-Received: by B4 Relay for george.moussalem@outlook.com/20250321
with auth_id=364
X-Original-From: George Moussalem <george.moussalem@outlook.com>
Reply-To: george.moussalem@outlook.com
From: George Moussalem <george.moussalem@outlook.com>
From: Vandhiadevan Karunamoorthy <vkarunam@codeaurora.org>
Add node to support I2C bus inside of IPQ5018.
Signed-off-by: Vandhiadevan Karunamoorthy <vkarunam@codeaurora.org>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 15 +++++++++++++++
1 file changed, 15 insertions(+)
---
base-commit: b0971d2008c644b9064d968d440fb9f44606d90c
change-id: 20250911-ipq5018-i2c-0a0fa1762818
Best regards,
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -504,6 +504,21 @@
status = "disabled";
};
+ blsp1_i2c3: i2c@78b7000 {
+ compatible = "qcom,i2c-qup-v2.2.1";
+ reg = <0x078b7000 0x600>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ interrupts = <GIC_SPI 97 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_QUP3_I2C_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ clock-frequency = <400000>;
+ dmas = <&blsp_dma 9>, <&blsp_dma 8>;
+ dma-names = "tx", "rx";
+ status = "disabled";
+ };
+
qpic_bam: dma-controller@7984000 {
compatible = "qcom,bam-v1.7.4", "qcom,bam-v1.7.0";
reg = <0x07984000 0x1c000>;

View file

@ -1,36 +0,0 @@
From b410d25fb349bc32132749bd2cb17aa17054287d Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Wed, 17 Sep 2025 15:49:00 +0400
Subject: arm64: dts: qcom: ipq5018: add QUP1 UART2 node
Add node to support the second UART node controller in IPQ5018.
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250917-ipq5018-uart2-v1-1-f8680bbf947f@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -490,6 +490,16 @@
status = "disabled";
};
+ blsp1_uart2: serial@78b0000 {
+ compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+ reg = <0x078b0000 0x200>;
+ interrupts = <GIC_SPI 108 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&gcc GCC_BLSP1_UART2_APPS_CLK>,
+ <&gcc GCC_BLSP1_AHB_CLK>;
+ clock-names = "core", "iface";
+ status = "disabled";
+ };
+
blsp1_spi1: spi@78b5000 {
compatible = "qcom,spi-qup-v2.2.1";
#address-cells = <1>;

View file

@ -1,30 +0,0 @@
From 60fb18fbc234efb2d59472a889282dba2df3402a Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 18 Aug 2025 15:33:47 +0400
Subject: arm64: dts: qcom: ipq5018: Remove tsens v1 fallback compatible
Remove qcom,tsens-v1 as fallback compatible since this IP has no RPM
and, as such, must use its own init routine available in the driver.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20250818-ipq5018-tsens-fix-v1-2-0f08cf09182d@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -340,7 +340,7 @@
};
tsens: thermal-sensor@4a9000 {
- compatible = "qcom,ipq5018-tsens", "qcom,tsens-v1";
+ compatible = "qcom,ipq5018-tsens";
reg = <0x004a9000 0x1000>,
<0x004a8000 0x1000>;

View file

@ -1,48 +0,0 @@
From d106f9681d1952b7c19726b0713cee6ae11211f5 Mon Sep 17 00:00:00 2001
From: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Date: Tue, 6 Jan 2026 19:51:24 +0100
Subject: arm64: dts: qcom: ipq5018: Correct USB DWC3 wrapper interrupts
Interrupts for DWC3 node were completely mixed up - SPI interrupt 62 is
not listed in reference manual at all. It was also causing dtbs_check
warnings:
ipq5018-rdp432-c2.dtb: usb@8af8800 (qcom,ipq5018-dwc3): interrupt-names:0: 'pwr_event' was expected
ipq5018-rdp432-c2.dtb: usb@8af8800 (qcom,ipq5018-dwc3): interrupt-names: ['hs_phy_irq'] is too short
Warning itself was introduced by commit 53c6d854be4e ("dt-bindings: usb:
dwc3: Clean up hs_phy_irq in binding"), but this was trying to bring
sanity to the interrupts overall, although did a mistake for IPQ5018.
IPQ5018 does not have QUSB2 PHY and its interrupts should rather match
ones used in IPQ5332.
Correct it by using interrupts matching the bindings and reference
manual.
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Tested-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20260106185123.19929-3-krzysztof.kozlowski@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -571,8 +571,12 @@
compatible = "qcom,ipq5018-dwc3", "qcom,dwc3";
reg = <0x08af8800 0x400>;
- interrupts = <GIC_SPI 62 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "hs_phy_irq";
+ interrupts = <GIC_SPI 134 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "pwr_event",
+ "dp_hs_phy_irq",
+ "dm_hs_phy_irq";
clocks = <&gcc GCC_USB0_MASTER_CLK>,
<&gcc GCC_SYS_NOC_USB0_AXI_CLK>,

View file

@ -1,74 +0,0 @@
From a8cd1a1baadbfed43ac214f0bf3e26c90e3b521e Mon Sep 17 00:00:00 2001
From: Devi Priya <quic_devipriy@quicinc.com>
Date: Mon, 6 Apr 2026 22:24:38 +0200
Subject: [PATCH] dt-bindings: pwm: add IPQ6018 binding
DT binding for the PWM block in Qualcomm IPQ6018 SoC.
Reviewed-by: Bjorn Andersson <bjorn.andersson@linaro.org>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://patch.msgid.link/20260406-ipq-pwm-v21-1-6ed1e868e4c2@outlook.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
---
.../bindings/pwm/qcom,ipq6018-pwm.yaml | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
--- /dev/null
+++ b/Documentation/devicetree/bindings/pwm/qcom,ipq6018-pwm.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/pwm/qcom,ipq6018-pwm.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm IPQ6018 PWM controller
+
+maintainers:
+ - George Moussalem <george.moussalem@outlook.com>
+
+properties:
+ compatible:
+ oneOf:
+ - items:
+ - enum:
+ - qcom,ipq5018-pwm
+ - qcom,ipq5332-pwm
+ - qcom,ipq9574-pwm
+ - const: qcom,ipq6018-pwm
+ - const: qcom,ipq6018-pwm
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ "#pwm-cells":
+ const: 3
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - "#pwm-cells"
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/qcom,gcc-ipq6018.h>
+
+ pwm: pwm@1941010 {
+ compatible = "qcom,ipq6018-pwm";
+ reg = <0x01941010 0x20>;
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clock-rates = <100000000>;
+ #pwm-cells = <3>;
+ };

View file

@ -1,326 +0,0 @@
From c436e3e9c265a1f012008ef5da6fd28863f8025c Mon Sep 17 00:00:00 2001
From: Devi Priya <quic_devipriy@quicinc.com>
Date: Mon, 6 Apr 2026 22:24:39 +0200
Subject: [PATCH] pwm: Driver for qualcomm ipq6018 pwm block
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Driver for the PWM block in Qualcomm IPQ6018 line of SoCs. Based on
driver from downstream Codeaurora kernel tree. Removed support for older
(V1) variants because I have no access to that hardware.
Tested on IPQ5018 and IPQ6010 based hardware.
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
Reviewed-by: Bjorn Andersson <andersson@kernel.org>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://patch.msgid.link/20260406-ipq-pwm-v21-2-6ed1e868e4c2@outlook.com
[ukleinek: Fixed a few nitpicks as agreed on the mailing list]
Signed-off-by: Uwe Kleine-König <ukleinek@kernel.org>
---
drivers/pwm/Kconfig | 12 ++
drivers/pwm/Makefile | 1 +
drivers/pwm/pwm-ipq.c | 263 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 276 insertions(+)
create mode 100644 drivers/pwm/pwm-ipq.c
--- a/drivers/pwm/Kconfig
+++ b/drivers/pwm/Kconfig
@@ -319,6 +319,18 @@ config PWM_INTEL_LGM
To compile this driver as a module, choose M here: the module
will be called pwm-intel-lgm.
+config PWM_IPQ
+ tristate "IPQ PWM support"
+ depends on ARCH_QCOM || COMPILE_TEST
+ depends on HAVE_CLK && HAS_IOMEM
+ help
+ Generic PWM framework driver for IPQ PWM block which supports
+ 4 pwm channels. Each of the these channels can be configured
+ independent of each other.
+
+ To compile this driver as a module, choose M here: the module
+ will be called pwm-ipq.
+
config PWM_IQS620A
tristate "Azoteq IQS620A PWM support"
depends on MFD_IQS62X || COMPILE_TEST
--- a/drivers/pwm/Makefile
+++ b/drivers/pwm/Makefile
@@ -27,6 +27,7 @@ obj-$(CONFIG_PWM_IMX1) += pwm-imx1.o
obj-$(CONFIG_PWM_IMX27) += pwm-imx27.o
obj-$(CONFIG_PWM_IMX_TPM) += pwm-imx-tpm.o
obj-$(CONFIG_PWM_INTEL_LGM) += pwm-intel-lgm.o
+obj-$(CONFIG_PWM_IPQ) += pwm-ipq.o
obj-$(CONFIG_PWM_IQS620A) += pwm-iqs620a.o
obj-$(CONFIG_PWM_JZ4740) += pwm-jz4740.o
obj-$(CONFIG_PWM_KEEMBAY) += pwm-keembay.o
--- /dev/null
+++ b/drivers/pwm/pwm-ipq.c
@@ -0,0 +1,263 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright (c) 2016-2017, 2020 The Linux Foundation. All rights reserved.
+ *
+ * Limitations:
+ * - The PWM controller has no publicly available datasheet.
+ * - Each of the four channels is programmed via two 32-bit registers
+ * (REG0 and REG1 at 8-byte stride).
+ * - Period and duty-cycle reconfiguration is fully atomic: new divider,
+ * pre-divider, and high-duration values are latched by setting the
+ * UPDATE bit (bit 30 in REG1). The hardware applies the new settings
+ * at the beginning of the next period without disabling the output,
+ * so the currently running period is always completed.
+ * - On disable (clearing the ENABLE bit 31 in REG1), the hardware
+ * finishes the current period before stopping the output. The pin
+ * is then driven to the inactive (low) level.
+ * - Upon disabling, the hardware resets the pre-divider (PRE_DIV) and divider
+ * fields (PWM_DIV) in REG0 and REG1 to 0x0000 and 0x0001 respectively.
+ * - Only normal polarity is supported.
+ */
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/math64.h>
+#include <linux/of_device.h>
+#include <linux/bitfield.h>
+#include <linux/units.h>
+
+/* The frequency range supported is 1 Hz to 100 Mhz (clock rate) */
+#define IPQ_PWM_MAX_PERIOD_NS ((u64)NSEC_PER_SEC)
+#define IPQ_PWM_MIN_PERIOD_NS 10
+
+/*
+ * Two 32-bit registers for each PWM: REG0, and REG1.
+ * Base offset for PWM #i is at 8 * #i.
+ */
+#define IPQ_PWM_REG0 0
+#define IPQ_PWM_REG0_PWM_DIV GENMASK(15, 0)
+#define IPQ_PWM_REG0_HI_DURATION GENMASK(31, 16)
+
+#define IPQ_PWM_REG1 4
+#define IPQ_PWM_REG1_PRE_DIV GENMASK(15, 0)
+/*
+ * Enable bit is set to enable output toggling in pwm device.
+ * Update bit is set to trigger the change and is unset automatically
+ * to reflect the changed divider and high duration values in register.
+ */
+#define IPQ_PWM_REG1_UPDATE BIT(30)
+#define IPQ_PWM_REG1_ENABLE BIT(31)
+
+/*
+ * The max value specified for each field is based on the number of bits
+ * in the pwm control register for that field (16-bit)
+ */
+#define IPQ_PWM_MAX_DIV FIELD_MAX(IPQ_PWM_REG0_PWM_DIV)
+
+struct ipq_pwm_chip {
+ void __iomem *mem;
+ unsigned long clk_rate;
+};
+
+static struct ipq_pwm_chip *ipq_pwm_from_chip(struct pwm_chip *chip)
+{
+ return pwmchip_get_drvdata(chip);
+}
+
+static unsigned int ipq_pwm_reg_read(struct pwm_device *pwm, unsigned int reg)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);
+ unsigned int off = 8 * pwm->hwpwm + reg;
+
+ return readl(ipq_chip->mem + off);
+}
+
+static void ipq_pwm_reg_write(struct pwm_device *pwm, unsigned int reg,
+ unsigned int val)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(pwm->chip);
+ unsigned int off = 8 * pwm->hwpwm + reg;
+
+ writel(val, ipq_chip->mem + off);
+}
+
+static int ipq_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm,
+ const struct pwm_state *state)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
+ unsigned int pre_div, pwm_div;
+ u64 period_ns, duty_ns;
+ unsigned long val = 0;
+ unsigned long hi_dur;
+
+ if (!state->enabled) {
+ /* clear IPQ_PWM_REG1_ENABLE */
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, IPQ_PWM_REG1_UPDATE);
+ return 0;
+ }
+
+ if (state->polarity != PWM_POLARITY_NORMAL)
+ return -EINVAL;
+
+ /*
+ * Check the upper and lower bounds for the period as per
+ * hardware limits
+ */
+ if (state->period < IPQ_PWM_MIN_PERIOD_NS)
+ return -ERANGE;
+ period_ns = min(state->period, IPQ_PWM_MAX_PERIOD_NS);
+ duty_ns = min(state->duty_cycle, period_ns);
+
+ /*
+ * Pick the maximal value for PWM_DIV that still allows a
+ * 100% relative duty cycle. This allows a fine grained
+ * selection of duty cycles.
+ */
+ pwm_div = IPQ_PWM_MAX_DIV - 1;
+
+ /*
+ * although mul_u64_u64_div_u64 returns a u64, in practice it
+ * won't overflow due to above constraints. Take the max period
+ * of 10^9 (NSEC_PER_SEC) and the pwm_div + 1 (IPQ_PWM_MAX_DIV)
+ * 10^9 * 10^8
+ * ------------- => which fits well into a 32-bit unsigned int.
+ * 10^9 * 65,535
+ */
+ pre_div = mul_u64_u64_div_u64(period_ns, ipq_chip->clk_rate,
+ (u64)NSEC_PER_SEC * (pwm_div + 1));
+
+ if (!pre_div)
+ return -ERANGE;
+
+ pre_div -= 1;
+
+ if (pre_div > IPQ_PWM_MAX_DIV)
+ pre_div = IPQ_PWM_MAX_DIV;
+
+ /* pwm duty = HI_DUR * (PRE_DIV + 1) / clk_rate */
+ hi_dur = mul_u64_u64_div_u64(duty_ns, ipq_chip->clk_rate,
+ (u64)NSEC_PER_SEC * (pre_div + 1));
+
+ val = FIELD_PREP(IPQ_PWM_REG0_HI_DURATION, hi_dur) |
+ FIELD_PREP(IPQ_PWM_REG0_PWM_DIV, pwm_div);
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG0, val);
+
+ val = FIELD_PREP(IPQ_PWM_REG1_PRE_DIV, pre_div);
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
+
+ /* PWM enable toggle needs a separate write to REG1 */
+ val |= IPQ_PWM_REG1_UPDATE | IPQ_PWM_REG1_ENABLE;
+ ipq_pwm_reg_write(pwm, IPQ_PWM_REG1, val);
+
+ return 0;
+}
+
+static int ipq_pwm_get_state(struct pwm_chip *chip, struct pwm_device *pwm,
+ struct pwm_state *state)
+{
+ struct ipq_pwm_chip *ipq_chip = ipq_pwm_from_chip(chip);
+ unsigned int pre_div, pwm_div, hi_dur;
+ u64 effective_div, hi_div;
+ u32 reg0, reg1;
+
+ reg1 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG1);
+ state->enabled = reg1 & IPQ_PWM_REG1_ENABLE;
+
+ if (!state->enabled)
+ return 0;
+
+ reg0 = ipq_pwm_reg_read(pwm, IPQ_PWM_REG0);
+
+ state->polarity = PWM_POLARITY_NORMAL;
+
+ pwm_div = FIELD_GET(IPQ_PWM_REG0_PWM_DIV, reg0);
+ hi_dur = FIELD_GET(IPQ_PWM_REG0_HI_DURATION, reg0);
+ pre_div = FIELD_GET(IPQ_PWM_REG1_PRE_DIV, reg1);
+
+ effective_div = (u64)(pwm_div + 1) * (pre_div + 1);
+
+ /*
+ * effective_div <= 0x100000000, so the multiplication doesn't overflow.
+ */
+ state->period = DIV64_U64_ROUND_UP(effective_div * NSEC_PER_SEC,
+ ipq_chip->clk_rate);
+
+ hi_div = hi_dur * (pre_div + 1);
+ state->duty_cycle = DIV64_U64_ROUND_UP(hi_div * NSEC_PER_SEC,
+ ipq_chip->clk_rate);
+
+ /*
+ * ensure a valid config is passed back to PWM core in case duty_cycle
+ * is > period (>100%)
+ */
+ state->duty_cycle = min(state->duty_cycle, state->period);
+
+ return 0;
+}
+
+static const struct pwm_ops ipq_pwm_ops = {
+ .apply = ipq_pwm_apply,
+ .get_state = ipq_pwm_get_state,
+};
+
+static int ipq_pwm_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct ipq_pwm_chip *pwm;
+ struct pwm_chip *chip;
+ struct clk *clk;
+ int ret;
+
+ chip = devm_pwmchip_alloc(dev, 4, sizeof(*pwm));
+ if (IS_ERR(chip))
+ return PTR_ERR(chip);
+ pwm = ipq_pwm_from_chip(chip);
+
+ pwm->mem = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(pwm->mem))
+ return dev_err_probe(dev, PTR_ERR(pwm->mem),
+ "Failed to acquire resource\n");
+
+ clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(dev, PTR_ERR(clk),
+ "Failed to get clock\n");
+
+ ret = devm_clk_rate_exclusive_get(dev, clk);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to lock clock rate\n");
+
+ pwm->clk_rate = clk_get_rate(clk);
+ if (!pwm->clk_rate)
+ return dev_err_probe(dev, -EINVAL, "Failed due to clock rate being zero\n");
+
+ chip->ops = &ipq_pwm_ops;
+
+ ret = devm_pwmchip_add(dev, chip);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to add pwm chip\n");
+
+ return 0;
+}
+
+static const struct of_device_id pwm_ipq_dt_match[] = {
+ { .compatible = "qcom,ipq6018-pwm", },
+ {}
+};
+MODULE_DEVICE_TABLE(of, pwm_ipq_dt_match);
+
+static struct platform_driver ipq_pwm_driver = {
+ .driver = {
+ .name = "ipq-pwm",
+ .of_match_table = pwm_ipq_dt_match,
+ },
+ .probe = ipq_pwm_probe,
+};
+
+module_platform_driver(ipq_pwm_driver);
+
+MODULE_LICENSE("GPL");

View file

@ -1,44 +0,0 @@
From 6cc812b7435a64cd9d66af107c6dfefb2e77a7cb Mon Sep 17 00:00:00 2001
From: Devi Priya <quic_devipriy@quicinc.com>
Date: Mon, 6 Apr 2026 22:24:40 +0200
Subject: arm64: dts: qcom: ipq6018: add pwm node
Describe the PWM block on IPQ6018.
Although PWM is in the TCSR area, make pwm its own node as simple-mfd
has been removed from the bindings and as such hardware components
should have its own node.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Co-developed-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Baruch Siach <baruch.siach@siklu.com>
Signed-off-by: Devi Priya <quic_devipriy@quicinc.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20260406-ipq-pwm-v21-3-6ed1e868e4c2@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq6018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -416,6 +416,16 @@
reg = <0x0 0x01937000 0x0 0x21000>;
};
+ pwm: pwm@1941010 {
+ compatible = "qcom,ipq6018-pwm";
+ reg = <0x0 0x01941010 0x0 0x20>;
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clock-rates = <100000000>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
usb2: usb@70f8800 {
compatible = "qcom,ipq6018-dwc3", "qcom,dwc3";
reg = <0x0 0x070f8800 0x0 0x400>;

View file

@ -1,41 +0,0 @@
From 4b00afd17a28f44dc63a8602143f84e5f3fa592c Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 6 Apr 2026 22:24:41 +0200
Subject: arm64: dts: qcom: ipq5018: add pwm node
Describe the PWM block on IPQ5018.
Although PWM is in the TCSR area, make pwm its own node as simple-mfd
has been removed from the bindings and as such hardware components
should have its own node.
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20260406-ipq-pwm-v21-4-6ed1e868e4c2@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 10 ++++++++++
1 file changed, 10 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -453,6 +453,16 @@
reg = <0x01937000 0x21000>;
};
+ pwm: pwm@1941010 {
+ compatible = "qcom,ipq5018-pwm", "qcom,ipq6018-pwm";
+ reg = <0x01941010 0x20>;
+ clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clocks = <&gcc GCC_ADSS_PWM_CLK>;
+ assigned-clock-rates = <100000000>;
+ #pwm-cells = <3>;
+ status = "disabled";
+ };
+
sdhc_1: mmc@7804000 {
compatible = "qcom,ipq5018-sdhci", "qcom,sdhci-msm-v5";
reg = <0x7804000 0x1000>;

View file

@ -1,52 +0,0 @@
From a57666004f49fa5031d6bf388834213e6f961922 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 11 Mar 2026 19:39:38 +0100
Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL support for IPQ6018
The CMN PLL block in the IPQ6018 SoC takes 48 MHz as the reference
input clock. Its output clocks are the bias_pll_cc_clk (300 MHz) and
bias_pll_nss_noc_clk (416.5 MHz) clocks used by the networking
subsystem.
Add the related compatible for IPQ6018 to the ipq9574-cmn-pll
generic schema.
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260311183942.10134-2-ansuelsmth@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
.../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 1 +
include/dt-bindings/clock/qcom,ipq6018-cmn-pll.h | 15 +++++++++++++++
2 files changed, 16 insertions(+)
create mode 100644 include/dt-bindings/clock/qcom,ipq6018-cmn-pll.h
--- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
@@ -26,6 +26,7 @@ properties:
enum:
- qcom,ipq5018-cmn-pll
- qcom,ipq5424-cmn-pll
+ - qcom,ipq6018-cmn-pll
- qcom,ipq9574-cmn-pll
reg:
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,ipq6018-cmn-pll.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ6018_CMN_PLL_H
+#define _DT_BINDINGS_CLK_QCOM_IPQ6018_CMN_PLL_H
+
+/* CMN PLL core clock. */
+#define IPQ6018_CMN_PLL_CLK 0
+
+/* The output clocks from CMN PLL of IPQ6018. */
+#define IPQ6018_BIAS_PLL_CC_CLK 1
+#define IPQ6018_BIAS_PLL_NSS_NOC_CLK 2
+#endif

View file

@ -1,52 +0,0 @@
From 7156c65030006e6930dd99c5b8c5e84e69ca5f0b Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 11 Mar 2026 19:39:40 +0100
Subject: [PATCH] dt-bindings: clock: qcom: Add CMN PLL support for IPQ8074
The CMN PLL block in the IPQ8074 SoC takes 48 MHz as the reference
input clock. Its output clocks are the bias_pll_cc_clk (300 MHz) and
bias_pll_nss_noc_clk (416.5 MHz) clocks used by the networking
subsystem.
Add the related compatible for IPQ8074 to the ipq9574-cmn-pll
generic schema.
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260311183942.10134-4-ansuelsmth@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
.../bindings/clock/qcom,ipq9574-cmn-pll.yaml | 1 +
include/dt-bindings/clock/qcom,ipq8074-cmn-pll.h | 15 +++++++++++++++
2 files changed, 16 insertions(+)
create mode 100644 include/dt-bindings/clock/qcom,ipq8074-cmn-pll.h
--- a/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
+++ b/Documentation/devicetree/bindings/clock/qcom,ipq9574-cmn-pll.yaml
@@ -27,6 +27,7 @@ properties:
- qcom,ipq5018-cmn-pll
- qcom,ipq5424-cmn-pll
- qcom,ipq6018-cmn-pll
+ - qcom,ipq8074-cmn-pll
- qcom,ipq9574-cmn-pll
reg:
--- /dev/null
+++ b/include/dt-bindings/clock/qcom,ipq8074-cmn-pll.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef _DT_BINDINGS_CLK_QCOM_IPQ8074_CMN_PLL_H
+#define _DT_BINDINGS_CLK_QCOM_IPQ8074_CMN_PLL_H
+
+/* CMN PLL core clock. */
+#define IPQ8074_CMN_PLL_CLK 0
+
+/* The output clocks from CMN PLL of IPQ8074. */
+#define IPQ8074_BIAS_PLL_CC_CLK 1
+#define IPQ8074_BIAS_PLL_NSS_NOC_CLK 2
+#endif

View file

@ -1,48 +0,0 @@
From 97eb2ac52726fbb702ced40d552a3f6f2683b664 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 11 Mar 2026 19:39:39 +0100
Subject: [PATCH] clk: qcom: ipq-cmn-pll: Add IPQ6018 SoC support
The CMN PLL in IPQ6018 SoC supplies fixed clocks to the networking
subsystem: bias_pll_cc_clk at 300 MHz and bias_pll_nss_noc_clk at
416.5 MHz.
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20260311183942.10134-3-ansuelsmth@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/ipq-cmn-pll.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/clk/qcom/ipq-cmn-pll.c
+++ b/drivers/clk/qcom/ipq-cmn-pll.c
@@ -52,6 +52,7 @@
#include <dt-bindings/clock/qcom,ipq-cmn-pll.h>
#include <dt-bindings/clock/qcom,ipq5018-cmn-pll.h>
#include <dt-bindings/clock/qcom,ipq5424-cmn-pll.h>
+#include <dt-bindings/clock/qcom,ipq6018-cmn-pll.h>
#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8)
@@ -118,6 +119,12 @@ static const struct cmn_pll_fixed_output
{ /* Sentinel */ }
};
+static const struct cmn_pll_fixed_output_clk ipq6018_output_clks[] = {
+ CLK_PLL_OUTPUT(IPQ6018_BIAS_PLL_CC_CLK, "bias_pll_cc_clk", 300000000UL),
+ CLK_PLL_OUTPUT(IPQ6018_BIAS_PLL_NSS_NOC_CLK, "bias_pll_nss_noc_clk", 416500000UL),
+ { /* Sentinel */ }
+};
+
static const struct cmn_pll_fixed_output_clk ipq5424_output_clks[] = {
CLK_PLL_OUTPUT(IPQ5424_XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
CLK_PLL_OUTPUT(IPQ5424_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
@@ -449,6 +456,7 @@ static const struct dev_pm_ops ipq_cmn_p
static const struct of_device_id ipq_cmn_pll_clk_ids[] = {
{ .compatible = "qcom,ipq5018-cmn-pll", .data = &ipq5018_output_clks },
{ .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks },
+ { .compatible = "qcom,ipq6018-cmn-pll", .data = &ipq6018_output_clks },
{ .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks },
{ }
};

View file

@ -1,48 +0,0 @@
From 4e36f8ab45c406420f2c2ce6ee3988e0d13ba1c9 Mon Sep 17 00:00:00 2001
From: John Crispin <john@phrozen.org>
Date: Wed, 11 Mar 2026 19:39:41 +0100
Subject: [PATCH] clk: qcom: ipq-cmn-pll: Add IPQ8074 SoC support
The CMN PLL in IPQ8074 SoC supplies fixed clocks to the networking
subsystem: bias_pll_cc_clk at 300 MHz and bias_pll_nss_noc_clk at
416.5 MHz.
Signed-off-by: John Crispin <john@phrozen.org>
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
Link: https://lore.kernel.org/r/20260311183942.10134-5-ansuelsmth@gmail.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/ipq-cmn-pll.c | 8 ++++++++
1 file changed, 8 insertions(+)
--- a/drivers/clk/qcom/ipq-cmn-pll.c
+++ b/drivers/clk/qcom/ipq-cmn-pll.c
@@ -53,6 +53,7 @@
#include <dt-bindings/clock/qcom,ipq5018-cmn-pll.h>
#include <dt-bindings/clock/qcom,ipq5424-cmn-pll.h>
#include <dt-bindings/clock/qcom,ipq6018-cmn-pll.h>
+#include <dt-bindings/clock/qcom,ipq8074-cmn-pll.h>
#define CMN_PLL_REFCLK_SRC_SELECTION 0x28
#define CMN_PLL_REFCLK_SRC_DIV GENMASK(9, 8)
@@ -125,6 +126,12 @@ static const struct cmn_pll_fixed_output
{ /* Sentinel */ }
};
+static const struct cmn_pll_fixed_output_clk ipq8074_output_clks[] = {
+ CLK_PLL_OUTPUT(IPQ8074_BIAS_PLL_CC_CLK, "bias_pll_cc_clk", 300000000UL),
+ CLK_PLL_OUTPUT(IPQ8074_BIAS_PLL_NSS_NOC_CLK, "bias_pll_nss_noc_clk", 416500000UL),
+ { /* Sentinel */ }
+};
+
static const struct cmn_pll_fixed_output_clk ipq5424_output_clks[] = {
CLK_PLL_OUTPUT(IPQ5424_XO_24MHZ_CLK, "xo-24mhz", 24000000UL),
CLK_PLL_OUTPUT(IPQ5424_SLEEP_32KHZ_CLK, "sleep-32khz", 32000UL),
@@ -457,6 +464,7 @@ static const struct of_device_id ipq_cmn
{ .compatible = "qcom,ipq5018-cmn-pll", .data = &ipq5018_output_clks },
{ .compatible = "qcom,ipq5424-cmn-pll", .data = &ipq5424_output_clks },
{ .compatible = "qcom,ipq6018-cmn-pll", .data = &ipq6018_output_clks },
+ { .compatible = "qcom,ipq8074-cmn-pll", .data = &ipq8074_output_clks },
{ .compatible = "qcom,ipq9574-cmn-pll", .data = &ipq9574_output_clks },
{ }
};

View file

@ -1,56 +0,0 @@
From 88c543fff756450bcd04ec4560c4440be36c9e75 Mon Sep 17 00:00:00 2001
From: Luo Jie <jie.luo@oss.qualcomm.com>
Date: Tue, 6 Jan 2026 21:35:10 -0800
Subject: [PATCH] clk: qcom: cmnpll: Account for reference clock divider
The clk_cmn_pll_recalc_rate() function must account for the reference clock
divider programmed in CMN_PLL_REFCLK_CONFIG. Without this fix, platforms
with a reference divider other than 1 calculate incorrect CMN PLL rates.
For example, on IPQ5332 where the reference divider is 2, the computed rate
becomes twice the actual output.
Read CMN_PLL_REFCLK_DIV and divide the parent rate by this value before
applying the 2 * FACTOR scaling. This yields the correct rate calculation:
rate = (parent_rate / ref_div) * 2 * factor.
Maintain backward compatibility with earlier platforms (e.g. IPQ9574,
IPQ5424, IPQ5018) that use ref_div = 1.
Fixes: f81715a4c87c ("clk: qcom: Add CMN PLL clock controller driver for IPQ SoC")
Signed-off-by: Luo Jie <jie.luo@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Tested-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20260106-qcom_ipq5332_cmnpll-v2-1-f9f7e4efbd79@oss.qualcomm.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
drivers/clk/qcom/ipq-cmn-pll.c | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
--- a/drivers/clk/qcom/ipq-cmn-pll.c
+++ b/drivers/clk/qcom/ipq-cmn-pll.c
@@ -200,7 +200,7 @@ static unsigned long clk_cmn_pll_recalc_
unsigned long parent_rate)
{
struct clk_cmn_pll *cmn_pll = to_clk_cmn_pll(hw);
- u32 val, factor;
+ u32 val, factor, ref_div;
/*
* The value of CMN_PLL_DIVIDER_CTRL_FACTOR is automatically adjusted
@@ -208,8 +208,15 @@ static unsigned long clk_cmn_pll_recalc_
*/
regmap_read(cmn_pll->regmap, CMN_PLL_DIVIDER_CTRL, &val);
factor = FIELD_GET(CMN_PLL_DIVIDER_CTRL_FACTOR, val);
+ if (WARN_ON(factor == 0))
+ factor = 1;
- return parent_rate * 2 * factor;
+ regmap_read(cmn_pll->regmap, CMN_PLL_REFCLK_CONFIG, &val);
+ ref_div = FIELD_GET(CMN_PLL_REFCLK_DIV, val);
+ if (WARN_ON(ref_div == 0))
+ ref_div = 1;
+
+ return div_u64((u64)parent_rate * 2 * factor, ref_div);
}
static int clk_cmn_pll_determine_rate(struct clk_hw *hw,

View file

@ -1,35 +0,0 @@
From 02320d694fa1124b8b77fcb52191141004ef7fbb Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Thu, 21 May 2026 11:55:58 +0400
Subject: arm64: dts: qcom: ipq5018: Correct CMN PLL reference clock rate
The correct CMN PLL reference clock rate for IPQ5018 is 4.8 GHz.
The CMN PLL driver did not account for the ref clock divider which is 2
for IPQ5018. Therefore, the computed rate was twice the actual output.
With the driver now accounting for the CMN PLL reference clock
divider (commit: 88c543fff756), set the correct reference clock rate.
Fixes: c006b249c544 ("arm64: dts: ipq5018: Add CMN PLL node")
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Acked-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Link: https://lore.kernel.org/r/20260521-ipq5018-cmn-pll-rate-fix-v2-1-04b28a92e0f2@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -256,7 +256,7 @@
"sys";
#clock-cells = <1>;
assigned-clocks = <&cmn_pll IPQ5018_CMN_PLL_CLK>;
- assigned-clock-rates-u64 = /bits/ 64 <9600000000>;
+ assigned-clock-rates-u64 = /bits/ 64 <4800000000>;
};
qfprom: qfprom@a0000 {

View file

@ -1,90 +0,0 @@
From 82eaf94d69fce20f8859a2b8dae8e7064d9343da Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 13 Jun 2025 05:55:07 +0400
Subject: [PATCH] dt-bindings: net: qca,ar803x: Add IPQ5018 Internal GE PHY
support
Document the IPQ5018 Internal Gigabit Ethernet PHY found in the IPQ5018
SoC. Its output pins provide an MDI interface to either an external
switch in a PHY to PHY link scenario or is directly attached to an RJ45
connector.
The PHY supports 10/100/1000 mbps link modes, CDT, auto-negotiation and
802.3az EEE.
For operation, the LDO controller found in the IPQ5018 SoC for which
there is provision in the mdio-4019 driver.
Two common archictures across IPQ5018 boards are:
1. IPQ5018 PHY --> MDI --> RJ45 connector
2. IPQ5018 PHY --> MDI --> External PHY
In a phy to phy architecture, the DAC needs to be configured to
accommodate for the short cable length. As such, add an optional boolean
property so the driver sets preset DAC register values accordingly.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Link: https://patch.msgid.link/20250613-ipq5018-ge-phy-v5-1-9af06e34ea6b@outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
.../devicetree/bindings/net/qca,ar803x.yaml | 43 +++++++++++++++++++
1 file changed, 43 insertions(+)
--- a/Documentation/devicetree/bindings/net/qca,ar803x.yaml
+++ b/Documentation/devicetree/bindings/net/qca,ar803x.yaml
@@ -16,8 +16,37 @@ description: |
allOf:
- $ref: ethernet-phy.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - ethernet-phy-id004d.d0c0
+
+ then:
+ properties:
+ reg:
+ const: 7 # This PHY is always at MDIO address 7 in the IPQ5018 SoC
+
+ resets:
+ items:
+ - description:
+ GE PHY MISC reset which triggers a reset across MDC, DSP, RX, and TX lines.
+
+ qcom,dac-preset-short-cable:
+ description:
+ Set if this phy is connected to another phy to adjust the values for
+ MDAC and EDAC to adjust amplitude, bias current settings, and error
+ detection and correction algorithm to accommodate for short cable length.
+ If not set, DAC values are not modified and it is assumed the MDI output pins
+ of this PHY are directly connected to an RJ45 connector.
+ type: boolean
properties:
+ compatible:
+ enum:
+ - ethernet-phy-id004d.d0c0
+
qca,clk-out-frequency:
description: Clock output frequency in Hertz.
$ref: /schemas/types.yaml#/definitions/uint32
@@ -132,3 +161,17 @@ examples:
};
};
};
+ - |
+ #include <dt-bindings/reset/qcom,gcc-ipq5018.h>
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ ge_phy: ethernet-phy@7 {
+ compatible = "ethernet-phy-id004d.d0c0";
+ reg = <7>;
+
+ resets = <&gcc GCC_GEPHY_MISC_ARES>;
+ };
+ };

View file

@ -1,38 +0,0 @@
From 19e00bdfbb1b5f7a2d1f3c1c38b3da25e17ea486 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 8 Jun 2026 09:09:16 +0400
Subject: [PATCH] dt-bindings: net: ethernet-phy: increase max clock count to
two
The clocks property has a restriction to maximum one.
Yet, some PHYs may require more than 1 clock such as the IPQ5018 PHY
which requires two clocks for RX and TX. As such, increase maxItems to
two.
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://patch.msgid.link/20260608-ipq5018-gephy-clocks-v4-1-fb2ccd56894b@outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
Documentation/devicetree/bindings/net/ethernet-phy.yaml | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
--- a/Documentation/devicetree/bindings/net/ethernet-phy.yaml
+++ b/Documentation/devicetree/bindings/net/ethernet-phy.yaml
@@ -102,10 +102,13 @@ properties:
by software.
clocks:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
description:
- External clock connected to the PHY. If not specified it is assumed
- that the PHY uses a fixed crystal or an internal oscillator.
+ External clock connected to the PHY or RX and TX clocks that the PHY
+ requires to enable explicitly. If not specified it is assumed
+ that the PHY uses a fixed crystal or an internal oscillator or that the
+ RX/TX clocks are hardware enabled by default.
enet-phy-lane-swap:
$ref: /schemas/types.yaml#/definitions/flag

View file

@ -1,66 +0,0 @@
From fea4ae4b5b5059612d1a4f5acb88c27a5f7e60dc Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 8 Jun 2026 09:09:17 +0400
Subject: [PATCH] dt-bindings: net: qca,ar803x: Add clocks for IPQ5018 PHY
Further testing revealed that the RX and TX clocks of the IPQ5018 PHY
need to be explicitly enabled. As such, add the required clocks to the
schema.
Acked-by: Conor Dooley <conor.dooley@microchip.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://patch.msgid.link/20260608-ipq5018-gephy-clocks-v4-2-fb2ccd56894b@outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
.../devicetree/bindings/net/qca,ar803x.yaml | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
--- a/Documentation/devicetree/bindings/net/qca,ar803x.yaml
+++ b/Documentation/devicetree/bindings/net/qca,ar803x.yaml
@@ -28,6 +28,16 @@ allOf:
reg:
const: 7 # This PHY is always at MDIO address 7 in the IPQ5018 SoC
+ clocks:
+ items:
+ - description: RX clock
+ - description: TX clock
+
+ clock-names:
+ items:
+ - const: rx
+ - const: tx
+
resets:
items:
- description:
@@ -42,6 +52,11 @@ allOf:
of this PHY are directly connected to an RJ45 connector.
type: boolean
+ required:
+ - clocks
+ - clock-names
+ - resets
+
properties:
compatible:
enum:
@@ -162,6 +177,7 @@ examples:
};
};
- |
+ #include <dt-bindings/clock/qcom,gcc-ipq5018.h>
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
mdio {
@@ -172,6 +188,9 @@ examples:
compatible = "ethernet-phy-id004d.d0c0";
reg = <7>;
+ clocks = <&gcc GCC_GEPHY_RX_CLK>,
+ <&gcc GCC_GEPHY_TX_CLK>;
+ clock-names = "rx", "tx";
resets = <&gcc GCC_GEPHY_MISC_ARES>;
};
};

View file

@ -1,51 +0,0 @@
From cf6077e4903ffed2291f5f3cb9d61b29abe456c4 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 8 Jun 2026 09:09:19 +0400
Subject: [PATCH] net: phy: at803x: add RX and TX clock management for IPQ5018
PHY
Acquire and enable the RX and TX clocks for the IPQ5018 PHY.
These clocks are required for the PHY's datapath to function correctly.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://patch.msgid.link/20260608-ipq5018-gephy-clocks-v4-4-fb2ccd56894b@outlook.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
drivers/net/phy/qcom/at803x.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/net/phy/qcom/at803x.c
+++ b/drivers/net/phy/qcom/at803x.c
@@ -19,6 +19,7 @@
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/phylink.h>
+#include <linux/clk.h>
#include <linux/reset.h>
#include <linux/sfp.h>
#include <dt-bindings/net/qca-ar803x.h>
@@ -1089,6 +1090,7 @@ static void ipq5018_link_change_notify(s
static int ipq5018_probe(struct phy_device *phydev)
{
struct device *dev = &phydev->mdio.dev;
+ struct clk *rx_clk, *tx_clk;
struct ipq5018_priv *priv;
int ret;
@@ -1099,6 +1101,16 @@ static int ipq5018_probe(struct phy_devi
priv->set_short_cable_dac = of_property_read_bool(dev->of_node,
"qcom,dac-preset-short-cable");
+ rx_clk = devm_clk_get_enabled(dev, "rx");
+ if (IS_ERR(rx_clk))
+ return dev_err_probe(dev, PTR_ERR(rx_clk),
+ "failed to get and enable RX clock\n");
+
+ tx_clk = devm_clk_get_enabled(dev, "tx");
+ if (IS_ERR(tx_clk))
+ return dev_err_probe(dev, PTR_ERR(tx_clk),
+ "failed to get and enable TX clock\n");
+
priv->rst = devm_reset_control_array_get_exclusive(dev);
if (IS_ERR(priv->rst))
return dev_err_probe(dev, PTR_ERR(priv->rst),

View file

@ -1,30 +0,0 @@
From 20959cefc27e7e2e506b4e789b728e5702c77f95 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 8 Jun 2026 09:09:18 +0400
Subject: arm64: qcom: ipq5018: Add GEPHY RX and TX clocks
Add RX and TX clocks for the IPQ5018 GEPHY to enable the datapath.
Fixes: f5f2b835e316 ("arm64: dts: qcom: ipq5018: Add GE PHY to internal mdio bus")
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Link: https://lore.kernel.org/r/20260608-ipq5018-gephy-clocks-v4-3-fb2ccd56894b@outlook.com
Signed-off-by: Bjorn Andersson <andersson@kernel.org>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 3 +++
1 file changed, 3 insertions(+)
(limited to 'arch/arm64/boot/dts/qcom/ipq5018.dtsi')
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -229,6 +229,9 @@
compatible = "ethernet-phy-id004d.d0c0";
reg = <7>;
+ clocks = <&gcc GCC_GEPHY_RX_CLK>,
+ <&gcc GCC_GEPHY_TX_CLK>;
+ clock-names = "rx", "tx";
resets = <&gcc GCC_GEPHY_MISC_ARES>;
};
};

View file

@ -1,60 +0,0 @@
From ad2d07f71739351eeea1d8a120c0918e2c4b265f Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 22 Dec 2021 12:23:34 +0100
Subject: [PATCH] arm64: dts: ipq8074: add reserved memory nodes
IPQ8074 has multiple reserved memory ranges, if they are not defined
then weird things tend to happen, board hangs and resets when PCI or
WLAN is used etc.
So, to avoid all of that add the reserved memory nodes from the downstream
5.4 kernel from QCA.
This is their default layout meant for devices with 1GB of RAM, but
devices with lower ammounts can override the Q6 node.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 35 +++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -86,6 +86,16 @@
#size-cells = <2>;
ranges;
+ nss@40000000 {
+ no-map;
+ reg = <0x0 0x40000000 0x0 0x01000000>;
+ };
+
+ tzapp_region: tzapp@4a400000 {
+ no-map;
+ reg = <0x0 0x4a400000 0x0 0x00200000>;
+ };
+
bootloader@4a600000 {
reg = <0x0 0x4a600000 0x0 0x400000>;
no-map;
@@ -108,6 +118,21 @@
reg = <0x0 0x4ac00000 0x0 0x400000>;
no-map;
};
+
+ q6_region: wcnss@4b000000 {
+ no-map;
+ reg = <0x0 0x4b000000 0x0 0x05f00000>;
+ };
+
+ q6_etr_region: q6_etr_dump@50f00000 {
+ no-map;
+ reg = <0x0 0x50f00000 0x0 0x00100000>;
+ };
+
+ m3_dump_region: m3_dump@51000000 {
+ no-map;
+ reg = <0x0 0x51000000 0x0 0x100000>;
+ };
};
firmware {

View file

@ -1,43 +0,0 @@
From fb1f6850be00d8dd8a54017be4c1336e224069ac Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Wed, 16 Nov 2022 22:26:25 +0100
Subject: [PATCH] arm64: dts: qcom: ipq8074: use msi-parent for PCIe
Instead of hardcoding the IRQ, simply use msi-parent instead.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -759,7 +759,7 @@
reg = <0x0b000000 0x1000>, <0x0b002000 0x1000>;
ranges = <0 0xb00a000 0xffd>;
- v2m@0 {
+ gic_v2m0: v2m@0 {
compatible = "arm,gic-v2m-frame";
msi-controller;
reg = <0x0 0xffd>;
@@ -872,8 +872,7 @@
ranges = <0x81000000 0x0 0x00000000 0x10200000 0x0 0x10000>, /* I/O */
<0x82000000 0x0 0x10220000 0x10220000 0x0 0xfde0000>; /* MEM */
- interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ msi-parent = <&gic_v2m0>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc 0 0 142
@@ -944,8 +943,7 @@
ranges = <0x81000000 0x0 0x00000000 0x20200000 0x0 0x10000>, /* I/O */
<0x82000000 0x0 0x20220000 0x20220000 0x0 0xfde0000>; /* MEM */
- interrupts = <GIC_SPI 52 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "msi";
+ msi-parent = <&gic_v2m0>;
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0x7>;
interrupt-map = <0 0 0 1 &intc 0 0 75

View file

@ -1,155 +0,0 @@
From 125681433c8e526356947acf572fe8ca8ad32291 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:05 +0530
Subject: [PATCH] remoteproc: qcom: Add PRNG proxy clock
PRNG clock is needed by the secure PIL, support for the same
is added in subsequent patches.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 65 +++++++++++++++++++++--------
1 file changed, 47 insertions(+), 18 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -91,19 +91,6 @@ enum {
WCSS_QCS404,
};
-struct wcss_data {
- const char *firmware_name;
- unsigned int crash_reason_smem;
- u32 version;
- bool aon_reset_required;
- bool wcss_q6_reset_required;
- const char *ssr_name;
- const char *sysmon_name;
- int ssctl_id;
- const struct rproc_ops *ops;
- bool requires_force_stop;
-};
-
struct q6v5_wcss {
struct device *dev;
@@ -128,6 +115,7 @@ struct q6v5_wcss {
struct clk *qdsp6ss_xo_cbcr;
struct clk *qdsp6ss_core_gfmux;
struct clk *lcc_bcr_sleep;
+ struct clk *prng_clk;
struct regulator *cx_supply;
struct qcom_sysmon *sysmon;
@@ -152,6 +140,21 @@ struct q6v5_wcss {
struct qcom_rproc_ssr ssr_subdev;
};
+struct wcss_data {
+ int (*init_clock)(struct q6v5_wcss *wcss);
+ int (*init_regulator)(struct q6v5_wcss *wcss);
+ const char *firmware_name;
+ unsigned int crash_reason_smem;
+ u32 version;
+ bool aon_reset_required;
+ bool wcss_q6_reset_required;
+ const char *ssr_name;
+ const char *sysmon_name;
+ int ssctl_id;
+ const struct rproc_ops *ops;
+ bool requires_force_stop;
+};
+
static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
{
int ret;
@@ -241,6 +244,12 @@ static int q6v5_wcss_start(struct rproc
struct q6v5_wcss *wcss = rproc->priv;
int ret;
+ ret = clk_prepare_enable(wcss->prng_clk);
+ if (ret) {
+ dev_err(wcss->dev, "prng clock enable failed\n");
+ return ret;
+ }
+
qcom_q6v5_prepare(&wcss->q6v5);
/* Release Q6 and WCSS reset */
@@ -734,6 +743,7 @@ static int q6v5_wcss_stop(struct rproc *
return ret;
}
+ clk_disable_unprepare(wcss->prng_clk);
qcom_q6v5_unprepare(&wcss->q6v5);
return 0;
@@ -900,7 +910,21 @@ static int q6v5_alloc_memory_region(stru
return 0;
}
-static int q6v5_wcss_init_clock(struct q6v5_wcss *wcss)
+static int ipq8074_init_clock(struct q6v5_wcss *wcss)
+{
+ int ret;
+
+ wcss->prng_clk = devm_clk_get(wcss->dev, "prng");
+ if (IS_ERR(wcss->prng_clk)) {
+ ret = PTR_ERR(wcss->prng_clk);
+ if (ret != -EPROBE_DEFER)
+ dev_err(wcss->dev, "Failed to get prng clock\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int qcs404_init_clock(struct q6v5_wcss *wcss)
{
int ret;
@@ -990,7 +1014,7 @@ static int q6v5_wcss_init_clock(struct q
return 0;
}
-static int q6v5_wcss_init_regulator(struct q6v5_wcss *wcss)
+static int qcs404_init_regulator(struct q6v5_wcss *wcss)
{
wcss->cx_supply = devm_regulator_get(wcss->dev, "cx");
if (IS_ERR(wcss->cx_supply))
@@ -1034,12 +1058,14 @@ static int q6v5_wcss_probe(struct platfo
if (ret)
return ret;
- if (wcss->version == WCSS_QCS404) {
- ret = q6v5_wcss_init_clock(wcss);
+ if (desc->init_clock) {
+ ret = desc->init_clock(wcss);
if (ret)
return ret;
+ }
- ret = q6v5_wcss_init_regulator(wcss);
+ if (desc->init_regulator) {
+ ret = desc->init_regulator(wcss);
if (ret)
return ret;
}
@@ -1081,6 +1107,7 @@ static void q6v5_wcss_remove(struct plat
}
static const struct wcss_data wcss_ipq8074_res_init = {
+ .init_clock = ipq8074_init_clock,
.firmware_name = "IPQ8074/q6_fw.mdt",
.crash_reason_smem = WCSS_CRASH_REASON,
.aon_reset_required = true,
@@ -1090,6 +1117,8 @@ static const struct wcss_data wcss_ipq80
};
static const struct wcss_data wcss_qcs404_res_init = {
+ .init_clock = qcs404_init_clock,
+ .init_regulator = qcs404_init_regulator,
.crash_reason_smem = WCSS_CRASH_REASON,
.firmware_name = "wcnss.mdt",
.version = WCSS_QCS404,

View file

@ -1,143 +0,0 @@
From 7358d42dfbdfdb5d4f1d0d4c2e5c2bb4143a29b0 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:06 +0530
Subject: [PATCH] remoteproc: qcom: Add secure PIL support
IPQ8074 uses secure PIL. Hence, adding the support for the same.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 43 +++++++++++++++++++++++++++--
1 file changed, 40 insertions(+), 3 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -18,6 +18,7 @@
#include <linux/regulator/consumer.h>
#include <linux/reset.h>
#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/firmware/qcom/qcom_scm.h>
#include "qcom_common.h"
#include "qcom_pil_info.h"
#include "qcom_q6v5.h"
@@ -86,6 +87,9 @@
#define TCSR_WCSS_CLK_ENABLE 0x14
#define MAX_HALT_REG 4
+
+#define WCNSS_PAS_ID 6
+
enum {
WCSS_IPQ8074,
WCSS_QCS404,
@@ -134,6 +138,7 @@ struct q6v5_wcss {
unsigned int crash_reason_smem;
u32 version;
bool requires_force_stop;
+ bool need_mem_protection;
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_pdm pdm_subdev;
@@ -153,6 +158,7 @@ struct wcss_data {
int ssctl_id;
const struct rproc_ops *ops;
bool requires_force_stop;
+ bool need_mem_protection;
};
static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
@@ -252,6 +258,15 @@ static int q6v5_wcss_start(struct rproc
qcom_q6v5_prepare(&wcss->q6v5);
+ if (wcss->need_mem_protection) {
+ ret = qcom_scm_pas_auth_and_reset(WCNSS_PAS_ID);
+ if (ret) {
+ dev_err(wcss->dev, "wcss_reset failed\n");
+ return ret;
+ }
+ goto wait_for_reset;
+ }
+
/* Release Q6 and WCSS reset */
ret = reset_control_deassert(wcss->wcss_reset);
if (ret) {
@@ -286,6 +301,7 @@ static int q6v5_wcss_start(struct rproc
if (ret)
goto wcss_q6_reset;
+wait_for_reset:
ret = qcom_q6v5_wait_for_start(&wcss->q6v5, 5 * HZ);
if (ret == -ETIMEDOUT)
dev_err(wcss->dev, "start timed out\n");
@@ -719,6 +735,15 @@ static int q6v5_wcss_stop(struct rproc *
struct q6v5_wcss *wcss = rproc->priv;
int ret;
+ if (wcss->need_mem_protection) {
+ ret = qcom_scm_pas_shutdown(WCNSS_PAS_ID);
+ if (ret) {
+ dev_err(wcss->dev, "not able to shutdown\n");
+ return ret;
+ }
+ goto pas_done;
+ }
+
/* WCSS powerdown */
if (wcss->requires_force_stop) {
ret = qcom_q6v5_request_stop(&wcss->q6v5, NULL);
@@ -743,6 +768,7 @@ static int q6v5_wcss_stop(struct rproc *
return ret;
}
+pas_done:
clk_disable_unprepare(wcss->prng_clk);
qcom_q6v5_unprepare(&wcss->q6v5);
@@ -766,9 +792,15 @@ static int q6v5_wcss_load(struct rproc *
struct q6v5_wcss *wcss = rproc->priv;
int ret;
- ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware,
- 0, wcss->mem_region, wcss->mem_phys,
- wcss->mem_size, &wcss->mem_reloc);
+ if (wcss->need_mem_protection)
+ ret = qcom_mdt_load(wcss->dev, fw, rproc->firmware,
+ WCNSS_PAS_ID, wcss->mem_region,
+ wcss->mem_phys, wcss->mem_size,
+ &wcss->mem_reloc);
+ else
+ ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware,
+ 0, wcss->mem_region, wcss->mem_phys,
+ wcss->mem_size, &wcss->mem_reloc);
if (ret)
return ret;
@@ -1036,6 +1068,9 @@ static int q6v5_wcss_probe(struct platfo
if (!desc)
return -EINVAL;
+ if (desc->need_mem_protection && !qcom_scm_is_available())
+ return -EPROBE_DEFER;
+
rproc = devm_rproc_alloc(&pdev->dev, pdev->name, desc->ops,
desc->firmware_name, sizeof(*wcss));
if (!rproc) {
@@ -1049,6 +1084,7 @@ static int q6v5_wcss_probe(struct platfo
wcss->version = desc->version;
wcss->requires_force_stop = desc->requires_force_stop;
+ wcss->need_mem_protection = desc->need_mem_protection;
ret = q6v5_wcss_init_mmio(wcss, pdev);
if (ret)
@@ -1114,6 +1150,7 @@ static const struct wcss_data wcss_ipq80
.wcss_q6_reset_required = true,
.ops = &q6v5_wcss_ipq8074_ops,
.requires_force_stop = true,
+ .need_mem_protection = true,
};
static const struct wcss_data wcss_qcs404_res_init = {

View file

@ -1,103 +0,0 @@
From b422c9d4f048b086ce83f44a7cfcddcce162897f Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:07 +0530
Subject: [PATCH] remoteproc: qcom: Add support for split q6 + m3 wlan firmware
IPQ8074 supports split firmware for q6 and m3 as well.
So add support for loading the m3 firmware before q6.
Now the drivers works fine for both split and unified
firmwares.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 33 +++++++++++++++++++++++++----
1 file changed, 29 insertions(+), 4 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -139,6 +139,7 @@ struct q6v5_wcss {
u32 version;
bool requires_force_stop;
bool need_mem_protection;
+ const char *m3_firmware_name;
struct qcom_rproc_glink glink_subdev;
struct qcom_rproc_pdm pdm_subdev;
@@ -148,7 +149,8 @@ struct q6v5_wcss {
struct wcss_data {
int (*init_clock)(struct q6v5_wcss *wcss);
int (*init_regulator)(struct q6v5_wcss *wcss);
- const char *firmware_name;
+ const char *q6_firmware_name;
+ const char *m3_firmware_name;
unsigned int crash_reason_smem;
u32 version;
bool aon_reset_required;
@@ -790,8 +792,29 @@ static void *q6v5_wcss_da_to_va(struct r
static int q6v5_wcss_load(struct rproc *rproc, const struct firmware *fw)
{
struct q6v5_wcss *wcss = rproc->priv;
+ const struct firmware *m3_fw;
int ret;
+ if (wcss->m3_firmware_name) {
+ ret = request_firmware(&m3_fw, wcss->m3_firmware_name,
+ wcss->dev);
+ if (ret)
+ goto skip_m3;
+
+ ret = qcom_mdt_load_no_init(wcss->dev, m3_fw,
+ wcss->m3_firmware_name, 0,
+ wcss->mem_region, wcss->mem_phys,
+ wcss->mem_size, &wcss->mem_reloc);
+
+ release_firmware(m3_fw);
+
+ if (ret) {
+ dev_err(wcss->dev, "can't load m3_fw.bXX\n");
+ return ret;
+ }
+ }
+
+skip_m3:
if (wcss->need_mem_protection)
ret = qcom_mdt_load(wcss->dev, fw, rproc->firmware,
WCNSS_PAS_ID, wcss->mem_region,
@@ -1072,7 +1095,7 @@ static int q6v5_wcss_probe(struct platfo
return -EPROBE_DEFER;
rproc = devm_rproc_alloc(&pdev->dev, pdev->name, desc->ops,
- desc->firmware_name, sizeof(*wcss));
+ desc->q6_firmware_name, sizeof(*wcss));
if (!rproc) {
dev_err(&pdev->dev, "failed to allocate rproc\n");
return -ENOMEM;
@@ -1085,6 +1108,7 @@ static int q6v5_wcss_probe(struct platfo
wcss->version = desc->version;
wcss->requires_force_stop = desc->requires_force_stop;
wcss->need_mem_protection = desc->need_mem_protection;
+ wcss->m3_firmware_name = desc->m3_firmware_name;
ret = q6v5_wcss_init_mmio(wcss, pdev);
if (ret)
@@ -1144,7 +1168,8 @@ static void q6v5_wcss_remove(struct plat
static const struct wcss_data wcss_ipq8074_res_init = {
.init_clock = ipq8074_init_clock,
- .firmware_name = "IPQ8074/q6_fw.mdt",
+ .q6_firmware_name = "IPQ8074/q6_fw.mdt",
+ .m3_firmware_name = "IPQ8074/m3_fw.mdt",
.crash_reason_smem = WCSS_CRASH_REASON,
.aon_reset_required = true,
.wcss_q6_reset_required = true,
@@ -1157,7 +1182,7 @@ static const struct wcss_data wcss_qcs40
.init_clock = qcs404_init_clock,
.init_regulator = qcs404_init_regulator,
.crash_reason_smem = WCSS_CRASH_REASON,
- .firmware_name = "wcnss.mdt",
+ .q6_firmware_name = "wcnss.mdt",
.version = WCSS_QCS404,
.aon_reset_required = false,
.wcss_q6_reset_required = false,

View file

@ -1,24 +0,0 @@
From 3a8f67b4770c817b04794c9a02e3f88f85d86280 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:08 +0530
Subject: [PATCH] remoteproc: qcom: Add ssr subdevice identifier
Add name for ssr subdevice on IPQ8074 SoC.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -1173,6 +1173,7 @@ static const struct wcss_data wcss_ipq80
.crash_reason_smem = WCSS_CRASH_REASON,
.aon_reset_required = true,
.wcss_q6_reset_required = true,
+ .ssr_name = "q6wcss",
.ops = &q6v5_wcss_ipq8074_ops,
.requires_force_stop = true,
.need_mem_protection = true,

View file

@ -1,57 +0,0 @@
From 8c73af6e8d78c66cfef0f551b00d375ec0b67ff3 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:09 +0530
Subject: [PATCH] remoteproc: qcom: Update regmap offsets for halt register
Fixed issue in reading halt-regs parameter from device-tree.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -155,6 +155,7 @@ struct wcss_data {
u32 version;
bool aon_reset_required;
bool wcss_q6_reset_required;
+ bool bcr_reset_required;
const char *ssr_name;
const char *sysmon_name;
int ssctl_id;
@@ -876,10 +877,13 @@ static int q6v5_wcss_init_reset(struct q
}
}
- wcss->wcss_q6_bcr_reset = devm_reset_control_get_exclusive(dev, "wcss_q6_bcr_reset");
- if (IS_ERR(wcss->wcss_q6_bcr_reset)) {
- dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n");
- return PTR_ERR(wcss->wcss_q6_bcr_reset);
+ if (desc->bcr_reset_required) {
+ wcss->wcss_q6_bcr_reset = devm_reset_control_get_exclusive(dev,
+ "wcss_q6_bcr_reset");
+ if (IS_ERR(wcss->wcss_q6_bcr_reset)) {
+ dev_err(wcss->dev, "unable to acquire wcss_q6_bcr_reset\n");
+ return PTR_ERR(wcss->wcss_q6_bcr_reset);
+ }
}
return 0;
@@ -1173,6 +1177,7 @@ static const struct wcss_data wcss_ipq80
.crash_reason_smem = WCSS_CRASH_REASON,
.aon_reset_required = true,
.wcss_q6_reset_required = true,
+ .bcr_reset_required = false,
.ssr_name = "q6wcss",
.ops = &q6v5_wcss_ipq8074_ops,
.requires_force_stop = true,
@@ -1187,6 +1192,7 @@ static const struct wcss_data wcss_qcs40
.version = WCSS_QCS404,
.aon_reset_required = false,
.wcss_q6_reset_required = false,
+ .bcr_reset_required = true,
.ssr_name = "mpss",
.sysmon_name = "wcnss",
.ssctl_id = 0x12,

View file

@ -1,26 +0,0 @@
From ff7c6533ed8c4de58ed6c8aab03ea59c03eb4f31 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:10 +0530
Subject: [PATCH] dt-bindings: clock: qcom: Add reset for WCSSAON
Add binding for WCSSAON reset required for Q6v5 reset on IPQ8074 SoC.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
Acked-by: Rob Herring <robh@kernel.org>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
include/dt-bindings/clock/qcom,gcc-ipq8074.h | 1 +
1 file changed, 1 insertion(+)
--- a/include/dt-bindings/clock/qcom,gcc-ipq8074.h
+++ b/include/dt-bindings/clock/qcom,gcc-ipq8074.h
@@ -381,6 +381,7 @@
#define GCC_NSSPORT4_RESET 143
#define GCC_NSSPORT5_RESET 144
#define GCC_NSSPORT6_RESET 145
+#define GCC_WCSSAON_RESET 146
#define USB0_GDSC 0
#define USB1_GDSC 1

View file

@ -1,25 +0,0 @@
From 43d9788f546d24df22d8ba3fcc2497d7ccc198f3 Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:11 +0530
Subject: [PATCH] clk: qcom: Add WCSSAON reset
Add WCSSAON reset required for Q6v5 on IPQ8074 SoC.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
Acked-by: Stephen Boyd <sboyd@kernel.org>
---
drivers/clk/qcom/gcc-ipq8074.c | 1 +
1 file changed, 1 insertion(+)
--- a/drivers/clk/qcom/gcc-ipq8074.c
+++ b/drivers/clk/qcom/gcc-ipq8074.c
@@ -4712,6 +4712,7 @@ static const struct qcom_reset_map gcc_i
[GCC_NSSPORT4_RESET] = { .reg = 0x68014, .bitmask = BIT(27) | GENMASK(9, 8) },
[GCC_NSSPORT5_RESET] = { .reg = 0x68014, .bitmask = BIT(28) | GENMASK(11, 10) },
[GCC_NSSPORT6_RESET] = { .reg = 0x68014, .bitmask = BIT(29) | GENMASK(13, 12) },
+ [GCC_WCSSAON_RESET] = { 0x59010, 0 },
};
static struct gdsc *gcc_ipq8074_gdscs[] = {

View file

@ -1,48 +0,0 @@
From 406a332fd1bcc4e18d73cce390f56272fe9111d7 Mon Sep 17 00:00:00 2001
From: Sivaprakash Murugesan <sivaprak@codeaurora.org>
Date: Fri, 17 Apr 2020 16:37:10 +0530
Subject: [PATCH] remoteproc: wcss: disable auto boot for IPQ8074
There is no need for remoteproc to boot automatically, ath11k will trigger
booting when its probing.
Signed-off-by: Sivaprakash Murugesan <sivaprak@codeaurora.org>
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 4 ++++
1 file changed, 4 insertions(+)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -162,6 +162,7 @@ struct wcss_data {
const struct rproc_ops *ops;
bool requires_force_stop;
bool need_mem_protection;
+ bool need_auto_boot;
};
static int q6v5_wcss_reset(struct q6v5_wcss *wcss)
@@ -1151,6 +1152,7 @@ static int q6v5_wcss_probe(struct platfo
desc->sysmon_name,
desc->ssctl_id);
+ rproc->auto_boot = desc->need_auto_boot;
ret = rproc_add(rproc);
if (ret)
return ret;
@@ -1182,6 +1184,7 @@ static const struct wcss_data wcss_ipq80
.ops = &q6v5_wcss_ipq8074_ops,
.requires_force_stop = true,
.need_mem_protection = true,
+ .need_auto_boot = false,
};
static const struct wcss_data wcss_qcs404_res_init = {
@@ -1198,6 +1201,7 @@ static const struct wcss_data wcss_qcs40
.ssctl_id = 0x12,
.ops = &q6v5_wcss_qcs404_ops,
.requires_force_stop = false,
+ .need_auto_boot = true,
};
static const struct of_device_id q6v5_wcss_of_match[] = {

View file

@ -1,120 +0,0 @@
From 7388400b8bd42f71d040dbf2fdbdcb834fcc0ede Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Sat, 30 Jan 2021 10:50:13 +0530
Subject: [PATCH] arm64: dts: qcom: Enable Q6v5 WCSS for ipq8074 SoC
Enable remoteproc WCSS PIL driver with glink and ssr subdevices.
Also enables smp2p and mailboxes required for IPC.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Signed-off-by: Sricharan R <sricharan@codeaurora.org>
Signed-off-by: Nikhil Prakash V <nprakash@codeaurora.org>
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 81 +++++++++++++++++++++++++++
1 file changed, 81 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -142,6 +142,32 @@
};
};
+ wcss: smp2p-wcss {
+ compatible = "qcom,smp2p";
+ qcom,smem = <435>, <428>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <0 322 1>;
+
+ mboxes = <&apcs_glb 9>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <1>;
+
+ wcss_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ qcom,smp2p-feature-ssr-ack;
+ #qcom,smem-state-cells = <1>;
+ };
+
+ wcss_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
+
soc: soc@0 {
#address-cells = <1>;
#size-cells = <1>;
@@ -415,6 +441,11 @@
reg = <0x01937000 0x21000>;
};
+ tcsr_q6: syscon@1945000 {
+ compatible = "syscon";
+ reg = <0x01945000 0xe000>;
+ };
+
spmi_bus: spmi@200f000 {
compatible = "qcom,spmi-pmic-arb";
reg = <0x0200f000 0x001000>,
@@ -994,6 +1025,56 @@
ranges;
};
};
+
+ q6v5_wcss: q6v5_wcss@cd00000 {
+ compatible = "qcom,ipq8074-wcss-pil";
+ reg = <0x0cd00000 0x4040>,
+ <0x004ab000 0x20>;
+ reg-names = "qdsp6",
+ "rmb";
+ qca,auto-restart;
+ qca,extended-intc;
+ interrupts-extended = <&intc 0 325 1>,
+ <&wcss_smp2p_in 0 0>,
+ <&wcss_smp2p_in 1 0>,
+ <&wcss_smp2p_in 2 0>,
+ <&wcss_smp2p_in 3 0>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ resets = <&gcc GCC_WCSSAON_RESET>,
+ <&gcc GCC_WCSS_BCR>,
+ <&gcc GCC_WCSS_Q6_BCR>;
+
+ reset-names = "wcss_aon_reset",
+ "wcss_reset",
+ "wcss_q6_reset";
+
+ clocks = <&gcc GCC_PRNG_AHB_CLK>;
+ clock-names = "prng";
+
+ qcom,halt-regs = <&tcsr_q6 0xa000 0xd000 0x0>;
+
+ qcom,smem-states = <&wcss_smp2p_out 0>,
+ <&wcss_smp2p_out 1>;
+ qcom,smem-state-names = "shutdown",
+ "stop";
+
+ memory-region = <&q6_region>;
+
+ glink-edge {
+ interrupts = <GIC_SPI 321 IRQ_TYPE_EDGE_RISING>;
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 8>;
+
+ rpm_requests {
+ qcom,glink-channels = "IPCRTR";
+ };
+ };
+ };
};
timer {

View file

@ -1,135 +0,0 @@
From a67d1901741c162645eda0dbdc3a2c0c2aff5cf4 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Tue, 21 Dec 2021 14:49:36 +0100
Subject: [PATCH] arm64: dts: ipq8074: Add WLAN node
IPQ8074 has a AHB based Q6v5 802.11ax radios that are supported
by the ath11k.
Add the required DT node to enable the built-in radios.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 111 ++++++++++++++++++++++++++
1 file changed, 111 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -1075,6 +1075,117 @@
};
};
};
+
+ wifi: wifi@c0000000 {
+ compatible = "qcom,ipq8074-wifi";
+ reg = <0xc000000 0x2000000>;
+
+ interrupts = <GIC_SPI 320 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 319 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 316 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 315 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 314 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 311 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 310 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 411 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 410 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 40 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 39 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 302 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 301 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 37 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 36 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 296 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 295 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 294 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 293 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 292 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 290 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 289 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 288 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 239 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 236 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 235 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 234 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 233 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 232 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 231 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 230 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 229 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 228 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 224 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 223 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 203 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 183 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 180 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 178 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 176 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 163 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 162 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 160 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 159 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 158 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 157 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>;
+
+ interrupt-names = "misc-pulse1",
+ "misc-latch",
+ "sw-exception",
+ "ce0",
+ "ce1",
+ "ce2",
+ "ce3",
+ "ce4",
+ "ce5",
+ "ce6",
+ "ce7",
+ "ce8",
+ "ce9",
+ "ce10",
+ "ce11",
+ "host2wbm-desc-feed",
+ "host2reo-re-injection",
+ "host2reo-command",
+ "host2rxdma-monitor-ring3",
+ "host2rxdma-monitor-ring2",
+ "host2rxdma-monitor-ring1",
+ "reo2ost-exception",
+ "wbm2host-rx-release",
+ "reo2host-status",
+ "reo2host-destination-ring4",
+ "reo2host-destination-ring3",
+ "reo2host-destination-ring2",
+ "reo2host-destination-ring1",
+ "rxdma2host-monitor-destination-mac3",
+ "rxdma2host-monitor-destination-mac2",
+ "rxdma2host-monitor-destination-mac1",
+ "ppdu-end-interrupts-mac3",
+ "ppdu-end-interrupts-mac2",
+ "ppdu-end-interrupts-mac1",
+ "rxdma2host-monitor-status-ring-mac3",
+ "rxdma2host-monitor-status-ring-mac2",
+ "rxdma2host-monitor-status-ring-mac1",
+ "host2rxdma-host-buf-ring-mac3",
+ "host2rxdma-host-buf-ring-mac2",
+ "host2rxdma-host-buf-ring-mac1",
+ "rxdma2host-destination-ring-mac3",
+ "rxdma2host-destination-ring-mac2",
+ "rxdma2host-destination-ring-mac1",
+ "host2tcl-input-ring4",
+ "host2tcl-input-ring3",
+ "host2tcl-input-ring2",
+ "host2tcl-input-ring1",
+ "wbm2host-tx-completions-ring3",
+ "wbm2host-tx-completions-ring2",
+ "wbm2host-tx-completions-ring1",
+ "tcl2host-status-ring";
+ qcom,rproc = <&q6v5_wcss>;
+ status = "disabled";
+ };
};
timer {

View file

@ -1,59 +0,0 @@
From cb3ef99c1553565e1dc0301ccd5c1c0fa2d15c15 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Fri, 31 Dec 2021 17:56:14 +0100
Subject: [PATCH] arm64: dts: ipq8074: add CPU clock
Now that CPU clock is exposed and can be controlled, add the necessary
properties to the CPU nodes.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 9 +++++++++
1 file changed, 9 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -5,6 +5,7 @@
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/qcom,gcc-ipq8074.h>
+#include <dt-bindings/clock/qcom,apss-ipq.h>
/ {
#address-cells = <2>;
@@ -38,6 +39,8 @@
reg = <0x0>;
next-level-cache = <&l2_0>;
enable-method = "psci";
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ clock-names = "cpu";
};
cpu1: cpu@1 {
@@ -46,6 +49,8 @@
enable-method = "psci";
reg = <0x1>;
next-level-cache = <&l2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ clock-names = "cpu";
};
cpu2: cpu@2 {
@@ -54,6 +59,8 @@
enable-method = "psci";
reg = <0x2>;
next-level-cache = <&l2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ clock-names = "cpu";
};
cpu3: cpu@3 {
@@ -62,6 +69,8 @@
enable-method = "psci";
reg = <0x3>;
next-level-cache = <&l2_0>;
+ clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
+ clock-names = "cpu";
};
l2_0: l2-cache {

View file

@ -1,48 +0,0 @@
From 347ca56e86c99021fad059b9a8ef101245b8507e Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Fri, 31 Dec 2021 20:38:06 +0100
Subject: [PATCH] arm64: dts: ipq8074: add cooling cells to CPU nodes
Since there is CPU Freq support as well as thermal sensor support
now for the IPQ8074, add cooling cells to CPU nodes so that they can
be used as cooling devices using CPU Freq.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 4 ++++
1 file changed, 4 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -41,6 +41,7 @@
enable-method = "psci";
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
+ #cooling-cells = <2>;
};
cpu1: cpu@1 {
@@ -51,6 +52,7 @@
next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
+ #cooling-cells = <2>;
};
cpu2: cpu@2 {
@@ -61,6 +63,7 @@
next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
+ #cooling-cells = <2>;
};
cpu3: cpu@3 {
@@ -71,6 +74,7 @@
next-level-cache = <&l2_0>;
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
+ #cooling-cells = <2>;
};
l2_0: l2-cache {

View file

@ -1,121 +0,0 @@
From 04d2fc6a551bbd972a6428059b45ce79cb9de9d7 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Fri, 6 May 2022 22:38:24 +0200
Subject: [PATCH] arm64: dts: qcom: ipq8074: add QFPROM fuses
Add the QFPROM node and CPR fuses.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 107 ++++++++++++++++++++++++++
1 file changed, 107 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -326,6 +326,106 @@
reg = <0x000a4000 0x2000>;
#address-cells = <1>;
#size-cells = <1>;
+
+ cpr_efuse_speedbin: speedbin@125 {
+ reg = <0x125 0x1>;
+ bits = <0 3>;
+ };
+
+ cpr_efuse_boost_cfg: boost_cfg@125 {
+ reg = <0x125 0x1>;
+ bits = <3 3>;
+ };
+
+ cpr_efuse_misc_volt_adj: misc_volt_adj@125 {
+ reg = <0x125 0x1>;
+ bits = <3 3>;
+ };
+
+ cpr_efuse_boost_volt: boost_volt@126 {
+ reg = <0x126 0x1>;
+ bits = <6 1>;
+ };
+
+ cpr_efuse_revision: revision@23e {
+ reg = <0x23e 0x1>;
+ bits = <5 3>;
+ };
+
+ cpr_efuse_ro_sel0: rosel0@249 {
+ reg = <0x249 0x1>;
+ bits = <0 4>;
+ };
+
+ cpr_efuse_ro_sel1: rosel1@248 {
+ reg = <0x248 0x1>;
+ bits = <4 4>;
+ };
+
+ cpr_efuse_ro_sel2: rosel2@248 {
+ reg = <0x248 0x2>;
+ bits = <0 4>;
+ };
+
+ cpr_efuse_ro_sel3: rosel3@249 {
+ reg = <0x249 0x1>;
+ bits = <4 4>;
+ };
+
+ cpr_efuse_init_voltage0: ivoltage0@23a {
+ reg = <0x23a 0x1>;
+ bits = <2 6>;
+ };
+
+ cpr_efuse_init_voltage1: ivoltage1@239 {
+ reg = <0x239 0x2>;
+ bits = <4 6>;
+ };
+
+ cpr_efuse_init_voltage2: ivoltage2@238 {
+ reg = <0x238 0x2>;
+ bits = <6 6>;
+ };
+
+ cpr_efuse_init_voltage3: ivoltage3@238 {
+ reg = <0x238 0x1>;
+ bits = <0 6>;
+ };
+
+ cpr_efuse_quot0: quot0@244 {
+ reg = <0x244 0x2>;
+ bits = <0 12>;
+ };
+
+ cpr_efuse_quot1: quot1@242 {
+ reg = <0x242 0x2>;
+ bits = <4 12>;
+ };
+
+ cpr_efuse_quot2: quot2@241 {
+ reg = <0x241 0x2>;
+ bits = <0 12>;
+ };
+
+ cpr_efuse_quot3: quot3@245 {
+ reg = <0x245 0x2>;
+ bits = <4 12>;
+ };
+
+ cpr_efuse_quot0_offset: quot0_offset@23d {
+ reg = <0x23d 0x2>;
+ bits = <6 7>;
+ };
+
+ cpr_efuse_quot1_offset: quot1_offset@23c {
+ reg = <0x23c 0x2>;
+ bits = <7 7>;
+ };
+
+ cpr_efuse_quot2_offset: quot2_offset@23c {
+ reg = <0x23c 0x1>;
+ bits = <0 7>;
+ };
};
prng: rng@e3000 {

View file

@ -1,102 +0,0 @@
From a20c4e8738a00087aa5d53fe5148ed484e23d229 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Sat, 31 Dec 2022 13:56:26 +0100
Subject: [PATCH] arm64: dts: qcom: ipq8074: add CPU OPP table
Now that there is NVMEM CPUFreq support for IPQ8074, we can add the OPP
table for SoC.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq8074.dtsi | 52 +++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq8074.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq8074.dtsi
@@ -42,6 +42,7 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
#cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
cpu1: cpu@1 {
@@ -53,6 +54,7 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
#cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
cpu2: cpu@2 {
@@ -64,6 +66,7 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
#cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
cpu3: cpu@3 {
@@ -75,6 +78,7 @@
clocks = <&apcs_glb APCS_ALIAS0_CORE_CLK>;
clock-names = "cpu";
#cooling-cells = <2>;
+ operating-points-v2 = <&cpu_opp_table>;
};
l2_0: l2-cache {
@@ -84,6 +88,54 @@
};
};
+ cpu_opp_table: opp-table {
+ compatible = "operating-points-v2-kryo-cpu";
+ nvmem-cells = <&cpr_efuse_speedbin>;
+ opp-shared;
+
+ opp-1017600000 {
+ opp-hz = /bits/ 64 <1017600000>;
+ opp-microvolt = <1>;
+ opp-supported-hw = <0xf>;
+ clock-latency-ns = <200000>;
+ };
+
+ opp-1382400000 {
+ opp-hz = /bits/ 64 <1382400000>;
+ opp-microvolt = <2>;
+ opp-supported-hw = <0xf>;
+ clock-latency-ns = <200000>;
+ };
+
+ opp-1651200000 {
+ opp-hz = /bits/ 64 <1651200000>;
+ opp-microvolt = <3>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <200000>;
+ };
+
+ opp-1843200000 {
+ opp-hz = /bits/ 64 <1843200000>;
+ opp-microvolt = <4>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <200000>;
+ };
+
+ opp-1920000000 {
+ opp-hz = /bits/ 64 <1920000000>;
+ opp-microvolt = <5>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <200000>;
+ };
+
+ opp-2208000000 {
+ opp-hz = /bits/ 64 <2208000000>;
+ opp-microvolt = <6>;
+ opp-supported-hw = <0x1>;
+ clock-latency-ns = <200000>;
+ };
+ };
+
pmu {
compatible = "arm,cortex-a53-pmu";
interrupts = <GIC_PPI 7 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;

View file

@ -1,27 +0,0 @@
From 7e102b1eb2ca3eff7a6f33ebeab17825e6f70956 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Mon, 4 Nov 2024 22:01:24 +0100
Subject: [PATCH] arm64: dts: qcom: ipq6018: add NSS reserved memory
It seems that despite NSS not being supported in OpenWrt the memory it
usually uses needs to be reserved anyway for stability reasons.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
arch/arm64/boot/dts/qcom/ipq6018.dtsi | 5 +++++
1 file changed, 5 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq6018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq6018.dtsi
@@ -194,6 +194,11 @@
no-map;
};
+ nss_region: memory@40000000 {
+ reg = <0x0 0x40000000 0x0 0x01000000>;
+ no-map;
+ };
+
bootloader@4a100000 {
reg = <0x0 0x4a100000 0x0 0x400000>;
no-map;

View file

@ -1,61 +0,0 @@
From 9dd19a9ae36bc60d58287d0c52e53024d484e64d Mon Sep 17 00:00:00 2001
From: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
Date: Fri, 29 Jan 2021 22:41:59 +0530
Subject: [PATCH 2/3] remoteproc: qcom: wcss: populate driver data for IPQ6018
Populate hardcoded param using driver data for IPQ6018 SoCs.
Signed-off-by: Gokul Sriram Palanisamy <gokulsri@codeaurora.org>
---
drivers/remoteproc/qcom_q6v5_wcss.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_wcss.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss.c
@@ -970,7 +970,7 @@ static int q6v5_alloc_memory_region(stru
return 0;
}
-static int ipq8074_init_clock(struct q6v5_wcss *wcss)
+static int ipq_init_clock(struct q6v5_wcss *wcss)
{
int ret;
@@ -1173,7 +1173,7 @@ static void q6v5_wcss_remove(struct plat
}
static const struct wcss_data wcss_ipq8074_res_init = {
- .init_clock = ipq8074_init_clock,
+ .init_clock = ipq_init_clock,
.q6_firmware_name = "IPQ8074/q6_fw.mdt",
.m3_firmware_name = "IPQ8074/m3_fw.mdt",
.crash_reason_smem = WCSS_CRASH_REASON,
@@ -1187,6 +1187,20 @@ static const struct wcss_data wcss_ipq80
.need_auto_boot = false,
};
+static const struct wcss_data wcss_ipq6018_res_init = {
+ .init_clock = ipq_init_clock,
+ .q6_firmware_name = "IPQ6018/q6_fw.mdt",
+ .m3_firmware_name = "IPQ6018/m3_fw.mdt",
+ .crash_reason_smem = WCSS_CRASH_REASON,
+ .aon_reset_required = true,
+ .wcss_q6_reset_required = true,
+ .bcr_reset_required = false,
+ .ssr_name = "q6wcss",
+ .ops = &q6v5_wcss_ipq8074_ops,
+ .requires_force_stop = true,
+ .need_mem_protection = true,
+};
+
static const struct wcss_data wcss_qcs404_res_init = {
.init_clock = qcs404_init_clock,
.init_regulator = qcs404_init_regulator,
@@ -1206,6 +1220,7 @@ static const struct wcss_data wcss_qcs40
static const struct of_device_id q6v5_wcss_of_match[] = {
{ .compatible = "qcom,ipq8074-wcss-pil", .data = &wcss_ipq8074_res_init },
+ { .compatible = "qcom,ipq6018-wcss-pil", .data = &wcss_ipq6018_res_init },
{ .compatible = "qcom,qcs404-wcss-pil", .data = &wcss_qcs404_res_init },
{ },
};

View file

@ -1,64 +0,0 @@
From 9d67219c941458fd26eb474d25f9a6b2525876ca Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Tue, 21 Oct 2025 15:38:28 +0400
Subject: [PATCH v6 1/8] firmware: qcom_scm: ipq5332: add support to pass metadata size
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <20251021-ipq5018-wifi-v6-1-c55c547df6fc@outlook.com>
IPQ5332 security software running under trustzone requires metadata size.
With new command support added in TrustZone that includes a size parameter,
pass metadata size as well.
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Signed-off-by: Gokul Sriram Palanisamy <gokul.sriram.p@oss.qualcomm.com>
---
drivers/firmware/qcom/qcom_scm.c | 17 +++++++++++++----
drivers/firmware/qcom/qcom_scm.h | 1 +
2 files changed, 14 insertions(+), 4 deletions(-)
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -583,9 +583,6 @@ int qcom_scm_pas_init_image(u32 peripher
int ret;
struct qcom_scm_desc desc = {
.svc = QCOM_SCM_SVC_PIL,
- .cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE,
- .arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW),
- .args[0] = peripheral,
.owner = ARM_SMCCC_OWNER_SIP,
};
struct qcom_scm_res res;
@@ -617,7 +614,19 @@ int qcom_scm_pas_init_image(u32 peripher
if (ret)
goto disable_clk;
- desc.args[1] = mdata_phys;
+ if (__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
+ QCOM_SCM_PIL_PAS_INIT_IMAGE_V2)) {
+ desc.cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE_V2;
+ desc.arginfo = QCOM_SCM_ARGS(3, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL);
+ desc.args[0] = peripheral;
+ desc.args[1] = mdata_phys;
+ desc.args[2] = size;
+ } else {
+ desc.cmd = QCOM_SCM_PIL_PAS_INIT_IMAGE;
+ desc.arginfo = QCOM_SCM_ARGS(2, QCOM_SCM_VAL, QCOM_SCM_RW);
+ desc.args[0] = peripheral;
+ desc.args[1] = mdata_phys;
+ }
ret = qcom_scm_call(__scm->dev, &desc, &res);
qcom_scm_bw_disable();
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -101,6 +101,7 @@ struct qcom_tzmem_pool *qcom_scm_get_tzm
#define QCOM_SCM_PIL_PAS_SHUTDOWN 0x06
#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
+#define QCOM_SCM_PIL_PAS_INIT_IMAGE_V2 0x1a
#define QCOM_SCM_SVC_IO 0x05
#define QCOM_SCM_IO_READ 0x01

View file

@ -1,157 +0,0 @@
From db128ef0282b8cc41816caf39a03fa17d10fa865 Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Tue, 21 Oct 2025 15:38:29 +0400
Subject: [PATCH v6 2/8] dt-bindings: remoteproc: qcom: document hexagon based WCSS secure PIL
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <20251021-ipq5018-wifi-v6-2-c55c547df6fc@outlook.com>
Add new binding document for hexagon based WCSS secure PIL remoteproc.
IPQ5018, IPQ5332, IPQ5424 and IPQ9574 follow secure PIL remoteproc.
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Signed-off-by: Gokul Sriram Palanisamy <quic_gokulsri@quicinc.com>
---
.../bindings/remoteproc/qcom,wcss-sec-pil.yaml | 133 +++++++++++++++++++++
1 file changed, 133 insertions(+)
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,wcss-sec-pil.yaml
@@ -0,0 +1,135 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/remoteproc/qcom,wcss-sec-pil.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm WCSS Secure Peripheral Image Loader
+
+maintainers:
+ - Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
+
+description:
+ Wireless Connectivity Subsystem (WCSS) Secure Peripheral Image Loader loads
+ firmware and power up QDSP6 remoteproc on the Qualcomm IPQ series SoC.
+
+properties:
+ compatible:
+ enum:
+ - qcom,ipq5018-wcss-sec-pil
+ - qcom,ipq5332-wcss-sec-pil
+ - qcom,ipq5424-wcss-sec-pil
+ - qcom,ipq9574-wcss-sec-pil
+
+ reg:
+ maxItems: 1
+
+ firmware-name:
+ maxItems: 1
+ description: Firmware name for the Hexagon core
+
+ interrupts:
+ items:
+ - description: Watchdog interrupt
+ - description: Fatal interrupt
+ - description: Ready interrupt
+ - description: Handover interrupt
+ - description: Stop acknowledge interrupt
+
+ interrupt-names:
+ items:
+ - const: wdog
+ - const: fatal
+ - const: ready
+ - const: handover
+ - const: stop-ack
+
+ clocks:
+ items:
+ - description: sleep clock
+ - description: AHB interconnect between system NOC and WCSS block
+
+ clock-names:
+ items:
+ - const: sleep
+ - const: interconnect
+
+ mboxes:
+ maxItems: 1
+ items:
+ - description: A phandle to the TMECom mailbox device node
+
+ qcom,smem-states:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: States used by the AP to signal the remote processor
+ items:
+ - description: Stop Q6
+ - description: Shutdown Q6
+
+ qcom,smem-state-names:
+ description:
+ Names of the states used by the AP to signal the remote processor
+ items:
+ - const: stop
+ - const: shutdown
+
+ memory-region:
+ items:
+ - description: Q6 reserved region
+
+ glink-edge:
+ $ref: /schemas/remoteproc/qcom,glink-edge.yaml#
+ description:
+ Qualcomm G-Link subnode which represents communication edge, channels
+ and devices related to the Modem.
+ unevaluatedProperties: false
+
+required:
+ - compatible
+ - reg
+ - firmware-name
+ - interrupts
+ - interrupt-names
+ - qcom,smem-states
+ - qcom,smem-state-names
+ - memory-region
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/clock/qcom,ipq5424-gcc.h>
+ remoteproc@d100000 {
+ compatible = "qcom,ipq5424-wcss-sec-pil";
+ reg = <0x0d100000 0x4040>;
+ firmware-name = "ath12k/IPQ5424/hw1.0/q6_fw0.mbn";
+ interrupts-extended = <&intc GIC_SPI 508 IRQ_TYPE_EDGE_RISING>,
+ <&wcss_smp2p_in 0 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 1 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 2 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 3 IRQ_TYPE_NONE>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ clocks = <&gcc GCC_IM_SLEEP_CLK>;
+ clock-names = "sleep";
+
+ mboxes = <&tmel_qmp 0>;
+ qcom,smem-states = <&wcss_smp2p_out 1>,
+ <&wcss_smp2p_out 0>;
+ qcom,smem-state-names = "stop",
+ "shutdown";
+
+ memory-region = <&q6_region>;
+
+ glink-edge {
+ interrupts = <GIC_SPI 500 IRQ_TYPE_EDGE_RISING>;
+ label = "rtr";
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 8>;
+ };
+ };

View file

@ -1,500 +0,0 @@
From 47d46157200bb5f67e540a87c67aab9cde62f8a4 Mon Sep 17 00:00:00 2001
From: Vignesh Viswanathan <vignesh.viswanathan@oss.qualcomm.com>
Date: Tue, 21 Oct 2025 15:38:30 +0400
Subject: [PATCH v6 3/8] remoteproc: qcom: add hexagon based WCSS secure PIL driver
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <20251021-ipq5018-wifi-v6-3-c55c547df6fc@outlook.com>
Add support to bring up hexagon based WCSS using secure PIL. All IPQxxxx
SoCs support secure Peripheral Image Loading (PIL).
Secure PIL image is signed firmware image which only trusted software such
as TrustZone (TZ) can authenticate and load. Linux kernel will send a
Peripheral Authentication Service (PAS) request to TZ to authenticate and
load the PIL images. This change also introduces secure firmware
authentication using Trusted Management Engine-Lite (TME-L) which is
supported on IPQ5424 SoC. This driver uses mailbox based PAS request to
TME-L for image authentication if supported, else it will fallback to use
SCM call based PAS request to TZ.
In order to avoid overloading the existing WCSS driver or PAS driver, we
came up with this new PAS based IPQ WCSS driver.
Signed-off-by: Vignesh Viswanathan <vignesh.viswanathan@oss.qualcomm.com>
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Signed-off-by: Gokul Sriram Palanisamy <gokul.sriram.p@oss.qualcomm.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/remoteproc/Kconfig | 19 ++
drivers/remoteproc/Makefile | 1 +
drivers/remoteproc/qcom_q6v5_wcss_sec.c | 390 ++++++++++++++++++++++++++++++++
include/linux/remoteproc.h | 2 +
4 files changed, 412 insertions(+)
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -255,6 +255,25 @@ config QCOM_Q6V5_WCSS
Hexagon V5 based WCSS remote processors on e.g. IPQ8074. This is
a non-TrustZone wireless subsystem.
+config QCOM_Q6V5_WCSS_SEC
+ tristate "Qualcomm Hexagon based WCSS Secure Peripheral Image Loader"
+ depends on OF && ARCH_QCOM
+ depends on QCOM_SMEM
+ depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ select QCOM_MDT_LOADER
+ select QCOM_PIL_INFO
+ select QCOM_Q6V5_COMMON
+ select QCOM_RPROC_COMMON
+ select QCOM_SCM
+ help
+ Say y here to support the Qualcomm Secure Peripheral Image Loader
+ for the Hexagon based remote processors on e.g. IPQ5332.
+
+ This is TrustZone wireless subsystem. The firmware is
+ verified and booted with the help of the Peripheral Authentication
+ System (PAS) in TrustZone.
+
config QCOM_SYSMON
tristate "Qualcomm sysmon driver"
depends on RPMSG
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6
obj-$(CONFIG_QCOM_Q6V5_MSS) += qcom_q6v5_mss.o
obj-$(CONFIG_QCOM_Q6V5_PAS) += qcom_q6v5_pas.o
obj-$(CONFIG_QCOM_Q6V5_WCSS) += qcom_q6v5_wcss.o
+obj-$(CONFIG_QCOM_Q6V5_WCSS_SEC) += qcom_q6v5_wcss_sec.o
obj-$(CONFIG_QCOM_SYSMON) += qcom_sysmon.o
obj-$(CONFIG_QCOM_WCNSS_PIL) += qcom_wcnss_pil.o
qcom_wcnss_pil-y += qcom_wcnss.o
--- /dev/null
+++ b/drivers/remoteproc/qcom_q6v5_wcss_sec.c
@@ -0,0 +1,406 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Linaro Ltd.
+ * Copyright (C) 2014 Sony Mobile Communications AB
+ * Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2024-2025 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+#include <linux/clk.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/io.h>
+#include <linux/mailbox_client.h>
+#include <linux/mailbox/tmelcom-qmp.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/mdt_loader.h>
+
+#include "qcom_common.h"
+#include "qcom_q6v5.h"
+#include "qcom_pil_info.h"
+
+#define WCSS_CRASH_REASON 421
+
+#define WCSS_PAS_ID 0x6
+#define MPD_WCSS_PAS_ID 0xd
+
+#define Q6_WAIT_TIMEOUT (5 * HZ)
+
+struct wcss_sec {
+ struct device *dev;
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_q6v5 q6;
+ phys_addr_t mem_phys;
+ phys_addr_t mem_reloc;
+ void *mem_region;
+ size_t mem_size;
+ const struct wcss_data *desc;
+
+ struct mbox_client mbox_client;
+ struct mbox_chan *mbox_chan;
+ void *metadata;
+ size_t metadata_len;
+};
+
+struct wcss_data {
+ u32 pasid;
+ const char *ss_name;
+ bool auto_boot;
+ bool use_tmelcom;
+};
+
+static int wcss_sec_start(struct rproc *rproc)
+{
+ struct wcss_sec *wcss = rproc->priv;
+ struct device *dev = wcss->dev;
+ int ret;
+
+ ret = qcom_q6v5_prepare(&wcss->q6);
+ if (ret)
+ return ret;
+
+ if (wcss->desc->use_tmelcom) {
+ struct tmel_sec_auth tsa;
+ struct tmel_qmp_msg tqm;
+
+ tsa.data = wcss->metadata;
+ tsa.size = wcss->metadata_len;
+ tsa.pas_id = wcss->desc->pasid;
+ tqm.msg = &tsa;
+ tqm.msg_id = TMEL_MSG_UID_SECBOOT_SEC_AUTH;
+
+ ret = mbox_send_message(wcss->mbox_chan, (void *)&tqm);
+ if (ret < 0) {
+ dev_err(dev, "Failed to send message via mailbox\n");
+ goto unprepare;
+ }
+ } else {
+ ret = qcom_scm_pas_auth_and_reset(wcss->desc->pasid);
+ if (ret) {
+ dev_err(dev, "wcss_reset failed\n");
+ goto unprepare;
+ }
+ }
+
+ ret = qcom_q6v5_wait_for_start(&wcss->q6, Q6_WAIT_TIMEOUT);
+ if (ret == -ETIMEDOUT)
+ dev_err(dev, "start timed out\n");
+
+unprepare:
+ qcom_q6v5_unprepare(&wcss->q6);
+
+ return ret;
+}
+
+static int wcss_sec_stop(struct rproc *rproc)
+{
+ struct wcss_sec *wcss = rproc->priv;
+ struct device *dev = wcss->dev;
+ int ret;
+
+ if (wcss->desc->use_tmelcom) {
+ struct tmel_sec_auth tsa = {0};
+ struct tmel_qmp_msg tqm;
+
+ tsa.pas_id = wcss->desc->pasid;
+ tqm.msg = &tsa;
+ tqm.msg_id = TMEL_MSG_UID_SECBOOT_SS_TEAR_DOWN;
+
+ mbox_send_message(wcss->mbox_chan, (void *)&tqm);
+ } else {
+ ret = qcom_scm_pas_shutdown(wcss->desc->pasid);
+ if (ret) {
+ dev_err(dev, "not able to shutdown\n");
+ return ret;
+ }
+ }
+
+ qcom_q6v5_unprepare(&wcss->q6);
+
+ return 0;
+}
+
+static void *wcss_sec_da_to_va(struct rproc *rproc, u64 da, size_t len,
+ bool *is_iomem)
+{
+ struct wcss_sec *wcss = rproc->priv;
+ int offset;
+
+ offset = da - wcss->mem_reloc;
+ if (offset < 0 || offset + len > wcss->mem_size)
+ return NULL;
+
+ return wcss->mem_region + offset;
+}
+
+static int wcss_sec_load(struct rproc *rproc, const struct firmware *fw)
+{
+ struct wcss_sec *wcss = rproc->priv;
+ struct device *dev = wcss->dev;
+ int ret;
+
+ if (wcss->desc->use_tmelcom) {
+ wcss->metadata = qcom_mdt_read_metadata(fw, &wcss->metadata_len,
+ rproc->firmware, wcss->dev);
+ if (IS_ERR(wcss->metadata)) {
+ ret = PTR_ERR(wcss->metadata);
+ dev_err(wcss->dev, "error %d reading firmware %s metadata\n",
+ ret, rproc->firmware);
+ return ret;
+ }
+
+ ret = qcom_mdt_load_no_init(wcss->dev, fw, rproc->firmware, wcss->desc->pasid,
+ wcss->mem_region, wcss->mem_phys, wcss->mem_size,
+ &wcss->mem_reloc);
+ if (ret) {
+ kfree(wcss->metadata);
+ return ret;
+ }
+ } else {
+ ret = qcom_mdt_load(dev, fw, rproc->firmware, wcss->desc->pasid, wcss->mem_region,
+ wcss->mem_phys, wcss->mem_size, &wcss->mem_reloc);
+ if (ret)
+ return ret;
+ }
+
+ qcom_pil_info_store("wcss", wcss->mem_phys, wcss->mem_size);
+
+ return 0;
+}
+
+static unsigned long wcss_sec_panic(struct rproc *rproc)
+{
+ struct wcss_sec *wcss = rproc->priv;
+
+ return qcom_q6v5_panic(&wcss->q6);
+}
+
+static void wcss_sec_copy_segment(struct rproc *rproc,
+ struct rproc_dump_segment *segment,
+ void *dest, size_t offset, size_t size)
+{
+ struct wcss_sec *wcss = rproc->priv;
+ struct device *dev = wcss->dev;
+
+ if (!segment->io_ptr)
+ segment->io_ptr = ioremap_wc(segment->da, segment->size);
+
+ if (!segment->io_ptr) {
+ dev_err(dev, "Failed to ioremap segment %pad size 0x%zx\n",
+ &segment->da, segment->size);
+ return;
+ }
+
+ if (offset + size < segment->size) {
+ memcpy(dest, segment->io_ptr + offset, size);
+ } else {
+ iounmap(segment->io_ptr);
+ segment->io_ptr = NULL;
+ }
+}
+
+static int wcss_sec_dump_segments(struct rproc *rproc,
+ const struct firmware *fw)
+{
+ struct device *dev = rproc->dev.parent;
+ struct reserved_mem *rmem = NULL;
+ struct device_node *node;
+ int num_segs, index;
+ int ret;
+
+ /*
+ * Parse through additional reserved memory regions for the rproc
+ * and add them to the coredump segments
+ */
+ num_segs = of_count_phandle_with_args(dev->of_node,
+ "memory-region", NULL);
+ for (index = 0; index < num_segs; index++) {
+ node = of_parse_phandle(dev->of_node,
+ "memory-region", index);
+ if (!node)
+ return -EINVAL;
+
+ rmem = of_reserved_mem_lookup(node);
+ of_node_put(node);
+ if (!rmem) {
+ dev_err(dev, "unable to acquire memory-region index %d num_segs %d\n",
+ index, num_segs);
+ return -EINVAL;
+ }
+
+ dev_dbg(dev, "Adding segment 0x%pa size 0x%pa",
+ &rmem->base, &rmem->size);
+ ret = rproc_coredump_add_custom_segment(rproc,
+ rmem->base,
+ rmem->size,
+ wcss_sec_copy_segment,
+ NULL);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct rproc_ops wcss_sec_ops = {
+ .start = wcss_sec_start,
+ .stop = wcss_sec_stop,
+ .da_to_va = wcss_sec_da_to_va,
+ .load = wcss_sec_load,
+ .get_boot_addr = rproc_elf_get_boot_addr,
+ .panic = wcss_sec_panic,
+ .parse_fw = wcss_sec_dump_segments,
+};
+
+static int wcss_sec_alloc_memory_region(struct wcss_sec *wcss)
+{
+ struct reserved_mem *rmem = NULL;
+ struct device_node *node;
+ struct device *dev = wcss->dev;
+
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (!node) {
+ dev_err(dev, "can't find phandle memory-region\n");
+ return -EINVAL;
+ }
+
+ rmem = of_reserved_mem_lookup(node);
+ of_node_put(node);
+
+ if (!rmem) {
+ dev_err(dev, "unable to acquire memory-region\n");
+ return -EINVAL;
+ }
+
+ wcss->mem_phys = rmem->base;
+ wcss->mem_reloc = rmem->base;
+ wcss->mem_size = rmem->size;
+ wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
+ if (!wcss->mem_region) {
+ dev_err(dev, "unable to map memory region: %pa+%pa\n",
+ &rmem->base, &rmem->size);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int wcss_sec_probe(struct platform_device *pdev)
+{
+ struct rproc *rproc;
+ struct wcss_sec *wcss;
+ struct clk *sleep_clk;
+ struct clk *int_clk;
+ const char *fw_name = NULL;
+ const struct wcss_data *desc = of_device_get_match_data(&pdev->dev);
+ int ret;
+
+ ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
+ &fw_name);
+ if (ret < 0)
+ return ret;
+
+ rproc = devm_rproc_alloc(&pdev->dev, desc->ss_name, &wcss_sec_ops,
+ fw_name, sizeof(*wcss));
+ if (!rproc) {
+ dev_err(&pdev->dev, "failed to allocate rproc\n");
+ return -ENOMEM;
+ }
+
+ wcss = rproc->priv;
+ wcss->dev = &pdev->dev;
+ wcss->desc = desc;
+
+ ret = wcss_sec_alloc_memory_region(wcss);
+ if (ret)
+ return ret;
+
+ sleep_clk = devm_clk_get_optional_enabled(&pdev->dev, "sleep");
+ if (IS_ERR(sleep_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(sleep_clk),
+ "Failed to get sleep clock\n");
+
+ int_clk = devm_clk_get_optional_enabled(&pdev->dev, "interconnect");
+ if (IS_ERR(int_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(int_clk),
+ "Failed to get interconnect clock\n");
+
+ ret = qcom_q6v5_init(&wcss->q6, pdev, rproc,
+ WCSS_CRASH_REASON, NULL, NULL);
+ if (ret)
+ return ret;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, desc->ss_name);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, desc->ss_name);
+
+ rproc->auto_boot = false;
+ rproc->dump_conf = RPROC_COREDUMP_INLINE;
+ rproc_coredump_set_elf_info(rproc, ELFCLASS32, EM_NONE);
+
+ if (desc->use_tmelcom) {
+ wcss->mbox_client.dev = wcss->dev;
+ wcss->mbox_client.knows_txdone = true;
+ wcss->mbox_client.tx_block = true;
+ wcss->mbox_chan = mbox_request_channel(&wcss->mbox_client, 0);
+ if (IS_ERR_OR_NULL(wcss->mbox_chan))
+ return dev_err_probe(wcss->dev, PTR_ERR(wcss->mbox_chan),
+ "mbox chan for IPC is missing\n");
+ }
+
+ ret = devm_rproc_add(&pdev->dev, rproc);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, rproc);
+
+ return 0;
+}
+
+static void wcss_sec_remove(struct platform_device *pdev)
+{
+ struct rproc *rproc = platform_get_drvdata(pdev);
+ struct wcss_sec *wcss = rproc->priv;
+
+ mbox_free_channel(wcss->mbox_chan);
+ qcom_remove_glink_subdev(rproc, &wcss->glink_subdev);
+ qcom_remove_ssr_subdev(rproc, &wcss->ssr_subdev);
+ qcom_q6v5_deinit(&wcss->q6);
+}
+
+static const struct wcss_data wcss_sec_ipq5332_res_init = {
+ .pasid = MPD_WCSS_PAS_ID,
+ .ss_name = "q6wcss",
+};
+
+static const struct wcss_data wcss_sec_ipq5424_res_init = {
+ .pasid = MPD_WCSS_PAS_ID,
+ .ss_name = "q6wcss",
+ .use_tmelcom = true,
+};
+
+static const struct wcss_data wcss_sec_ipq9574_res_init = {
+ .pasid = WCSS_PAS_ID,
+ .ss_name = "q6wcss",
+};
+
+static const struct of_device_id wcss_sec_of_match[] = {
+ { .compatible = "qcom,ipq5018-wcss-sec-pil", .data = &wcss_sec_ipq5332_res_init },
+ { .compatible = "qcom,ipq5332-wcss-sec-pil", .data = &wcss_sec_ipq5332_res_init },
+ { .compatible = "qcom,ipq5424-wcss-sec-pil", .data = &wcss_sec_ipq5424_res_init },
+ { .compatible = "qcom,ipq9574-wcss-sec-pil", .data = &wcss_sec_ipq9574_res_init },
+ { },
+};
+MODULE_DEVICE_TABLE(of, wcss_sec_of_match);
+
+static struct platform_driver wcss_sec_driver = {
+ .probe = wcss_sec_probe,
+ .remove = wcss_sec_remove,
+ .driver = {
+ .name = "qcom-wcss-secure-pil",
+ .of_match_table = wcss_sec_of_match,
+ },
+};
+module_platform_driver(wcss_sec_driver);
+
+MODULE_DESCRIPTION("Hexagon WCSS Secure Peripheral Image Loader");
+MODULE_LICENSE("GPL");
--- a/include/linux/remoteproc.h
+++ b/include/linux/remoteproc.h
@@ -472,6 +472,7 @@ enum rproc_dump_mechanism {
* @node: list node related to the rproc segment list
* @da: device address of the segment
* @size: size of the segment
+ * @io_ptr: ptr to store the ioremapped dump segment
* @priv: private data associated with the dump_segment
* @dump: custom dump function to fill device memory segment associated
* with coredump
@@ -483,6 +484,7 @@ struct rproc_dump_segment {
dma_addr_t da;
size_t size;
+ void *io_ptr;
void *priv;
void (*dump)(struct rproc *rproc, struct rproc_dump_segment *segment,
void *dest, size_t offset, size_t size);

View file

@ -1,101 +0,0 @@
From 553461c1f1ae9b2ac50bce5ed5de15092cc04d29 Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Tue, 21 Oct 2025 15:38:32 +0400
Subject: [PATCH v6 5/8] arm64: dts: qcom: ipq5018: add nodes to bringup q6
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <20251021-ipq5018-wifi-v6-5-c55c547df6fc@outlook.com>
Enable nodes required for q6 remoteproc bring up.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
arch/arm64/boot/dts/qcom/ipq5018.dtsi | 62 +++++++++++++++++++++++++++++++++++
1 file changed, 62 insertions(+)
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -158,6 +158,11 @@
reg = <0x0 0x4ac00000 0x0 0x200000>;
no-map;
};
+
+ q6_region: wcss@4b000000 {
+ reg = <0x0 0x4b000000 0x0 0x1b00000>;
+ no-map;
+ };
};
soc: soc@0 {
@@ -734,6 +739,41 @@
};
};
+ q6v5_wcss: remoteproc@cd00000 {
+ compatible = "qcom,ipq5018-wcss-sec-pil";
+ reg = <0x0cd00000 0x10000>;
+ firmware-name = "ath11k/IPQ5018/hw1.0/q6_fw.mbn";
+ interrupts-extended = <&intc GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
+ <&wcss_smp2p_in 0 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 1 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 2 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 3 IRQ_TYPE_NONE>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ clocks = <&gcc GCC_SLEEP_CLK_SRC>,
+ <&gcc GCC_SYS_NOC_WCSS_AHB_CLK>;
+ clock-names = "sleep",
+ "interconnect";
+
+ qcom,smem-states = <&wcss_smp2p_out 0>,
+ <&wcss_smp2p_out 1>;
+ qcom,smem-state-names = "shutdown",
+ "stop";
+
+ memory-region = <&q6_region>;
+
+ glink-edge {
+ interrupts = <GIC_SPI 179 IRQ_TYPE_EDGE_RISING>;
+ label = "rtr";
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 8>;
+ };
+ };
+
pcie1: pcie@80000000 {
compatible = "qcom,pcie-ipq5018";
reg = <0x80000000 0xf1d>,
@@ -1008,4 +1048,28 @@
<GIC_PPI 4 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 1 (GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
};
+
+ wcss: smp2p-wcss {
+ compatible = "qcom,smp2p";
+ qcom,smem = <435>, <428>;
+
+ interrupt-parent = <&intc>;
+ interrupts = <GIC_SPI 177 IRQ_TYPE_EDGE_RISING>;
+
+ mboxes = <&apcs_glb 9>;
+
+ qcom,local-pid = <0>;
+ qcom,remote-pid = <1>;
+
+ wcss_smp2p_out: master-kernel {
+ qcom,entry-name = "master-kernel";
+ #qcom,smem-state-cells = <1>;
+ };
+
+ wcss_smp2p_in: slave-kernel {
+ qcom,entry-name = "slave-kernel";
+ interrupt-controller;
+ #interrupt-cells = <2>;
+ };
+ };
};

View file

@ -1,65 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Subject: [PATCH] pinctrl: qcom: IPQ5018: update pwm groups
Date: Wed, 27 Nov 2024 09:14:11 +0400
GPIO 1, 30, and 46 are used to control PWM1, PWM3, and PWM0 respectively which
in turn drive the PWM led, so let's update the pwm# and pingroups accordingly.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/pinctrl/qcom/pinctrl-ipq5018.c
+++ b/drivers/pinctrl/qcom/pinctrl-ipq5018.c
@@ -541,7 +541,7 @@ static const char * const qdss_tracectl_
};
static const char * const pwm0_groups[] = {
- "gpio42",
+ "gpio42", "gpio46",
};
static const char * const qdss_cti_trig_out_b0_groups[] = {
@@ -549,7 +549,7 @@ static const char * const qdss_cti_trig_
};
static const char * const pwm1_groups[] = {
- "gpio43",
+ "gpio43", "gpio1",
};
static const char * const qdss_cti_trig_in_b0_groups[] = {
@@ -565,7 +565,7 @@ static const char * const qdss_cti_trig_
};
static const char * const pwm3_groups[] = {
- "gpio45",
+ "gpio45", "gpio30",
};
static const char * const qdss_cti_trig_in_b1_groups[] = {
@@ -679,7 +679,7 @@ static const struct pinfunction ipq5018_
static const struct msm_pingroup ipq5018_groups[] = {
PINGROUP(0, atest_char, _, qdss_cti_trig_out_a0, wci_txd, wci_rxd, xfem, _, _, _),
- PINGROUP(1, atest_char, _, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
+ PINGROUP(1, atest_char, pwm1, qdss_cti_trig_in_a0, wci_txd, wci_rxd, xfem, _, _, _),
PINGROUP(2, atest_char, _, qdss_cti_trig_out_a1, wci_txd, wci_rxd, xfem, _, _, _),
PINGROUP(3, atest_char, _, qdss_cti_trig_in_a1, wci_txd, wci_rxd, xfem, _, _, _),
PINGROUP(4, sdc1_data, qspi_data, blsp1_spi1, btss, dbg_out, qdss_traceclk_a, _, burn0, _),
@@ -708,7 +708,7 @@ static const struct msm_pingroup ipq5018
PINGROUP(27, audio_txmclk, wsa_swrm, audio_txmclk, blsp2_spi, btss, _, qdss_tracedata_b, _, _),
PINGROUP(28, audio_txbclk, wsa_swrm, blsp0_uart1, btss, qdss_tracedata_b, _, _, _, _),
PINGROUP(29, audio_txfsync, _, blsp0_uart1, _, qdss_tracedata_b, _, _, _, _),
- PINGROUP(30, audio_txd, led2, led0, _, _, _, _, _, _),
+ PINGROUP(30, audio_txd, led2, led0, pwm3, _, _, _, _, _),
PINGROUP(31, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
PINGROUP(32, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _, _),
PINGROUP(33, blsp2_i2c0, blsp2_spi0, blsp1_uart1, _, qdss_tracedata_b, eud_gpio, _, _, _),
@@ -724,7 +724,7 @@ static const struct msm_pingroup ipq5018
PINGROUP(43, pwm1, qdss_cti_trig_in_b0, wci_txd, wci_rxd, xfem, _, _, _, _),
PINGROUP(44, pwm2, qdss_cti_trig_out_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
PINGROUP(45, pwm3, qdss_cti_trig_in_b1, wci_txd, wci_rxd, xfem, _, _, _, _),
- PINGROUP(46, led0, _, _, _, _, _, _, _, _),
+ PINGROUP(46, led0, pwm0, _, _, _, _, _, _, _),
};
static const struct msm_pinctrl_soc_data ipq5018_pinctrl = {

View file

@ -1,47 +0,0 @@
From 8d8b37d3af2bdccf0a37d2017d876bfc6ce42552 Mon Sep 17 00:00:00 2001
From: Chukun Pan <amadeus@jmu.edu.cn>
Date: Fri, 20 Oct 2023 23:18:21 +0800
Subject: [PATCH 1/1] mtd: rawnand: add support for TH58NYG3S0HBAI4 NAND flash
The Toshiba TH58NYG3S0HBAI4 is detected with 128 byte OOB while the flash
has 256 bytes OOB. Since it is not an ONFI compliant NAND, the model name
cannot be read from anywhere, add a static NAND ID entry to correct this.
However, the NAND ID of this flash is inconsistent with the datasheet.
The actual NAND ID is only 4 ID bytes, the last ID byte is missing.
Datasheet available at (the ID table is on page 50):
https://europe.kioxia.com/content/dam/kioxia/newidr/productinfo/datasheet/201910/DST_TH58NYG3S0HBAI4-TDE_EN_31565.pdf
Datasheet NAND ID: {0x98, 0xa3, 0x91, 0x26, 0x76}
Actual NAND ID: {0x98, 0xa3, 0x91, 0x26}
It seems that this flash may be counterfeit, but another Toshiba flash
also has the same problem. Maybe the driver has a bug, or some Toshiba
nand flash is like this. Anyway, add a static NAND ID entry with only
4 ID bytes as a hack to make sure it works.
Tested on Arcadyan AW1000 flashed with OpenWrt.
Signed-off-by: Chukun Pan <amadeus@jmu.edu.cn>
With 0411-mtd-rawnand-qpic-only-support-max-4-bytes-ID.patch, we can
define 5 bytes ID here.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/mtd/nand/raw/nand_ids.c | 3 +++
1 file changed, 3 insertions(+)
--- a/drivers/mtd/nand/raw/nand_ids.c
+++ b/drivers/mtd/nand/raw/nand_ids.c
@@ -58,6 +58,9 @@ struct nand_flash_dev nand_flash_ids[] =
{ .id = {0xad, 0xde, 0x14, 0xa7, 0x42, 0x4a} },
SZ_16K, SZ_8K, SZ_4M, NAND_NEED_SCRAMBLING, 6, 1664,
NAND_ECC_INFO(40, SZ_1K) },
+ {"TH58NYG3S0HBAI4 8G 1.8V 8-bit", /* Last ID bytes missing */
+ { .id = {0x98, 0xa3, 0x91, 0x26, 0x76} },
+ SZ_4K, SZ_1K, SZ_256K, 0, 5, 256, NAND_ECC_INFO(8, SZ_512) },
{"TH58NVG2S3HBAI4 4G 3.3V 8-bit",
{ .id = {0x98, 0xdc, 0x91, 0x15, 0x76} },
SZ_2K, SZ_512, SZ_128K, 0, 5, 128, NAND_ECC_INFO(8, SZ_512) },

View file

@ -1,46 +0,0 @@
From 2e1ab53e8fcf708db51f560f7846802d406ee57d Mon Sep 17 00:00:00 2001
From: George Moussalem <george.moussalem@outlook.com>
Date: Thu, 15 May 2025 22:47:43 +0200
Subject: [PATCH] spi: spi-qpic-snand: default to 4-bit ECC
There are NAND IC-s that define 1-bit ECC as the minimal strength,
however that is unsupported by QPIC-SNAND as it only supports 4 or 8 bit
ECC.
Since most of these chips also support 4-bit ECC just fine, instead of
erroring out if 1-bit ECC is requested lets instead default to 4-bit ECC.
Fixes: 01b72ce61e8f ("qualcommax: ipq50xx: remove ECC user config from board files")
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
drivers/spi/spi-qpic-snand.c | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
--- a/drivers/spi/spi-qpic-snand.c
+++ b/drivers/spi/spi-qpic-snand.c
@@ -304,6 +304,24 @@ static int qcom_spi_ecc_init_ctx_pipelin
ecc_cfg->spare_bytes = 2;
break;
+ case 1:
+ case 2:
+ /*
+ * Many chips have set a minimum ECC strength requirement
+ * lower than 4-bits but also support higher strength, so
+ * check if ecc_cfg was set by chip reqs and try 4-bits.
+ */
+ if (reqs->strength) {
+ dev_warn(snandc->dev,
+ "ECC strength requirement of %u-bit(s) is unsupported, trying 4-bits\n",
+ reqs->strength);
+ ecc_cfg->ecc_mode = ECC_MODE_4BIT;
+ ecc_cfg->ecc_bytes_hw = 7;
+ ecc_cfg->spare_bytes = 4;
+ break;
+ } else
+ fallthrough;
+
default:
dev_err(snandc->dev,
"only 4 or 8 bits ECC strength is supported\n");

View file

@ -1,25 +0,0 @@
From ce4d8b3c5e866a8c515608cf623990e1471a69c7 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Tue, 2 Dec 2025 22:02:30 +0800
Subject: [PATCH 1/2] mtd: rawnand: qpic only support max 4 bytes ID
QPIC use a reg (NAND_READ_ID) to transport the ID, so the max bytes of ID is a word (4Bytes).
https://github.com/torvalds/linux/blob/3a8660878839faadb4f1a6dd72c3179c1df56787/drivers/mtd/nand/raw/qcom_nandc.c#L1783
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/mtd/nand/raw/nand_base.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/nand/raw/nand_base.c
+++ b/drivers/mtd/nand/raw/nand_base.c
@@ -4965,7 +4965,7 @@ static bool find_full_id_nand(struct nan
memorg = nanddev_get_memorg(&chip->base);
- if (!strncmp(type->id, id_data, type->id_len)) {
+ if (!strncmp(type->id, id_data, min(4, type->id_len))) {
memorg->pagesize = type->pagesize;
mtd->writesize = memorg->pagesize;
memorg->pages_per_eraseblock = type->erasesize /

View file

@ -1,25 +0,0 @@
From cf5225a6e279995a574a5ed97cb227b5e076ed8e Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:11 +0800
Subject: [PATCH 2/2] mtd: spinand: qpic only support max 4 bytes ID
QPIC use a reg (NAND_READ_ID) to transport the ID, so the max bytes of ID is a word (4Bytes).
https://github.com/torvalds/linux/blob/4a26e7032d7d57c998598c08a034872d6f0d3945/drivers/spi/spi-qpic-snand.c#L1392-L1393
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/mtd/nand/spi/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
--- a/drivers/mtd/nand/spi/core.c
+++ b/drivers/mtd/nand/spi/core.c
@@ -1337,7 +1337,7 @@ int spinand_match_and_init(struct spinan
if (rdid_method != info->devid.method)
continue;
- if (memcmp(id + 1, info->devid.id, info->devid.len))
+ if (memcmp(id + 1, info->devid.id, min(3, info->devid.len)))
continue;
nand->memorg = table[i].memorg;

View file

@ -1,20 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 28 May 2025 08:37:28 +0400
Subject: [PATCH] arm64: dts: qcom: ipq5018: Add vendor compatible to mdio bus
QCA SSDK needs to register the MDIO bus in its driver. Without a proper reference,
it will crash. Since it tries to look up the MDIO bus using compatible strings that
aren't upstreamed, add the vendor compatible.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -219,7 +219,7 @@
};
mdio0: mdio@88000 {
- compatible = "qcom,ipq5018-mdio";
+ compatible = "qcom,ipq5018-mdio", "qcom,ipq40xx-mdio";
reg = <0x00088000 0x64>,
<0x019475c4 0x4>;
#address-cells = <1>;

View file

@ -1,35 +0,0 @@
From f71366e0530db2c5cecbbbb6edfbf7344bd6f83b Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH 1/2] clk: gcc-ipq5018: remove the unsupported clk
combination for gmac
Comment out the unsupported clock combination in the frequency table
for GMAC1.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/clk/qcom/gcc-ipq5018.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
--- a/drivers/clk/qcom/gcc-ipq5018.c
+++ b/drivers/clk/qcom/gcc-ipq5018.c
@@ -678,7 +678,7 @@ static const struct freq_tbl ftbl_gmac1_
F(2500000, P_UNIPHY_RX, 12.5, 0, 0),
F(24000000, P_XO, 1, 0, 0),
F(25000000, P_UNIPHY_RX, 2.5, 0, 0),
- F(125000000, P_UNIPHY_RX, 2.5, 0, 0),
+ /* F(125000000, P_UNIPHY_RX, 2.5, 0, 0), */
F(125000000, P_UNIPHY_RX, 1, 0, 0),
F(312500000, P_UNIPHY_RX, 1, 0, 0),
{ }
@@ -718,7 +718,7 @@ static const struct freq_tbl ftbl_gmac1_
F(2500000, P_UNIPHY_TX, 12.5, 0, 0),
F(24000000, P_XO, 1, 0, 0),
F(25000000, P_UNIPHY_TX, 2.5, 0, 0),
- F(125000000, P_UNIPHY_TX, 2.5, 0, 0),
+ /* F(125000000, P_UNIPHY_TX, 2.5, 0, 0), */
F(125000000, P_UNIPHY_TX, 1, 0, 0),
F(312500000, P_UNIPHY_TX, 1, 0, 0),
{ }

View file

@ -1,22 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Fri, 30 May 2025 09:12:23 +0400
Subject: [PATCH] clk: qcom: gcc-ipq5018: fix UNIPHY soft reset issue
The SOFT reset is supposed to trigger a resets across the SYS, RX, and
TX lines of the IPQ5018 UNIPHY. So let's set the bitmask of the reset
definition accordingly in the GCC as per the downstream driver.
Link: https://git.codelinaro.org/clo/qsdk/oss/kernel/linux-ipq-5.4/-/commit/036bdc62aca561e8ff94a29c447fc400de2b7304
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
--- a/drivers/clk/qcom/gcc-ipq5018.c
+++ b/drivers/clk/qcom/gcc-ipq5018.c
@@ -3648,7 +3648,7 @@ static const struct qcom_reset_map gcc_i
[GCC_UNIPHY_SYS_ARES] = { 0x56104, 1 },
[GCC_UNIPHY_RX_ARES] = { 0x56104, 4 },
[GCC_UNIPHY_TX_ARES] = { 0x56104, 5 },
- [GCC_UNIPHY_SOFT_RESET] = {0x56104, 0 },
+ [GCC_UNIPHY_SOFT_RESET] = {0x56104, .bitmask = 0x32 },
[GCC_USB0_BCR] = { 0x3e070, 0 },
[GCC_USB0_PHY_BCR] = { 0x3e034, 0 },
[GCC_WCSS_BCR] = { 0x18000, 0 },

View file

@ -1,36 +0,0 @@
From 54280bff5b17407e8b23cdeafdc63f4d43ad1ee5 Mon Sep 17 00:00:00 2001
From: Robert Marko <robimarko@gmail.com>
Date: Thu, 27 Nov 2025 13:49:06 +0100
Subject: [PATCH] net: phy: aquantia: enable USXGMII MAC autoneg
USXGMII MAC autoneg control bit is always set disabled by default, in order
for USXGMII to work properly we must enable it.
Signed-off-by: Robert Marko <robimarko@gmail.com>
---
drivers/net/phy/aquantia/aquantia_main.c | 7 +++++++
1 file changed, 7 insertions(+)
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -46,6 +46,9 @@
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
+#define MDIO_PHYXS_VEND_PROV2 0xc441
+#define MDIO_PHYXS_VEND_PROV2_USX_AUTONEG_MAC BIT(3)
+
#define MDIO_AN_VEND_PROV 0xc400
#define MDIO_AN_VEND_PROV_1000BASET_FULL BIT(15)
#define MDIO_AN_VEND_PROV_1000BASET_HALF BIT(14)
@@ -440,6 +443,10 @@ static int aqr107_read_status(struct phy
break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_USXGMII:
phydev->interface = PHY_INTERFACE_MODE_USXGMII;
+ phy_modify_mmd(phydev, MDIO_MMD_PHYXS,
+ MDIO_PHYXS_VEND_PROV2,
+ MDIO_PHYXS_VEND_PROV2_USX_AUTONEG_MAC,
+ MDIO_PHYXS_VEND_PROV2_USX_AUTONEG_MAC);
break;
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI:
phydev->interface = PHY_INTERFACE_MODE_XAUI;

View file

@ -1,202 +0,0 @@
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Fri, 10 Nov 2023 14:49:29 +0530
Subject: [PATCH] dt-bindings: remoteproc: qcom: Add support for multipd model
Add new binding document for multipd model remoteproc.
IPQ5332, IPQ9574 follows multipd model.
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
--- /dev/null
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,multipd-pil.yaml
@@ -0,0 +1,189 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/remoteproc/qcom,multipd-pil.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm Multipd Secure Peripheral Image Loader
+
+maintainers:
+ - Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
+
+description:
+ Multipd Peripheral Image Loader loads firmware and boots Q6 protection domain,
+ WCSS protection domain remoteproc's on the Qualcomm IPQ9574, IPQ5332 SoC.
+ Protection domain is similar to process in Linux. Here QDSP6 processor runs
+ each wifi radio functionality on a separate process. One process can't access
+ other process resources, so this is termed as PD i.e protection domain.
+
+properties:
+ compatible:
+ enum:
+ - qcom,ipq5332-q6-mpd
+ - qcom,ipq9574-q6-mpd
+
+ reg:
+ maxItems: 1
+
+ firmware-name:
+ maxItems: 2
+
+ interrupts:
+ items:
+ - description: Watchdog interrupt
+ - description: Fatal interrupt
+ - description: Ready interrupt
+ - description: Handover interrupt
+ - description: Stop acknowledge interrupt
+
+ interrupt-names:
+ items:
+ - const: wdog
+ - const: fatal
+ - const: ready
+ - const: handover
+ - const: stop-ack
+
+ qcom,smem-states:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: States used by the AP to signal the remote processor
+ items:
+ - description: Shutdown Q6
+ - description: Stop Q6
+
+ qcom,smem-state-names:
+ description:
+ Names of the states used by the AP to signal the remote processor
+ items:
+ - const: shutdown
+ - const: stop
+
+ memory-region:
+ items:
+ - description: Q6 reserved region
+
+ glink-edge:
+ $ref: /schemas/remoteproc/qcom,glink-edge.yaml#
+ description:
+ Qualcomm G-Link subnode which represents communication edge, channels
+ and devices related to the Modem.
+ unevaluatedProperties: false
+
+patternProperties:
+ "^pd-1|pd-2|pd-3":
+ type: object
+ description:
+ WCSS means 'wireless connectivity sub system', in simple words it's a
+ wifi radio block. In multipd model, Q6 root protection domain will
+ provide services to WCSS user protection domain. In other words WCSS
+ protection domains depends on Q6 protection domain i.e Q6 should be up
+ before WCSS, similarly Q6 should shut down after all WCSS domains are
+ down. It can be achieved by building parent-child topology between Q6
+ and WCSS domain's i.e keeping wcss node as sub node of Q6 device node.
+
+ properties:
+ firmware-name:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: Fatal interrupt
+ - description: Ready interrupt
+ - description: Spawn acknowledge interrupt
+ - description: Stop acknowledge interrupt
+
+ interrupt-names:
+ items:
+ - const: fatal
+ - const: ready
+ - const: spawn-ack
+ - const: stop-ack
+
+ qcom,smem-states:
+ $ref: /schemas/types.yaml#/definitions/phandle-array
+ description: States used by the AP to signal the remote processor
+ items:
+ - description: Shutdown WCSS pd
+ - description: Stop WCSS pd
+ - description: Spawn WCSS pd
+
+ qcom,smem-state-names:
+ description:
+ Names of the states used by the AP to signal the remote processor
+ items:
+ - const: shutdown
+ - const: stop
+ - const: spawn
+
+ required:
+ - firmware-name
+ - interrupts
+ - interrupt-names
+ - qcom,smem-states
+ - qcom,smem-state-names
+
+ additionalProperties: false
+
+required:
+ - compatible
+ - firmware-name
+ - reg
+ - interrupts
+ - interrupt-names
+ - qcom,smem-states
+ - qcom,smem-state-names
+ - memory-region
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ q6v5_wcss: remoteproc@d100000 {
+ compatible = "qcom,ipq5332-q6-mpd";
+ reg = <0xd100000 0x4040>;
+ firmware-name = "ath11k/IPQ5332/hw1.0/q6_fw0.mdt",
+ "ath11k/IPQ5332/hw1.0/iu_fw.mdt";
+ interrupts-extended = <&intc GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
+ <&wcss_smp2p_in 0 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 1 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 2 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 3 IRQ_TYPE_NONE>;
+ interrupt-names = "wdog",
+ "fatal",
+ "ready",
+ "handover",
+ "stop-ack";
+
+ qcom,smem-states = <&wcss_smp2p_out 0>,
+ <&wcss_smp2p_out 1>;
+ qcom,smem-state-names = "shutdown",
+ "stop";
+
+ memory-region = <&q6_region>;
+
+ glink-edge {
+ interrupts = <GIC_SPI 417 IRQ_TYPE_EDGE_RISING>;
+ label = "rtr";
+ qcom,remote-pid = <1>;
+ mboxes = <&apcs_glb 8>;
+ };
+
+ pd-1 {
+ firmware-name = "ath11k/IPQ5332/hw1.0/q6_fw1.mdt";
+ interrupts-extended = <&wcss_smp2p_in 8 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 9 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 12 IRQ_TYPE_NONE>,
+ <&wcss_smp2p_in 11 IRQ_TYPE_NONE>;
+ interrupt-names = "fatal",
+ "ready",
+ "spawn-ack",
+ "stop-ack";
+ qcom,smem-states = <&wcss_smp2p_out 8>,
+ <&wcss_smp2p_out 9>,
+ <&wcss_smp2p_out 10>;
+ qcom,smem-state-names = "shutdown",
+ "stop",
+ "spawn";
+ };
+ };

View file

@ -1,126 +0,0 @@
From 217fbbc122663c5a3dac752cebef44fb3e0cc179 Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Fri, 10 Nov 2023 14:49:35 +0530
Subject: [PATCH] firmware: qcom_scm: ipq5332: add msa lock/unlock
support
IPQ5332 user pd remoteproc firmwares need to be locked
with MSA(modem secure access) features. This patch add
support to lock/unlock MSA features.
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
---
drivers/firmware/qcom//qcom_scm.c | 78 ++++++++++++++++++++++++++
drivers/firmware/qcom//qcom_scm.h | 2 +
include/linux/firmware/qcom/qcom_scm.h | 2 +
3 files changed, 82 insertions(+)
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -79,6 +79,8 @@ int qcom_scm_pas_mem_setup(u32 periphera
int qcom_scm_pas_auth_and_reset(u32 peripheral);
int qcom_scm_pas_shutdown(u32 peripheral);
bool qcom_scm_pas_supported(u32 peripheral);
+int qcom_scm_msa_lock(u32 peripheral);
+int qcom_scm_msa_unlock(u32 peripheral);
int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val);
int qcom_scm_io_writel(phys_addr_t addr, unsigned int val);
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -807,6 +807,84 @@ bool qcom_scm_pas_supported(u32 peripher
}
EXPORT_SYMBOL_GPL(qcom_scm_pas_supported);
+/**
+ * qcom_scm_msa_lock() - Lock given peripheral firmware region as MSA
+ *
+ * @peripheral: peripheral id
+ *
+ * Return 0 on success.
+ */
+int qcom_scm_msa_lock(u32 peripheral)
+{
+ int ret;
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_MSA_LOCK,
+ .arginfo = QCOM_SCM_ARGS(1),
+ .args[0] = peripheral,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+
+ if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
+ QCOM_SCM_MSA_LOCK))
+ return 0;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = qcom_scm_bw_enable();
+ if (ret)
+ return ret;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+ qcom_scm_bw_disable();
+ qcom_scm_clk_disable();
+
+ return ret ? : res.result[0];
+}
+EXPORT_SYMBOL_GPL(qcom_scm_msa_lock);
+
+/**
+ * qcom_scm_msa_unlock() - Unlock given peripheral MSA firmware region
+ *
+ * @peripheral: peripheral id
+ *
+ * Return 0 on success.
+ */
+int qcom_scm_msa_unlock(u32 peripheral)
+{
+ int ret;
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_MSA_UNLOCK,
+ .arginfo = QCOM_SCM_ARGS(1),
+ .args[0] = peripheral,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+
+ if (!__qcom_scm_is_call_available(__scm->dev, QCOM_SCM_SVC_PIL,
+ QCOM_SCM_MSA_UNLOCK))
+ return 0;
+
+ ret = qcom_scm_clk_enable();
+ if (ret)
+ return ret;
+
+ ret = qcom_scm_bw_enable();
+ if (ret)
+ return ret;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+ qcom_scm_bw_disable();
+ qcom_scm_clk_disable();
+
+ return ret ? : res.result[0];
+}
+EXPORT_SYMBOL_GPL(qcom_scm_msa_unlock);
+
static int __qcom_scm_pas_mss_reset(struct device *dev, bool reset)
{
struct qcom_scm_desc desc = {
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -102,6 +102,8 @@ struct qcom_tzmem_pool *qcom_scm_get_tzm
#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
#define QCOM_SCM_PIL_PAS_INIT_IMAGE_V2 0x1a
+#define QCOM_SCM_MSA_LOCK 0x24
+#define QCOM_SCM_MSA_UNLOCK 0x25
#define QCOM_SCM_SVC_IO 0x05
#define QCOM_SCM_IO_READ 0x01

View file

@ -1,148 +0,0 @@
From cae691d32306966065df869fa7424728d1b16b14 Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Fri, 10 Nov 2023 14:49:36 +0530
Subject: [PATCH] remoteproc: qcom: q6v5: Add multipd interrupts support
In multipd model, root & user pd remoteproc's interrupts are
different. User pd needs additional interrupts like spawn.
Instead of going with qcom_q6v5_init(), we defined a new
function to register userpd rproc interrupts in mpd driver.
Since userpd rproc uses some of common interrupts like fatal,
ready, static is removed from ISR handler and used in userpd
interrupt registration.
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
---
drivers/remoteproc/qcom_q6v5.c | 41 +++++++++++++++++++++++++++++++---
drivers/remoteproc/qcom_q6v5.h | 11 +++++++++
2 files changed, 49 insertions(+), 3 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5.c
+++ b/drivers/remoteproc/qcom_q6v5.c
@@ -112,7 +112,7 @@ static irqreturn_t q6v5_wdog_interrupt(i
return IRQ_HANDLED;
}
-static irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
+irqreturn_t q6v5_fatal_interrupt(int irq, void *data)
{
struct qcom_q6v5 *q6v5 = data;
size_t len;
@@ -132,8 +132,9 @@ static irqreturn_t q6v5_fatal_interrupt(
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(q6v5_fatal_interrupt);
-static irqreturn_t q6v5_ready_interrupt(int irq, void *data)
+irqreturn_t q6v5_ready_interrupt(int irq, void *data)
{
struct qcom_q6v5 *q6v5 = data;
@@ -141,6 +142,7 @@ static irqreturn_t q6v5_ready_interrupt(
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(q6v5_ready_interrupt);
/**
* qcom_q6v5_wait_for_start() - wait for remote processor start signal
@@ -179,7 +181,17 @@ static irqreturn_t q6v5_handover_interru
return IRQ_HANDLED;
}
-static irqreturn_t q6v5_stop_interrupt(int irq, void *data)
+irqreturn_t q6v5_spawn_interrupt(int irq, void *data)
+{
+ struct qcom_q6v5 *q6v5 = data;
+
+ complete(&q6v5->spawn_done);
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(q6v5_spawn_interrupt);
+
+irqreturn_t q6v5_stop_interrupt(int irq, void *data)
{
struct qcom_q6v5 *q6v5 = data;
@@ -187,6 +199,7 @@ static irqreturn_t q6v5_stop_interrupt(i
return IRQ_HANDLED;
}
+EXPORT_SYMBOL_GPL(q6v5_stop_interrupt);
/**
* qcom_q6v5_request_stop() - request the remote processor to stop
@@ -217,6 +230,28 @@ int qcom_q6v5_request_stop(struct qcom_q
EXPORT_SYMBOL_GPL(qcom_q6v5_request_stop);
/**
+ * qcom_q6v5_request_spawn() - request the remote processor to spawn
+ * @q6v5: reference to qcom_q6v5 context
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int qcom_q6v5_request_spawn(struct qcom_q6v5 *q6v5)
+{
+ int ret;
+
+ ret = qcom_smem_state_update_bits(q6v5->spawn_state,
+ BIT(q6v5->spawn_bit), BIT(q6v5->spawn_bit));
+
+ ret = wait_for_completion_timeout(&q6v5->spawn_done, 5 * HZ);
+
+ qcom_smem_state_update_bits(q6v5->spawn_state,
+ BIT(q6v5->spawn_bit), 0);
+
+ return ret == 0 ? -ETIMEDOUT : 0;
+}
+EXPORT_SYMBOL_GPL(qcom_q6v5_request_spawn);
+
+/**
* qcom_q6v5_panic() - panic handler to invoke a stop on the remote
* @q6v5: reference to qcom_q6v5 context
*
--- a/drivers/remoteproc/qcom_q6v5.h
+++ b/drivers/remoteproc/qcom_q6v5.h
@@ -18,21 +18,27 @@ struct qcom_q6v5 {
struct qcom_smem_state *state;
struct qmp *qmp;
+ struct qcom_smem_state *shutdown_state;
+ struct qcom_smem_state *spawn_state;
struct icc_path *path;
unsigned stop_bit;
+ unsigned shutdown_bit;
+ unsigned spawn_bit;
int wdog_irq;
int fatal_irq;
int ready_irq;
int handover_irq;
int stop_irq;
+ int spawn_irq;
bool handover_issued;
struct completion start_done;
struct completion stop_done;
+ struct completion spawn_done;
int crash_reason;
@@ -50,7 +56,12 @@ void qcom_q6v5_deinit(struct qcom_q6v5 *
int qcom_q6v5_prepare(struct qcom_q6v5 *q6v5);
int qcom_q6v5_unprepare(struct qcom_q6v5 *q6v5);
int qcom_q6v5_request_stop(struct qcom_q6v5 *q6v5, struct qcom_sysmon *sysmon);
+int qcom_q6v5_request_spawn(struct qcom_q6v5 *q6v5);
int qcom_q6v5_wait_for_start(struct qcom_q6v5 *q6v5, int timeout);
unsigned long qcom_q6v5_panic(struct qcom_q6v5 *q6v5);
+irqreturn_t q6v5_fatal_interrupt(int irq, void *data);
+irqreturn_t q6v5_ready_interrupt(int irq, void *data);
+irqreturn_t q6v5_spawn_interrupt(int irq, void *data);
+irqreturn_t q6v5_stop_interrupt(int irq, void *data);
#endif

View file

@ -1,895 +0,0 @@
From 3f61ff1fb5c90f8b6c28a3a2b4a29203000ee585 Mon Sep 17 00:00:00 2001
From: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
Date: Fri, 10 Nov 2023 14:49:37 +0530
Subject: [PATCH] remoteproc: qcom: Add Hexagon based multipd rproc
driver
It adds support to bring up remoteproc's on multipd model.
Pd means protection domain. It's similar to process in Linux.
Here QDSP6 processor runs each wifi radio functionality on a
separate process. One process can't access other process
resources, so this is termed as PD i.e protection domain.
Here we have two pd's called root and user pd. We can correlate
Root pd as root and user pd as user in linux. Root pd has more
privileges than user pd. Root will provide services to user pd.
>From remoteproc driver perspective, root pd corresponds to QDSP6
processor bring up and user pd corresponds to Wifi radio (WCSS)
bring up.
Here WCSS(user) PD is dependent on Q6(root) PD, so first
q6 pd should be up before wcss pd. After wcss pd goes down,
q6 pd should be turned off.
APPS QDSP6
------- -------------
| | Crash notification | | ------
| |<---------------------|----------|-------|User|
| | | | |->|PD1 |
| | | ------- | | ------
| | | | | | |
|Root | Start/stop Q6 | | R | | |
|PD |<---------------------|->| | | |
|rproc| Crash notification | | O | | |
| | | | | | |
|User |Start/stop UserPD1 | | O | | |
|PD1 |----------------------|->| |-|----|
|rproc| | | T | | |
| | | | | | |
|User |Start/stop UserPD2 | | P | | |
|PD2 |----------------------|->| |-|----|
|rproc| | | D | | |
| | | ------- | | ------
| | Crash notification | | |->|User|
| |<---------------------|----------|-------|PD2 |
------- | | ------
------------
IPQ5332, IPQ9574 supports multipd remoteproc driver.
Signed-off-by: Manikanta Mylavarapu <quic_mmanikan@quicinc.com>
---
drivers/remoteproc/Kconfig | 19 +
drivers/remoteproc/Makefile | 1 +
drivers/remoteproc/qcom_q6v5_mpd.c | 802 +++++++++++++++++++++++++++++
3 files changed, 822 insertions(+)
create mode 100644 drivers/remoteproc/qcom_q6v5_mpd.c
--- a/drivers/remoteproc/Kconfig
+++ b/drivers/remoteproc/Kconfig
@@ -235,6 +235,25 @@ config QCOM_Q6V5_PAS
CDSP (Compute DSP), MPSS (Modem Peripheral SubSystem), and
SLPI (Sensor Low Power Island).
+config QCOM_Q6V5_MPD
+ tristate "Qualcomm Hexagon based MPD model Peripheral Image Loader"
+ depends on OF && ARCH_QCOM
+ depends on QCOM_SMEM
+ depends on RPMSG_QCOM_SMD || RPMSG_QCOM_SMD=n
+ depends on RPMSG_QCOM_GLINK_SMEM || RPMSG_QCOM_GLINK_SMEM=n
+ depends on QCOM_SYSMON || QCOM_SYSMON=n
+ depends on RPMSG_QCOM_GLINK || RPMSG_QCOM_GLINK=n
+ depends on QCOM_AOSS_QMP || QCOM_AOSS_QMP=n
+ select QCOM_MDT_LOADER
+ select QCOM_PIL_INFO
+ select QCOM_Q6V5_COMMON
+ select QCOM_RPROC_COMMON
+ select QCOM_SCM
+ help
+ Say y here to support the Qualcomm Secure Peripheral Image Loader
+ for the Hexagon based MultiPD model remote processors on e.g. IPQ5018.
+ This is trustZone wireless subsystem.
+
config QCOM_Q6V5_WCSS
tristate "Qualcomm Hexagon based WCSS Peripheral Image Loader"
depends on OF && ARCH_QCOM
--- a/drivers/remoteproc/Makefile
+++ b/drivers/remoteproc/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_QCOM_PIL_INFO) += qcom_pil
obj-$(CONFIG_QCOM_RPROC_COMMON) += qcom_common.o
obj-$(CONFIG_QCOM_Q6V5_COMMON) += qcom_q6v5.o
obj-$(CONFIG_QCOM_Q6V5_ADSP) += qcom_q6v5_adsp.o
+obj-$(CONFIG_QCOM_Q6V5_MPD) += qcom_q6v5_mpd.o
obj-$(CONFIG_QCOM_Q6V5_MSS) += qcom_q6v5_mss.o
obj-$(CONFIG_QCOM_Q6V5_PAS) += qcom_q6v5_pas.o
obj-$(CONFIG_QCOM_Q6V5_WCSS) += qcom_q6v5_wcss.o
--- /dev/null
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -0,0 +1,796 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2016-2018 Linaro Ltd.
+ * Copyright (C) 2014 Sony Mobile Communications AB
+ * Copyright (c) 2012-2018, 2021 The Linux Foundation. All rights reserved.
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/firmware/qcom/qcom_scm.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/soc/qcom/smem.h>
+#include <linux/soc/qcom/smem_state.h>
+#include "qcom_common.h"
+#include "qcom_q6v5.h"
+
+#include "remoteproc_internal.h"
+
+#define WCSS_CRASH_REASON 421
+#define WCSS_SMEM_HOST 1
+
+#define WCNSS_PAS_ID 6
+#define MPD_WCNSS_PAS_ID 0xD
+
+#define BUF_SIZE 35
+
+#define MAX_FIRMWARE 3
+
+#define RPD_SWID MPD_WCNSS_PAS_ID
+#define UPD_SWID 0x12
+#define REMOTE_PID 1
+#define UPD_BOOT_INFO_SMEM_SIZE 4096
+#define UPD_BOOT_INFO_HEADER_TYPE 0x2
+#define UPD_BOOT_INFO_SMEM_ID 507
+#define VERSION2 2
+
+static LIST_HEAD(upd_rproc_list);
+enum {
+ Q6_IPQ,
+ WCSS_IPQ,
+};
+
+/**
+ * struct userpd_boot_info_header - header of user pd bootinfo
+ * @type: type of bootinfo passing over smem
+ * @length: length of header in bytes
+ */
+struct userpd_boot_info_header {
+ u8 type;
+ u8 length;
+};
+
+/**
+ * struct userpd_boot_info - holds info required to boot user pd
+ * @header: pointer to header
+ * @pid: unique id represents each user pd process
+ * @bootaddr: load address of user pd firmware
+ * @data_size: user pd firmware memory size
+ */
+struct userpd_boot_info {
+ struct userpd_boot_info_header header;
+ u8 pid;
+ u32 bootaddr;
+ u32 data_size;
+} __packed;
+
+struct q6_wcss {
+ struct device *dev;
+ struct qcom_rproc_glink glink_subdev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_q6v5 q6;
+ phys_addr_t mem_phys;
+ phys_addr_t mem_reloc;
+ void *mem_region;
+ size_t mem_size;
+ u8 pd_asid;
+ const struct wcss_data *desc;
+ const char **firmware;
+ u32 version;
+};
+
+struct wcss_data {
+ u32 pasid;
+ bool share_upd_info_to_q6;
+};
+
+/**
+ * qcom_get_pd_asid() - get the pd asid number from PD spawn bit
+ * @rproc: rproc handle
+ *
+ * Returns asid on success
+ */
+static u8 qcom_get_pd_asid(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ u8 bit = wcss->q6.spawn_bit;
+
+ return bit / 8;
+}
+
+static int q6_wcss_start(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ int ret;
+ const struct wcss_data *desc = wcss->desc;
+
+ qcom_q6v5_prepare(&wcss->q6);
+
+ ret = qcom_scm_pas_auth_and_reset(desc->pasid);
+ if (ret) {
+ dev_err(wcss->dev, "wcss_reset failed\n");
+ return ret;
+ }
+
+ ret = qcom_q6v5_wait_for_start(&wcss->q6, 5 * HZ);
+ if (ret == -ETIMEDOUT)
+ dev_err(wcss->dev, "start timed out\n");
+
+ return ret;
+}
+
+static int q6_wcss_spawn_pd(struct rproc *rproc)
+{
+ int ret;
+ struct q6_wcss *wcss = rproc->priv;
+
+ ret = qcom_q6v5_request_spawn(&wcss->q6);
+ if (ret == -ETIMEDOUT) {
+ dev_err(wcss->dev, "%s spawn timedout\n", rproc->name);
+ return ret;
+ }
+
+ ret = qcom_q6v5_wait_for_start(&wcss->q6, msecs_to_jiffies(10000));
+ if (ret == -ETIMEDOUT) {
+ dev_err(wcss->dev, "%s start timedout\n", rproc->name);
+ wcss->q6.running = false;
+ return ret;
+ }
+ wcss->q6.running = true;
+ return ret;
+}
+
+static int wcss_pd_start(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
+ int ret;
+
+ ret = qcom_scm_msa_lock(pasid);
+ if (ret) {
+ dev_err(wcss->dev, "failed to power up pd\n");
+ return ret;
+ }
+
+ if (wcss->q6.spawn_bit) {
+ ret = q6_wcss_spawn_pd(rproc);
+ if (ret)
+ return ret;
+ }
+
+ return ret;
+}
+
+static int q6_wcss_stop(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ const struct wcss_data *desc = wcss->desc;
+ int ret;
+
+ ret = qcom_scm_pas_shutdown(desc->pasid);
+ if (ret) {
+ dev_err(wcss->dev, "not able to shutdown\n");
+ return ret;
+ }
+ qcom_q6v5_unprepare(&wcss->q6);
+
+ return 0;
+}
+
+/**
+ * wcss_pd_stop() - Stop WCSS user pd
+ * @rproc: rproc handle
+ *
+ * Stop root pd after user pd down. Root pd
+ * is used to provide services to user pd, so
+ * keeping root pd alive when user pd is down
+ * is invalid.
+ * ---------------------------------------------
+ *
+ * -----------
+ * |-------->| User PD1 |
+ * | -----------
+ * |
+ * |
+ * ----- | -----------
+ * | Q6 |---------------->| User Pd2 |
+ * ----- | -----------
+ * |
+ * |
+ * | -----------
+ * |--------->| User Pd3 |
+ * -----------
+ * ----------------------------------------------
+ */
+static int wcss_pd_stop(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
+ u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
+ int ret;
+
+ if (rproc->state != RPROC_CRASHED && wcss->q6.stop_bit) {
+ ret = qcom_q6v5_request_stop(&wcss->q6, NULL);
+ if (ret) {
+ dev_err(&rproc->dev, "pd not stopped\n");
+ return ret;
+ }
+ }
+
+ ret = qcom_scm_msa_unlock(pasid);
+ if (ret) {
+ dev_err(wcss->dev, "failed to power down pd\n");
+ return ret;
+ }
+
+ rproc_shutdown(rpd_rproc);
+
+ return 0;
+}
+
+static void *q6_wcss_da_to_va(struct rproc *rproc, u64 da, size_t len,
+ bool *is_iomem)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ int offset;
+
+ offset = da - wcss->mem_reloc;
+ if (offset < 0 || offset + len > wcss->mem_size)
+ return NULL;
+
+ return wcss->mem_region + offset;
+}
+
+/**
+ * share_upd_bootinfo_to_q6() - Share userpd boot info to Q6 root pd
+ * @rproc: rproc handle
+ *
+ * Q6 needs user pd parameters like loadaddress and
+ * PIL size to authenticate user pd with underlying
+ * security software. If authenticatoin success then
+ * only Q6 spawns user pd and sends spawn ack to rproc
+ * driver. This API is passing userpd boot info to Q6
+ * over SMEM.
+ *
+ * User pd boot-info format mentioned below
+ * <Version> <No of elements passing over smem> <Header type> <Header Length>
+ * <Process Id> <Load address> <firmware mem Size>
+ *
+ * Returns 0 on success else negative value on failure.
+ */
+static int share_upd_bootinfo_to_q6(struct rproc *rproc)
+{
+ int ret;
+ size_t size;
+ u16 cnt = 0, version;
+ void *ptr;
+ struct q6_wcss *wcss = rproc->priv, *upd_wcss;
+ struct rproc *upd_rproc;
+ struct userpd_boot_info upd_bootinfo = {0};
+ const struct firmware *fw;
+
+ ret = qcom_smem_alloc(REMOTE_PID, UPD_BOOT_INFO_SMEM_ID,
+ UPD_BOOT_INFO_SMEM_SIZE);
+ if (ret && ret != -EEXIST) {
+ dev_err(wcss->dev,
+ "failed to allocate q6 bootinfo smem segment\n");
+ return ret;
+ }
+
+ ptr = qcom_smem_get(REMOTE_PID, UPD_BOOT_INFO_SMEM_ID, &size);
+ if (IS_ERR(ptr) || size != UPD_BOOT_INFO_SMEM_SIZE) {
+ dev_err(wcss->dev,
+ "Unable to acquire smp2p item(%d) ret:%ld\n",
+ UPD_BOOT_INFO_SMEM_ID, PTR_ERR(ptr));
+ return PTR_ERR(ptr);
+ }
+
+ /*Version*/
+ version = VERSION2;
+ memcpy_toio(ptr, &version, sizeof(version));
+ ptr += sizeof(version);
+
+ list_for_each_entry(upd_rproc, &upd_rproc_list, node)
+ cnt++;
+
+ /* No of elements */
+ cnt = (sizeof(upd_bootinfo) * cnt);
+ memcpy_toio(ptr, &cnt, sizeof(u16));
+ ptr += sizeof(u16);
+
+ list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
+ upd_wcss = upd_rproc->priv;
+
+ /* TYPE */
+ upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
+
+ /* LENGTH */
+ upd_bootinfo.header.length =
+ sizeof(upd_bootinfo) - sizeof(upd_bootinfo.header);
+
+ /* Process ID */
+ upd_bootinfo.pid = upd_wcss->pd_asid + 1;
+
+ ret = request_firmware(&fw, upd_rproc->firmware, upd_wcss->dev);
+ if (ret < 0) {
+ dev_err(upd_wcss->dev, "request_firmware failed: %d\n", ret);
+ return ret;
+ }
+
+ /* Load address */
+ upd_bootinfo.bootaddr = rproc_get_boot_addr(upd_rproc, fw);
+
+ /* Firmware mem size */
+ upd_bootinfo.data_size = qcom_mdt_get_size(fw);
+
+ release_firmware(fw);
+
+ /* copy into smem */
+ memcpy_toio(ptr, &upd_bootinfo, sizeof(upd_bootinfo));
+ ptr += sizeof(upd_bootinfo);
+ }
+ return 0;
+}
+
+static int q6_wcss_load(struct rproc *rproc, const struct firmware *fw)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ const struct firmware *fw_hdl;
+ int ret;
+ const struct wcss_data *desc = wcss->desc;
+ int loop;
+
+ /* Share user pd boot info to Q6 remote processor */
+ if (desc->share_upd_info_to_q6) {
+ ret = share_upd_bootinfo_to_q6(rproc);
+ if (ret) {
+ dev_err(wcss->dev,
+ "user pd boot info sharing with q6 failed %d\n",
+ ret);
+ return ret;
+ }
+ }
+
+ ret = qcom_mdt_load(wcss->dev, fw, rproc->firmware,
+ desc->pasid, wcss->mem_region,
+ wcss->mem_phys, wcss->mem_size,
+ &wcss->mem_reloc);
+ if (ret)
+ return ret;
+
+ for (loop = 1; loop < MAX_FIRMWARE; loop++) {
+ if (!wcss->firmware[loop])
+ continue;
+
+ ret = request_firmware(&fw_hdl, wcss->firmware[loop],
+ wcss->dev);
+ if (ret)
+ continue;
+
+ ret = qcom_mdt_load_no_init(wcss->dev, fw_hdl,
+ wcss->firmware[loop], 0,
+ wcss->mem_region,
+ wcss->mem_phys,
+ wcss->mem_size,
+ &wcss->mem_reloc);
+
+ release_firmware(fw_hdl);
+
+ if (ret) {
+ dev_err(wcss->dev,
+ "can't load %s ret:%d\n", wcss->firmware[loop], ret);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+/**
+ * wcss_pd_load() - Load WCSS user pd firmware
+ * @rproc: rproc handle
+ * @fw: firmware handle
+ *
+ * User pd get services from root pd. So first
+ * bring up root pd and then load userpd firmware.
+ * ---------------------------------------------
+ *
+ * -----------
+ * |-------->| User PD1 |
+ * | -----------
+ * |
+ * |
+ * ----- | -----------
+ * | Q6 |---------------->| User Pd2 |
+ * ----- | -----------
+ * |
+ * |
+ * | -----------
+ * |--------->| User Pd3 |
+ * -----------
+ * ----------------------------------------------
+ *
+ */
+static int wcss_pd_load(struct rproc *rproc, const struct firmware *fw)
+{
+ struct q6_wcss *wcss = rproc->priv;
+ struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
+ u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
+ int ret;
+
+ ret = rproc_boot(rpd_rproc);
+ if (ret)
+ return ret;
+
+ return qcom_mdt_load(wcss->dev, fw, rproc->firmware,
+ pasid, wcss->mem_region,
+ wcss->mem_phys, wcss->mem_size,
+ &wcss->mem_reloc);
+}
+
+static unsigned long q6_wcss_panic(struct rproc *rproc)
+{
+ struct q6_wcss *wcss = rproc->priv;
+
+ return qcom_q6v5_panic(&wcss->q6);
+}
+
+static const struct rproc_ops wcss_ops = {
+ .start = wcss_pd_start,
+ .stop = wcss_pd_stop,
+ .load = wcss_pd_load,
+ .get_boot_addr = rproc_elf_get_boot_addr,
+};
+
+static const struct rproc_ops q6_wcss_ops = {
+ .start = q6_wcss_start,
+ .stop = q6_wcss_stop,
+ .da_to_va = q6_wcss_da_to_va,
+ .load = q6_wcss_load,
+ .get_boot_addr = rproc_elf_get_boot_addr,
+ .panic = q6_wcss_panic,
+};
+
+static int q6_alloc_memory_region(struct q6_wcss *wcss)
+{
+ struct reserved_mem *rmem = NULL;
+ struct device_node *node;
+ struct device *dev = wcss->dev;
+
+ if (wcss->version == Q6_IPQ) {
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (node)
+ rmem = of_reserved_mem_lookup(node);
+
+ of_node_put(node);
+
+ if (!rmem) {
+ dev_err(dev, "unable to acquire memory-region\n");
+ return -EINVAL;
+ }
+ } else {
+ struct rproc *rpd_rproc = dev_get_drvdata(dev->parent);
+ struct q6_wcss *rpd_wcss = rpd_rproc->priv;
+
+ wcss->mem_phys = rpd_wcss->mem_phys;
+ wcss->mem_reloc = rpd_wcss->mem_reloc;
+ wcss->mem_size = rpd_wcss->mem_size;
+ wcss->mem_region = rpd_wcss->mem_region;
+ return 0;
+ }
+
+ wcss->mem_phys = rmem->base;
+ wcss->mem_reloc = rmem->base;
+ wcss->mem_size = rmem->size;
+ wcss->mem_region = devm_ioremap_wc(dev, wcss->mem_phys, wcss->mem_size);
+ if (!wcss->mem_region) {
+ dev_err(dev, "unable to map memory region: %pa+%pa\n",
+ &rmem->base, &rmem->size);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+static int q6_get_inbound_irq(struct qcom_q6v5 *q6,
+ struct platform_device *pdev,
+ const char *int_name,
+ int index, int *pirq,
+ irqreturn_t (*handler)(int irq, void *data))
+{
+ int ret, irq;
+ char *interrupt, *tmp = (char *)int_name;
+ struct q6_wcss *wcss = q6->rproc->priv;
+
+ irq = platform_get_irq(pdev, index);
+ if (irq < 0)
+ return irq;
+
+ *pirq = irq;
+
+ interrupt = devm_kzalloc(&pdev->dev, BUF_SIZE, GFP_KERNEL);
+ if (!interrupt)
+ return -ENOMEM;
+
+ snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d_%s", wcss->pd_asid, tmp);
+
+ ret = devm_request_threaded_irq(&pdev->dev, *pirq,
+ NULL, handler,
+ IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+ interrupt, q6);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "failed to acquire %s irq\n", interrupt);
+ return 0;
+}
+
+static int q6_get_outbound_irq(struct qcom_q6v5 *q6,
+ struct platform_device *pdev,
+ const char *int_name)
+{
+ struct qcom_smem_state *tmp_state;
+ unsigned bit;
+
+ tmp_state = qcom_smem_state_get(&pdev->dev, int_name, &bit);
+ if (IS_ERR(tmp_state))
+ return dev_err_probe(&pdev->dev, PTR_ERR(tmp_state),
+ "failed to acquire %s state\n", int_name);
+
+ if (!strcmp(int_name, "stop")) {
+ q6->state = tmp_state;
+ q6->stop_bit = bit;
+ } else if (!strcmp(int_name, "spawn")) {
+ q6->spawn_state = tmp_state;
+ q6->spawn_bit = bit;
+ }
+
+ return 0;
+}
+
+static int init_irq(struct qcom_q6v5 *q6,
+ struct platform_device *pdev, struct rproc *rproc,
+ int crash_reason, const char *load_state,
+ void (*handover)(struct qcom_q6v5 *q6))
+{
+ int ret;
+ struct q6_wcss *wcss = rproc->priv;
+
+ q6->rproc = rproc;
+ q6->dev = &pdev->dev;
+ q6->crash_reason = crash_reason;
+ q6->handover = handover;
+
+ init_completion(&q6->start_done);
+ init_completion(&q6->stop_done);
+ init_completion(&q6->spawn_done);
+
+ ret = q6_get_outbound_irq(q6, pdev, "stop");
+ if (ret)
+ return ret;
+
+ ret = q6_get_outbound_irq(q6, pdev, "spawn");
+ if (ret)
+ return ret;
+
+ /* Get pd_asid to prepare interrupt names */
+ wcss->pd_asid = qcom_get_pd_asid(rproc);
+
+ ret = q6_get_inbound_irq(q6, pdev, "fatal", 0, &q6->fatal_irq,
+ q6v5_fatal_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_inbound_irq(q6, pdev, "ready", 1, &q6->ready_irq,
+ q6v5_ready_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_inbound_irq(q6, pdev, "stop-ack", 3, &q6->stop_irq,
+ q6v5_stop_interrupt);
+ if (ret)
+ return ret;
+
+ ret = q6_get_inbound_irq(q6, pdev, "spawn-ack", 2, &q6->spawn_irq,
+ q6v5_spawn_interrupt);
+ if (ret)
+ return ret;
+ return 0;
+}
+
+static void q6_release_resources(void)
+{
+ struct rproc *upd_rproc;
+
+ /* Release userpd resources */
+ list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
+ rproc_del(upd_rproc);
+ rproc_free(upd_rproc);
+ }
+}
+
+static int q6_register_userpd(struct platform_device *pdev,
+ struct device_node *userpd_np)
+{
+ struct q6_wcss *wcss;
+ struct rproc *rproc = NULL;
+ int ret;
+ struct platform_device *userpd_pdev;
+ const char *firmware_name = NULL;
+ const char *label = NULL;
+
+ ret = of_property_read_string(userpd_np, "firmware-name",
+ &firmware_name);
+ if (ret < 0) {
+ /* All userpd's who want to register as rproc must have firmware.
+ * Other than userpd like glink they don't need any firmware.
+ * So for glink child simply return success.
+ */
+ if (ret == -EINVAL) {
+ /* Confirming userpd_np is glink node or not */
+ if (!of_property_read_string(userpd_np, "label", &label))
+ return 0;
+ }
+ return ret;
+ }
+
+ dev_info(&pdev->dev, "%s node found\n", userpd_np->name);
+
+ userpd_pdev = of_platform_device_create(userpd_np, userpd_np->name,
+ &pdev->dev);
+ if (!userpd_pdev)
+ return dev_err_probe(&pdev->dev, -ENODEV,
+ "failed to create %s platform device\n",
+ userpd_np->name);
+
+ userpd_pdev->dev.driver = pdev->dev.driver;
+ rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
+ firmware_name, sizeof(*wcss));
+ if (!rproc) {
+ ret = -ENOMEM;
+ goto free_rproc;
+ }
+
+ wcss = rproc->priv;
+ wcss->dev = &userpd_pdev->dev;
+ wcss->version = WCSS_IPQ;
+
+ ret = q6_alloc_memory_region(wcss);
+ if (ret)
+ goto free_rproc;
+
+ ret = init_irq(&wcss->q6, userpd_pdev, rproc,
+ WCSS_CRASH_REASON, NULL, NULL);
+ if (ret)
+ goto free_rproc;
+
+ rproc->auto_boot = false;
+ ret = rproc_add(rproc);
+ if (ret)
+ goto free_rproc;
+
+ list_add(&rproc->node, &upd_rproc_list);
+ platform_set_drvdata(userpd_pdev, rproc);
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, userpd_pdev->name);
+ return 0;
+
+free_rproc:
+ kfree(rproc);
+ return ret;
+}
+
+static int q6_wcss_probe(struct platform_device *pdev)
+{
+ struct q6_wcss *wcss;
+ struct rproc *rproc;
+ int ret;
+ const char **firmware;
+ struct device_node *userpd_np;
+ const struct rproc_ops *ops = &q6_wcss_ops;
+
+ firmware = devm_kcalloc(&pdev->dev, MAX_FIRMWARE,
+ sizeof(*firmware), GFP_KERNEL);
+ if (!firmware)
+ return -ENOMEM;
+
+ ret = of_property_read_string_array(pdev->dev.of_node, "firmware-name",
+ firmware, MAX_FIRMWARE);
+ if (ret < 0)
+ return ret;
+
+ rproc = rproc_alloc(&pdev->dev, pdev->name, ops,
+ firmware[0], sizeof(*wcss));
+ if (!rproc)
+ return -ENOMEM;
+
+ wcss = rproc->priv;
+ wcss->dev = &pdev->dev;
+ wcss->desc = of_device_get_match_data(&pdev->dev);
+ wcss->firmware = firmware;
+ wcss->version = Q6_IPQ;
+
+ ret = q6_alloc_memory_region(wcss);
+ if (ret)
+ goto free_rproc;
+
+ ret = qcom_q6v5_init(&wcss->q6, pdev, rproc,
+ WCSS_CRASH_REASON, NULL, NULL);
+ if (ret)
+ goto free_rproc;
+
+ qcom_add_glink_subdev(rproc, &wcss->glink_subdev, "q6wcss");
+ qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, "q6wcss");
+
+ rproc->auto_boot = false;
+ ret = rproc_add(rproc);
+ if (ret)
+ goto free_rproc;
+
+ platform_set_drvdata(pdev, rproc);
+
+ /* Iterate over userpd child's and register with rproc */
+ for_each_available_child_of_node(pdev->dev.of_node, userpd_np) {
+ ret = q6_register_userpd(pdev, userpd_np);
+ if (ret) {
+ /* release resources of successfully allocated userpd rproc's */
+ q6_release_resources();
+ return dev_err_probe(&pdev->dev, ret,
+ "Failed to register userpd(%s)\n",
+ userpd_np->name);
+ }
+ }
+ return 0;
+
+free_rproc:
+ rproc_free(rproc);
+
+ return ret;
+}
+
+static void q6_wcss_remove(struct platform_device *pdev)
+{
+ struct rproc *rproc = platform_get_drvdata(pdev);
+ struct q6_wcss *wcss = rproc->priv;
+
+ qcom_q6v5_deinit(&wcss->q6);
+
+ rproc_del(rproc);
+ rproc_free(rproc);
+}
+
+static const struct wcss_data q6_ipq5332_res_init = {
+ .pasid = MPD_WCNSS_PAS_ID,
+ .share_upd_info_to_q6 = true,
+};
+
+static const struct wcss_data q6_ipq9574_res_init = {
+ .pasid = WCNSS_PAS_ID,
+};
+
+static const struct of_device_id q6_wcss_of_match[] = {
+ { .compatible = "qcom,ipq5332-q6-mpd", .data = &q6_ipq5332_res_init },
+ { .compatible = "qcom,ipq9574-q6-mpd", .data = &q6_ipq9574_res_init },
+ { },
+};
+MODULE_DEVICE_TABLE(of, q6_wcss_of_match);
+
+static struct platform_driver q6_wcss_driver = {
+ .probe = q6_wcss_probe,
+ .remove_new = q6_wcss_remove,
+ .driver = {
+ .name = "qcom-q6-mpd",
+ .of_match_table = q6_wcss_of_match,
+ },
+};
+module_platform_driver(q6_wcss_driver);
+
+MODULE_DESCRIPTION("Hexagon WCSS Multipd Peripheral Image Loader");
+MODULE_LICENSE("GPL v2");

View file

@ -1,321 +0,0 @@
From 6c66dff196cbba8515380110dd3599cde31dd896 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH 1/2] rproc: qcom_q6v5_mpd: split q6_wcss to rootpd and
userpd
Split the q6_wcss structure and create a separate userpd struct to clearly
differentiate between the process to bring up the QDSP6 processor vs
process(es) to bring up the Wifi radio(s) (WCSS) for better readability.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/remoteproc/qcom_q6v5_mpd.c | 126 +++++++++++++----------------
1 file changed, 56 insertions(+), 70 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -45,10 +45,6 @@
#define VERSION2 2
static LIST_HEAD(upd_rproc_list);
-enum {
- Q6_IPQ,
- WCSS_IPQ,
-};
/**
* struct userpd_boot_info_header - header of user pd bootinfo
@@ -83,10 +79,15 @@ struct q6_wcss {
phys_addr_t mem_reloc;
void *mem_region;
size_t mem_size;
- u8 pd_asid;
const struct wcss_data *desc;
const char **firmware;
- u32 version;
+};
+
+struct userpd {
+ u8 pd_asid;
+ struct device *dev;
+ struct qcom_rproc_ssr ssr_subdev;
+ struct qcom_q6v5 q6;
};
struct wcss_data {
@@ -102,8 +103,8 @@ struct wcss_data {
*/
static u8 qcom_get_pd_asid(struct rproc *rproc)
{
- struct q6_wcss *wcss = rproc->priv;
- u8 bit = wcss->q6.spawn_bit;
+ struct userpd *upd = rproc->priv;
+ u8 bit = upd->q6.spawn_bit;
return bit / 8;
}
@@ -132,37 +133,37 @@ static int q6_wcss_start(struct rproc *r
static int q6_wcss_spawn_pd(struct rproc *rproc)
{
int ret;
- struct q6_wcss *wcss = rproc->priv;
+ struct userpd *upd = rproc->priv;
- ret = qcom_q6v5_request_spawn(&wcss->q6);
+ ret = qcom_q6v5_request_spawn(&upd->q6);
if (ret == -ETIMEDOUT) {
- dev_err(wcss->dev, "%s spawn timedout\n", rproc->name);
+ dev_err(upd->dev, "%s spawn timedout\n", rproc->name);
return ret;
}
- ret = qcom_q6v5_wait_for_start(&wcss->q6, msecs_to_jiffies(10000));
+ ret = qcom_q6v5_wait_for_start(&upd->q6, msecs_to_jiffies(10000));
if (ret == -ETIMEDOUT) {
- dev_err(wcss->dev, "%s start timedout\n", rproc->name);
- wcss->q6.running = false;
+ dev_err(upd->dev, "%s start timedout\n", rproc->name);
+ upd->q6.running = false;
return ret;
}
- wcss->q6.running = true;
+ upd->q6.running = true;
return ret;
}
static int wcss_pd_start(struct rproc *rproc)
{
- struct q6_wcss *wcss = rproc->priv;
- u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
+ struct userpd *upd = rproc->priv;
+ u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
int ret;
ret = qcom_scm_msa_lock(pasid);
if (ret) {
- dev_err(wcss->dev, "failed to power up pd\n");
+ dev_err(upd->dev, "failed to power up pd\n");
return ret;
}
- if (wcss->q6.spawn_bit) {
+ if (upd->q6.spawn_bit) {
ret = q6_wcss_spawn_pd(rproc);
if (ret)
return ret;
@@ -214,22 +215,22 @@ static int q6_wcss_stop(struct rproc *rp
*/
static int wcss_pd_stop(struct rproc *rproc)
{
- struct q6_wcss *wcss = rproc->priv;
- struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
- u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
+ struct userpd *upd = rproc->priv;
+ struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
+ u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
int ret;
- if (rproc->state != RPROC_CRASHED && wcss->q6.stop_bit) {
- ret = qcom_q6v5_request_stop(&wcss->q6, NULL);
+ if (rproc->state != RPROC_CRASHED && upd->q6.stop_bit) {
+ ret = qcom_q6v5_request_stop(&upd->q6, NULL);
if (ret) {
- dev_err(&rproc->dev, "pd not stopped\n");
+ dev_err(upd->dev, "pd not stopped\n");
return ret;
}
}
ret = qcom_scm_msa_unlock(pasid);
if (ret) {
- dev_err(wcss->dev, "failed to power down pd\n");
+ dev_err(upd->dev, "failed to power down pd\n");
return ret;
}
@@ -274,7 +275,8 @@ static int share_upd_bootinfo_to_q6(stru
size_t size;
u16 cnt = 0, version;
void *ptr;
- struct q6_wcss *wcss = rproc->priv, *upd_wcss;
+ struct q6_wcss *wcss = rproc->priv;
+ struct userpd *upd;
struct rproc *upd_rproc;
struct userpd_boot_info upd_bootinfo = {0};
const struct firmware *fw;
@@ -309,7 +311,7 @@ static int share_upd_bootinfo_to_q6(stru
ptr += sizeof(u16);
list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
- upd_wcss = upd_rproc->priv;
+ upd = upd_rproc->priv;
/* TYPE */
upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
@@ -319,11 +321,11 @@ static int share_upd_bootinfo_to_q6(stru
sizeof(upd_bootinfo) - sizeof(upd_bootinfo.header);
/* Process ID */
- upd_bootinfo.pid = upd_wcss->pd_asid + 1;
+ upd_bootinfo.pid = upd->pd_asid + 1;
- ret = request_firmware(&fw, upd_rproc->firmware, upd_wcss->dev);
+ ret = request_firmware(&fw, upd_rproc->firmware, upd->dev);
if (ret < 0) {
- dev_err(upd_wcss->dev, "request_firmware failed: %d\n", ret);
+ dev_err(upd->dev, "request_firmware failed: %d\n", ret);
return ret;
}
@@ -422,19 +424,20 @@ static int q6_wcss_load(struct rproc *rp
*/
static int wcss_pd_load(struct rproc *rproc, const struct firmware *fw)
{
- struct q6_wcss *wcss = rproc->priv;
- struct rproc *rpd_rproc = dev_get_drvdata(wcss->dev->parent);
- u32 pasid = (wcss->pd_asid << 8) | UPD_SWID;
+ struct userpd *upd = rproc->priv;
+ struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
+ struct q6_wcss *wcss = rpd_rproc->priv;
+ u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
int ret;
ret = rproc_boot(rpd_rproc);
if (ret)
return ret;
- return qcom_mdt_load(wcss->dev, fw, rproc->firmware,
+ return qcom_mdt_load(upd->dev, fw, rproc->firmware,
pasid, wcss->mem_region,
wcss->mem_phys, wcss->mem_size,
- &wcss->mem_reloc);
+ NULL);
}
static unsigned long q6_wcss_panic(struct rproc *rproc)
@@ -466,26 +469,15 @@ static int q6_alloc_memory_region(struct
struct device_node *node;
struct device *dev = wcss->dev;
- if (wcss->version == Q6_IPQ) {
- node = of_parse_phandle(dev->of_node, "memory-region", 0);
- if (node)
- rmem = of_reserved_mem_lookup(node);
-
- of_node_put(node);
-
- if (!rmem) {
- dev_err(dev, "unable to acquire memory-region\n");
- return -EINVAL;
- }
- } else {
- struct rproc *rpd_rproc = dev_get_drvdata(dev->parent);
- struct q6_wcss *rpd_wcss = rpd_rproc->priv;
-
- wcss->mem_phys = rpd_wcss->mem_phys;
- wcss->mem_reloc = rpd_wcss->mem_reloc;
- wcss->mem_size = rpd_wcss->mem_size;
- wcss->mem_region = rpd_wcss->mem_region;
- return 0;
+ node = of_parse_phandle(dev->of_node, "memory-region", 0);
+ if (node)
+ rmem = of_reserved_mem_lookup(node);
+
+ of_node_put(node);
+
+ if (!rmem) {
+ dev_err(dev, "unable to acquire memory-region\n");
+ return -EINVAL;
}
wcss->mem_phys = rmem->base;
@@ -509,7 +501,7 @@ static int q6_get_inbound_irq(struct qco
{
int ret, irq;
char *interrupt, *tmp = (char *)int_name;
- struct q6_wcss *wcss = q6->rproc->priv;
+ struct userpd *upd = q6->rproc->priv;
irq = platform_get_irq(pdev, index);
if (irq < 0)
@@ -521,7 +513,7 @@ static int q6_get_inbound_irq(struct qco
if (!interrupt)
return -ENOMEM;
- snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d_%s", wcss->pd_asid, tmp);
+ snprintf(interrupt, BUF_SIZE, "q6v5_wcss_userpd%d_%s", upd->pd_asid, tmp);
ret = devm_request_threaded_irq(&pdev->dev, *pirq,
NULL, handler,
@@ -562,7 +554,7 @@ static int init_irq(struct qcom_q6v5 *q6
void (*handover)(struct qcom_q6v5 *q6))
{
int ret;
- struct q6_wcss *wcss = rproc->priv;
+ struct userpd *upd = rproc->priv;
q6->rproc = rproc;
q6->dev = &pdev->dev;
@@ -582,7 +574,7 @@ static int init_irq(struct qcom_q6v5 *q6
return ret;
/* Get pd_asid to prepare interrupt names */
- wcss->pd_asid = qcom_get_pd_asid(rproc);
+ upd->pd_asid = qcom_get_pd_asid(rproc);
ret = q6_get_inbound_irq(q6, pdev, "fatal", 0, &q6->fatal_irq,
q6v5_fatal_interrupt);
@@ -620,7 +612,7 @@ static void q6_release_resources(void)
static int q6_register_userpd(struct platform_device *pdev,
struct device_node *userpd_np)
{
- struct q6_wcss *wcss;
+ struct userpd *upd;
struct rproc *rproc = NULL;
int ret;
struct platform_device *userpd_pdev;
@@ -653,21 +645,16 @@ static int q6_register_userpd(struct pla
userpd_pdev->dev.driver = pdev->dev.driver;
rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
- firmware_name, sizeof(*wcss));
+ firmware_name, sizeof(*upd));
if (!rproc) {
ret = -ENOMEM;
goto free_rproc;
}
- wcss = rproc->priv;
- wcss->dev = &userpd_pdev->dev;
- wcss->version = WCSS_IPQ;
-
- ret = q6_alloc_memory_region(wcss);
- if (ret)
- goto free_rproc;
+ upd = rproc->priv;
+ upd->dev = &userpd_pdev->dev;
- ret = init_irq(&wcss->q6, userpd_pdev, rproc,
+ ret = init_irq(&upd->q6, userpd_pdev, rproc,
WCSS_CRASH_REASON, NULL, NULL);
if (ret)
goto free_rproc;
@@ -679,7 +666,7 @@ static int q6_register_userpd(struct pla
list_add(&rproc->node, &upd_rproc_list);
platform_set_drvdata(userpd_pdev, rproc);
- qcom_add_ssr_subdev(rproc, &wcss->ssr_subdev, userpd_pdev->name);
+ qcom_add_ssr_subdev(rproc, &upd->ssr_subdev, userpd_pdev->name);
return 0;
free_rproc:
@@ -715,7 +702,6 @@ static int q6_wcss_probe(struct platform
wcss->dev = &pdev->dev;
wcss->desc = of_device_get_match_data(&pdev->dev);
wcss->firmware = firmware;
- wcss->version = Q6_IPQ;
ret = q6_alloc_memory_region(wcss);
if (ret)

View file

@ -1,206 +0,0 @@
From 0fa7bdb855247b738d1d227d6f4b3417ebdf21a8 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH 2/2] remoteproc: qcom_q6v5_mpd: fix incorrent use of
rproc->node
1.817524] list_add corruption. next->prev should be prev (ffffffc0814bbfc8), but was ffffffc0814bc358. (next=ffffff8003b56800).
[ 1.822435] WARNING: CPU: 1 PID: 24 at lib/list_debug.c:29 __list_add_valid_or_report+0x8c/0xdc
[ 1.833923] Modules linked in:
[ 1.842425] CPU: 1 PID: 24 Comm: kworker/u4:1 Not tainted 6.6.47 #0
[ 1.845552] Hardware name: Qualcomm MP03 (DT)
[ 1.851716] Workqueue: events_unbound deferred_probe_work_func
[ 1.856229] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 1.861959] pc : __list_add_valid_or_report+0x8c/0xdc
[ 1.868816] lr : __list_add_valid_or_report+0x8c/0xdc
[ 1.874022] sp : ffffffc081603a50
[ 1.879055] x29: ffffffc081603a50 x28: ffffff8000fa2810 x27: ffffff8003cba800
[ 1.882358] x26: ffffff8000fa2800 x25: ffffff8003cbac80 x24: 0000000000000000
[ 1.889476] x23: ffffffc08088b968 x22: ffffffc0814bb000 x21: ffffffc0814bbfc8
[ 1.896593] x20: ffffffc08088b8e8 x19: ffffff8003cba800 x18: 00000000000000b1
[ 1.903713] x17: 3863666262343138 x16: 3063666666666666 x15: ffffffc081416e20
[ 1.910830] x14: 0000000000000213 x13: 00000000000000b1 x12: 00000000ffffffea
[ 1.917948] x11: 00000000ffffefff x10: ffffffc08146ee20 x9 : ffffffc081416dc8
[ 1.925066] x8 : 0000000000017fe8 x7 : c0000000ffffefff x6 : 0000000000057fa8
[ 1.932184] x5 : 0000000000000fff x4 : 0000000000000000 x3 : ffffffc081603850
[ 1.939302] x2 : ffffffc081416d60 x1 : ffffffc081416d60 x0 : 0000000000000075
[ 1.946422] Call trace:
[ 1.953535] __list_add_valid_or_report+0x8c/0xdc
[ 1.955793] rproc_add+0x1f4/0x25c
[ 1.960653] q6_wcss_probe+0x510/0x634
[ 1.963950] platform_probe+0x68/0xc4
[ 1.967684] really_probe+0x148/0x2b0
[ 1.971417] __driver_probe_device+0x78/0x128
[ 1.975063] driver_probe_device+0x40/0xdc
[ 1.979402] __device_attach_driver+0xb8/0xf8
[ 1.983397] bus_for_each_drv+0x70/0xb8
[ 1.987823] __device_attach+0xa0/0x184
[ 1.991468] device_initial_probe+0x14/0x20
[ 1.995289] bus_probe_device+0xac/0xb0
[ 1.999455] deferred_probe_work_func+0xa4/0xec
[ 2.003275] process_one_work+0x178/0x2d4
[ 2.007788] worker_thread+0x2ec/0x4d8
[ 2.011954] kthread+0xdc/0xe0
[ 2.015600] ret_from_fork+0x10/0x20
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/remoteproc/qcom_q6v5_mpd.c | 53 +++++++++++++++++-------------
1 file changed, 30 insertions(+), 23 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -34,6 +34,7 @@
#define BUF_SIZE 35
+#define MAX_UPD 3
#define MAX_FIRMWARE 3
#define RPD_SWID MPD_WCNSS_PAS_ID
@@ -44,8 +45,6 @@
#define UPD_BOOT_INFO_SMEM_ID 507
#define VERSION2 2
-static LIST_HEAD(upd_rproc_list);
-
/**
* struct userpd_boot_info_header - header of user pd bootinfo
* @type: type of bootinfo passing over smem
@@ -81,6 +80,7 @@ struct q6_wcss {
size_t mem_size;
const struct wcss_data *desc;
const char **firmware;
+ struct userpd *upd[MAX_UPD];
};
struct userpd {
@@ -271,13 +271,12 @@ static void *q6_wcss_da_to_va(struct rpr
*/
static int share_upd_bootinfo_to_q6(struct rproc *rproc)
{
- int ret;
+ int i, ret;
size_t size;
u16 cnt = 0, version;
void *ptr;
struct q6_wcss *wcss = rproc->priv;
struct userpd *upd;
- struct rproc *upd_rproc;
struct userpd_boot_info upd_bootinfo = {0};
const struct firmware *fw;
@@ -302,16 +301,19 @@ static int share_upd_bootinfo_to_q6(stru
memcpy_toio(ptr, &version, sizeof(version));
ptr += sizeof(version);
- list_for_each_entry(upd_rproc, &upd_rproc_list, node)
- cnt++;
+ for (i = 0; i < ARRAY_SIZE(wcss->upd); i++)
+ if (wcss->upd[i])
+ cnt++;
/* No of elements */
cnt = (sizeof(upd_bootinfo) * cnt);
memcpy_toio(ptr, &cnt, sizeof(u16));
ptr += sizeof(u16);
- list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
- upd = upd_rproc->priv;
+ for (i = 0; i < ARRAY_SIZE(wcss->upd); i++) {
+ upd = wcss->upd[i];
+ if (!upd)
+ continue;
/* TYPE */
upd_bootinfo.header.type = UPD_BOOT_INFO_HEADER_TYPE;
@@ -323,14 +325,14 @@ static int share_upd_bootinfo_to_q6(stru
/* Process ID */
upd_bootinfo.pid = upd->pd_asid + 1;
- ret = request_firmware(&fw, upd_rproc->firmware, upd->dev);
+ ret = request_firmware(&fw, upd->q6.rproc->firmware, upd->dev);
if (ret < 0) {
dev_err(upd->dev, "request_firmware failed: %d\n", ret);
return ret;
}
/* Load address */
- upd_bootinfo.bootaddr = rproc_get_boot_addr(upd_rproc, fw);
+ upd_bootinfo.bootaddr = rproc_get_boot_addr(upd->q6.rproc, fw);
/* Firmware mem size */
upd_bootinfo.data_size = qcom_mdt_get_size(fw);
@@ -598,18 +600,23 @@ static int init_irq(struct qcom_q6v5 *q6
return 0;
}
-static void q6_release_resources(void)
+static void q6_release_resources(struct q6_wcss *wcss)
{
- struct rproc *upd_rproc;
+ struct userpd *upd;
+ int i;
/* Release userpd resources */
- list_for_each_entry(upd_rproc, &upd_rproc_list, node) {
- rproc_del(upd_rproc);
- rproc_free(upd_rproc);
+ for (i = 0; i < ARRAY_SIZE(wcss->upd); i++) {
+ upd = wcss->upd[i];
+ if (!upd)
+ continue;
+
+ rproc_del(upd->q6.rproc);
+ rproc_free(upd->q6.rproc);
}
}
-static int q6_register_userpd(struct platform_device *pdev,
+static int q6_register_userpd(struct q6_wcss *wcss,
struct device_node *userpd_np)
{
struct userpd *upd;
@@ -634,16 +641,16 @@ static int q6_register_userpd(struct pla
return ret;
}
- dev_info(&pdev->dev, "%s node found\n", userpd_np->name);
+ dev_info(wcss->dev, "%s node found\n", userpd_np->name);
userpd_pdev = of_platform_device_create(userpd_np, userpd_np->name,
- &pdev->dev);
+ wcss->dev);
if (!userpd_pdev)
- return dev_err_probe(&pdev->dev, -ENODEV,
+ return dev_err_probe(wcss->dev, -ENODEV,
"failed to create %s platform device\n",
userpd_np->name);
- userpd_pdev->dev.driver = pdev->dev.driver;
+ userpd_pdev->dev.driver = wcss->dev->driver;
rproc = rproc_alloc(&userpd_pdev->dev, userpd_pdev->name, &wcss_ops,
firmware_name, sizeof(*upd));
if (!rproc) {
@@ -664,7 +671,7 @@ static int q6_register_userpd(struct pla
if (ret)
goto free_rproc;
- list_add(&rproc->node, &upd_rproc_list);
+ wcss->upd[upd->pd_asid] = upd;
platform_set_drvdata(userpd_pdev, rproc);
qcom_add_ssr_subdev(rproc, &upd->ssr_subdev, userpd_pdev->name);
return 0;
@@ -724,10 +731,10 @@ static int q6_wcss_probe(struct platform
/* Iterate over userpd child's and register with rproc */
for_each_available_child_of_node(pdev->dev.of_node, userpd_np) {
- ret = q6_register_userpd(pdev, userpd_np);
+ ret = q6_register_userpd(wcss, userpd_np);
if (ret) {
/* release resources of successfully allocated userpd rproc's */
- q6_release_resources();
+ q6_release_resources(wcss);
return dev_err_probe(&pdev->dev, ret,
"Failed to register userpd(%s)\n",
userpd_np->name);

View file

@ -1,102 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Tue, 21 Oct 2025 15:26:31 +0400
Subject: [PATCH] remoteproc: qcom: wcss-sec: add split firmware support
The driver currently expects only one firmware file to be loaded as part
of bringing up WCSS. For IPQ5018 and QCN6122, multiple firmware files are
required, both the q6 and m3 firmware files. As such, add support for
loading up to 3 firmware files.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/remoteproc/qcom_q6v5_wcss_sec.c
+++ b/drivers/remoteproc/qcom_q6v5_wcss_sec.c
@@ -25,6 +25,8 @@
#define Q6_WAIT_TIMEOUT (5 * HZ)
+#define MAX_FIRMWARE 3
+
struct wcss_sec {
struct device *dev;
struct qcom_rproc_glink glink_subdev;
@@ -35,6 +37,7 @@ struct wcss_sec {
void *mem_region;
size_t mem_size;
const struct wcss_data *desc;
+ const char **firmware;
struct mbox_client mbox_client;
struct mbox_chan *mbox_chan;
@@ -137,7 +140,8 @@ static int wcss_sec_load(struct rproc *r
{
struct wcss_sec *wcss = rproc->priv;
struct device *dev = wcss->dev;
- int ret;
+ const struct firmware *fw_hdl;
+ int i, ret;
if (wcss->desc->use_tmelcom) {
wcss->metadata = qcom_mdt_read_metadata(fw, &wcss->metadata_len,
@@ -161,6 +165,28 @@ static int wcss_sec_load(struct rproc *r
wcss->mem_phys, wcss->mem_size, &wcss->mem_reloc);
if (ret)
return ret;
+
+ for (i = 1; i < MAX_FIRMWARE; i++) {
+ if (!wcss->firmware[i])
+ continue;
+
+ ret = request_firmware(&fw_hdl, wcss->firmware[i], dev);
+
+ if (ret)
+ continue;
+
+ ret = qcom_mdt_load_no_init(dev, fw_hdl, wcss->firmware[i], 0,
+ wcss->mem_region, wcss->mem_phys,
+ wcss->mem_size, &wcss->mem_reloc);
+
+ release_firmware(fw_hdl);
+
+ if (ret) {
+ dev_err(dev, "error %d loading firmware %s\n",
+ ret, wcss->firmware[i]);
+ return ret;
+ }
+ }
}
qcom_pil_info_store("wcss", wcss->mem_phys, wcss->mem_size);
@@ -291,17 +317,20 @@ static int wcss_sec_probe(struct platfor
struct wcss_sec *wcss;
struct clk *sleep_clk;
struct clk *int_clk;
- const char *fw_name = NULL;
+ const char **firmware = NULL;
const struct wcss_data *desc = of_device_get_match_data(&pdev->dev);
int ret;
- ret = of_property_read_string(pdev->dev.of_node, "firmware-name",
- &fw_name);
+ firmware = devm_kcalloc(&pdev->dev, MAX_FIRMWARE,
+ sizeof(*firmware), GFP_KERNEL);
+
+ ret = of_property_read_string_array(pdev->dev.of_node, "firmware-name",
+ firmware, MAX_FIRMWARE);
if (ret < 0)
return ret;
rproc = devm_rproc_alloc(&pdev->dev, desc->ss_name, &wcss_sec_ops,
- fw_name, sizeof(*wcss));
+ firmware[0], sizeof(*wcss));
if (!rproc) {
dev_err(&pdev->dev, "failed to allocate rproc\n");
return -ENOMEM;
@@ -310,6 +339,7 @@ static int wcss_sec_probe(struct platfor
wcss = rproc->priv;
wcss->dev = &pdev->dev;
wcss->desc = desc;
+ wcss->firmware = firmware;
ret = wcss_sec_alloc_memory_region(wcss);
if (ret)

View file

@ -1,128 +0,0 @@
From 6553d598cdb507f7ede020f25da646ba084a23c6 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH] firmware: qcom_scm: support MPD
Add SCM calls to power up / down the SoC's internal WiFi radio and to
load PIL segments to support the MPD architecture.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/firmware/qcom//qcom_scm.c | 79 ++++++++++++++++++++++++++
drivers/firmware/qcom//qcom_scm.h | 3 +
include/linux/firmware/qcom/qcom_scm.h | 3 +
3 files changed, 85 insertions(+)
--- a/include/linux/firmware/qcom/qcom_scm.h
+++ b/include/linux/firmware/qcom/qcom_scm.h
@@ -79,6 +79,9 @@ int qcom_scm_pas_mem_setup(u32 periphera
int qcom_scm_pas_auth_and_reset(u32 peripheral);
int qcom_scm_pas_shutdown(u32 peripheral);
bool qcom_scm_pas_supported(u32 peripheral);
+int qcom_scm_internal_wifi_powerup(u32 peripheral);
+int qcom_scm_internal_wifi_shutdown(u32 peripheral);
+int qcom_scm_pas_load_segment(u32 peripheral, int segment, dma_addr_t dma, int seg_cnt);
int qcom_scm_msa_lock(u32 peripheral);
int qcom_scm_msa_unlock(u32 peripheral);
--- a/drivers/firmware/qcom/qcom_scm.c
+++ b/drivers/firmware/qcom/qcom_scm.c
@@ -808,6 +808,85 @@ bool qcom_scm_pas_supported(u32 peripher
EXPORT_SYMBOL_GPL(qcom_scm_pas_supported);
/**
+ * qcom_scm_internal_wifi_powerup() - Bring up internal wifi
+ * @peripheral: peripheral id
+ *
+ * Return 0 on success.
+ */
+int qcom_scm_internal_wifi_powerup(u32 peripheral)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_INTERNAL_WIFI_POWERUP,
+ .arginfo = QCOM_SCM_ARGS(1),
+ .args[0] = peripheral,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+ int ret;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ return ret ? : res.result[0];
+}
+EXPORT_SYMBOL(qcom_scm_internal_wifi_powerup);
+
+/**
+ * qcom_scm_internal_wifi_shutdown() - Shut down internal wifi
+ * @peripheral: peripheral id
+ *
+ * Returns 0 on success.
+ */
+int qcom_scm_internal_wifi_shutdown(u32 peripheral)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_INTERNAL_WIFI_SHUTDOWN,
+ .arginfo = QCOM_SCM_ARGS(1),
+ .args[0] = peripheral,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+ int ret;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ return ret ? : res.result[0];
+}
+EXPORT_SYMBOL(qcom_scm_internal_wifi_shutdown);
+
+/**
+ * qcom_scm_pas_load_segment() - copy userpd PIL segments data to dma blocks
+ * @peripheral: peripheral id
+ * @segment: segment id
+ * @dma: handle of dma region
+ * @seg_cnt: no of dma blocks
+ *
+ * Returns 0 if trustzone successfully loads userpd PIL segments from dma
+ * blocks to DDR
+ */
+int qcom_scm_pas_load_segment(u32 peripheral, int segment, dma_addr_t dma, int seg_cnt)
+{
+ struct qcom_scm_desc desc = {
+ .svc = QCOM_SCM_SVC_PIL,
+ .cmd = QCOM_SCM_PIL_PAS_LOAD_SEG,
+ .arginfo = QCOM_SCM_ARGS(4, QCOM_SCM_VAL, QCOM_SCM_VAL, QCOM_SCM_RW, QCOM_SCM_VAL),
+ .args[0] = peripheral,
+ .args[1] = segment,
+ .args[2] = dma,
+ .args[3] = seg_cnt,
+ .owner = ARM_SMCCC_OWNER_SIP,
+ };
+ struct qcom_scm_res res;
+ int ret;
+
+ ret = qcom_scm_call(__scm->dev, &desc, &res);
+
+ return ret ? : res.result[0];
+}
+EXPORT_SYMBOL(qcom_scm_pas_load_segment);
+
+/**
* qcom_scm_msa_lock() - Lock given peripheral firmware region as MSA
*
* @peripheral: peripheral id
--- a/drivers/firmware/qcom/qcom_scm.h
+++ b/drivers/firmware/qcom/qcom_scm.h
@@ -102,6 +102,9 @@ struct qcom_tzmem_pool *qcom_scm_get_tzm
#define QCOM_SCM_PIL_PAS_IS_SUPPORTED 0x07
#define QCOM_SCM_PIL_PAS_MSS_RESET 0x0a
#define QCOM_SCM_PIL_PAS_INIT_IMAGE_V2 0x1a
+#define QCOM_SCM_INTERNAL_WIFI_POWERUP 0x17
+#define QCOM_SCM_INTERNAL_WIFI_SHUTDOWN 0x18
+#define QCOM_SCM_PIL_PAS_LOAD_SEG 0x19
#define QCOM_SCM_MSA_LOCK 0x24
#define QCOM_SCM_MSA_UNLOCK 0x25

View file

@ -1,199 +0,0 @@
From bf42d84868bc82a9cb334a33930f2d1da24f7070 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH] soc: qcom: mdt_loader: support MPD
Add support for loading user PD specific PIL segments as required by the
MPD architecture.
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
drivers/soc/qcom/mdt_loader.c | 110 ++++++++++++++++++++++++++--
include/linux/soc/qcom/mdt_loader.h | 5 ++
2 files changed, 110 insertions(+), 5 deletions(-)
--- a/drivers/soc/qcom/mdt_loader.c
+++ b/drivers/soc/qcom/mdt_loader.c
@@ -17,6 +17,16 @@
#include <linux/sizes.h>
#include <linux/slab.h>
#include <linux/soc/qcom/mdt_loader.h>
+#include <linux/dma-mapping.h>
+
+#include "../../remoteproc/qcom_common.h"
+
+#define QCOM_MDT_PF_ASID_MASK GENMASK(19, 16)
+
+struct segment_load_args {
+ __le64 addr;
+ __le64 blk_size;
+};
static bool mdt_header_valid(const struct firmware *fw)
{
@@ -100,6 +110,56 @@ static ssize_t mdt_load_split_segment(vo
return ret;
}
+static int mdt_load_split_segment_dma(int pas_id, unsigned int segment,
+ const struct elf32_phdr *phdrs,
+ const char *fw_name,
+ struct device *dev)
+{
+ const struct elf32_phdr *phdr = &phdrs[segment];
+ struct segment_load_args *args;
+ dma_addr_t *addrs;
+ void *ptr;
+ dma_addr_t dma_args, dma_addrs, dma_ptr;
+ int ret;
+
+ args = dma_alloc_coherent(dev, sizeof(*args) + sizeof(*addrs), &dma_args, GFP_DMA);
+ if (!args) {
+ dev_err(dev, "Error in dma alloc regin: %ld\n", sizeof(*args));
+ return -ENOMEM;
+ }
+
+ addrs = (void *) args + sizeof(*args);
+ dma_addrs = dma_args + sizeof(*args);
+
+ ptr = dma_alloc_coherent(dev, phdr->p_filesz, &dma_ptr, GFP_DMA);
+ if (!ptr) {
+ dev_err(dev, "Error in dma alloc ptr: %d\n", phdr->p_filesz);
+ return -ENOMEM;
+ }
+
+ args->addr = dma_addrs;
+ args->blk_size = phdr->p_filesz;
+
+ addrs[0] = dma_ptr;
+
+ ret = mdt_load_split_segment(ptr, phdrs, segment, fw_name, dev);
+ if (ret < 0) {
+ dev_err(dev, "Error in mdt_load_split_segment: %d\n", ret);
+ return ret;
+ }
+
+ ret = qcom_scm_pas_load_segment(pas_id, segment, dma_args, 1);
+ if (ret < 0) {
+ dev_err(dev, "Error in qcom_scm_pas_load_segment: %d\n", ret);
+ return ret;
+ }
+
+ dma_free_coherent(dev, phdr->p_filesz, ptr, dma_ptr);
+ dma_free_coherent(dev, sizeof(*args) + sizeof(*addrs), args, dma_args);
+
+ return 0;
+}
+
/**
* qcom_mdt_get_size() - acquire size of the memory region needed to load mdt
* @fw: firmware object for the mdt file
@@ -335,7 +395,8 @@ static bool qcom_mdt_bins_are_split(cons
static int __qcom_mdt_load(struct device *dev, const struct firmware *fw,
const char *fw_name, int pas_id, void *mem_region,
phys_addr_t mem_phys, size_t mem_size,
- phys_addr_t *reloc_base, bool pas_init)
+ phys_addr_t *reloc_base, bool pas_init,
+ bool dma_require, int pd_asid)
{
const struct elf32_phdr *phdrs;
const struct elf32_phdr *phdr;
@@ -392,6 +453,14 @@ static int __qcom_mdt_load(struct device
if (!mdt_phdr_valid(phdr))
continue;
+ /*
+ * While doing PD specific reloading, load only that PD
+ * specific writeable entries. Skip others
+ */
+ if (pd_asid && (FIELD_GET(QCOM_MDT_PF_ASID_MASK, phdr->p_flags) != pd_asid ||
+ (phdr->p_flags & PF_W) == 0))
+ continue;
+
offset = phdr->p_paddr - mem_reloc;
if (offset < 0 || offset + phdr->p_memsz > mem_size) {
dev_err(dev, "segment outside memory range\n");
@@ -409,7 +478,11 @@ static int __qcom_mdt_load(struct device
ptr = mem_region + offset;
- if (phdr->p_filesz && !is_split) {
+ if (dma_require && phdr->p_filesz) {
+ ret = mdt_load_split_segment_dma(pas_id, i, phdrs, fw_name, dev);
+ if (ret)
+ break;
+ } else if (phdr->p_filesz && !is_split) {
/* Firmware is large enough to be non-split */
if (phdr->p_offset + phdr->p_filesz > fw->size) {
dev_err(dev, "file %s segment %d would be truncated\n",
@@ -426,7 +499,7 @@ static int __qcom_mdt_load(struct device
break;
}
- if (phdr->p_memsz > phdr->p_filesz)
+ if (!dma_require && phdr->p_memsz > phdr->p_filesz)
memset(ptr + phdr->p_filesz, 0, phdr->p_memsz - phdr->p_filesz);
}
@@ -461,7 +534,7 @@ int qcom_mdt_load(struct device *dev, co
return ret;
return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
- mem_size, reloc_base, true);
+ mem_size, reloc_base, true, false, 0);
}
EXPORT_SYMBOL_GPL(qcom_mdt_load);
@@ -484,9 +557,36 @@ int qcom_mdt_load_no_init(struct device
size_t mem_size, phys_addr_t *reloc_base)
{
return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
- mem_size, reloc_base, false);
+ mem_size, reloc_base, false, false, 0);
}
EXPORT_SYMBOL_GPL(qcom_mdt_load_no_init);
+/**
+ * qcom_mdt_load_pd_seg() - load userpd specific PIL segements
+ * @dev: device handle to associate resources with
+ * @fw: firmware object for the mdt file
+ * @firmware: name of the firmware, for construction of segment file names
+ * @pas_id: PAS identifier
+ * @mem_region: allocated memory region to load firmware into
+ * @mem_phys: physical address of allocated memory region
+ * @mem_size: size of the allocated memory region
+ * @reloc_base: adjusted physical address after relocation
+ *
+ * Here userpd PIL segements are stitched with rootpd firmware.
+ * This function reloads userpd specific PIL segments during SSR
+ * of userpd.
+ *
+ * Returns 0 on success, negative errno otherwise.
+ */
+int qcom_mdt_load_pd_seg(struct device *dev, const struct firmware *fw,
+ const char *firmware, int pas_id, int pd_asid, void *mem_region,
+ phys_addr_t mem_phys, size_t mem_size,
+ phys_addr_t *reloc_base)
+{
+ return __qcom_mdt_load(dev, fw, firmware, pas_id, mem_region, mem_phys,
+ mem_size, reloc_base, false, true, pd_asid);
+}
+EXPORT_SYMBOL_GPL(qcom_mdt_load_pd_seg);
+
MODULE_DESCRIPTION("Firmware parser for Qualcomm MDT format");
MODULE_LICENSE("GPL v2");
--- a/include/linux/soc/qcom/mdt_loader.h
+++ b/include/linux/soc/qcom/mdt_loader.h
@@ -30,6 +30,11 @@ int qcom_mdt_load_no_init(struct device
void *qcom_mdt_read_metadata(const struct firmware *fw, size_t *data_len,
const char *fw_name, struct device *dev);
+int qcom_mdt_load_pd_seg(struct device *dev, const struct firmware *fw,
+ const char *firmware, int pas_id, int pd_asid, void *mem_region,
+ phys_addr_t mem_phys, size_t mem_size,
+ phys_addr_t *reloc_base);
+
#else /* !IS_ENABLED(CONFIG_QCOM_MDT_LOADER) */
static inline ssize_t qcom_mdt_get_size(const struct firmware *fw)

View file

@ -1,38 +0,0 @@
From e83215d5d22946885fa388d375b12f1b991a43c1 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH 3/5] remoteproc: qcom_q6v5_mpd: enable clocks
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/remoteproc/qcom_q6v5_mpd.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -78,6 +78,8 @@ struct q6_wcss {
phys_addr_t mem_reloc;
void *mem_region;
size_t mem_size;
+ struct clk_bulk_data *clks;
+ int num_clks;
const struct wcss_data *desc;
const char **firmware;
struct userpd *upd[MAX_UPD];
@@ -714,6 +716,16 @@ static int q6_wcss_probe(struct platform
if (ret)
goto free_rproc;
+ wcss->num_clks = devm_clk_bulk_get_all(wcss->dev, &wcss->clks);
+ if (wcss->num_clks < 0)
+ return dev_err_probe(wcss->dev, wcss->num_clks,
+ "failed to acquire clocks\n");
+
+ ret = clk_bulk_prepare_enable(wcss->num_clks, wcss->clks);
+ if (ret)
+ return dev_err_probe(wcss->dev, ret,
+ "failed to enable clocks\n");
+
ret = qcom_q6v5_init(&wcss->q6, pdev, rproc,
WCSS_CRASH_REASON, NULL, NULL);
if (ret)

View file

@ -1,111 +0,0 @@
From 4ae334127f073aa5f7c9209c9f0a17fd9e331db1 Mon Sep 17 00:00:00 2001
From: Ziyang Huang <hzyitc@outlook.com>
Date: Sun, 8 Sep 2024 16:40:12 +0800
Subject: [PATCH] remoteproc: qcom_q6v5_mpd: support ipq5018
Signed-off-by: Ziyang Huang <hzyitc@outlook.com>
---
drivers/remoteproc/qcom_q6v5_mpd.c | 37 +++++++++++++++++++++++++++---
1 file changed, 34 insertions(+), 3 deletions(-)
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -156,6 +156,8 @@ static int q6_wcss_spawn_pd(struct rproc
static int wcss_pd_start(struct rproc *rproc)
{
struct userpd *upd = rproc->priv;
+ struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
+ struct q6_wcss *wcss = rpd_rproc->priv;
u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
int ret;
@@ -171,6 +173,14 @@ static int wcss_pd_start(struct rproc *r
return ret;
}
+ if (upd->pd_asid == 1) {
+ ret = qcom_scm_internal_wifi_powerup(wcss->desc->pasid);
+ if (ret) {
+ dev_err(upd->dev, "failed to power up internal radio\n");
+ return ret;
+ }
+ }
+
return ret;
}
@@ -180,6 +190,12 @@ static int q6_wcss_stop(struct rproc *rp
const struct wcss_data *desc = wcss->desc;
int ret;
+ ret = qcom_q6v5_request_stop(&wcss->q6, NULL);
+ if (ret) {
+ dev_err(wcss->dev, "pd not stopped\n");
+ return ret;
+ }
+
ret = qcom_scm_pas_shutdown(desc->pasid);
if (ret) {
dev_err(wcss->dev, "not able to shutdown\n");
@@ -219,6 +235,7 @@ static int wcss_pd_stop(struct rproc *rp
{
struct userpd *upd = rproc->priv;
struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
+ struct q6_wcss *wcss = rpd_rproc->priv;
u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
int ret;
@@ -230,6 +247,14 @@ static int wcss_pd_stop(struct rproc *rp
}
}
+ if (upd->pd_asid == 1) {
+ ret = qcom_scm_internal_wifi_shutdown(wcss->desc->pasid);
+ if (ret) {
+ dev_err(upd->dev, "failed to power down internal radio\n");
+ return ret;
+ }
+ }
+
ret = qcom_scm_msa_unlock(pasid);
if (ret) {
dev_err(upd->dev, "failed to power down pd\n");
@@ -431,15 +456,14 @@ static int wcss_pd_load(struct rproc *rp
struct userpd *upd = rproc->priv;
struct rproc *rpd_rproc = dev_get_drvdata(upd->dev->parent);
struct q6_wcss *wcss = rpd_rproc->priv;
- u32 pasid = (upd->pd_asid << 8) | UPD_SWID;
int ret;
ret = rproc_boot(rpd_rproc);
if (ret)
return ret;
- return qcom_mdt_load(upd->dev, fw, rproc->firmware,
- pasid, wcss->mem_region,
+ return qcom_mdt_load_pd_seg(upd->dev, fw, rproc->firmware,
+ wcss->desc->pasid, upd->pd_asid, wcss->mem_region,
wcss->mem_phys, wcss->mem_size,
NULL);
}
@@ -771,6 +795,12 @@ static void q6_wcss_remove(struct platfo
rproc_free(rproc);
}
+static const struct wcss_data q6_ipq5018_res_init = {
+ .pasid = MPD_WCNSS_PAS_ID,
+ // .share_upd_info_to_q6 = true, /* Version 1 */
+ // .mdt_load_sec = qcom_mdt_load_pd_seg,
+};
+
static const struct wcss_data q6_ipq5332_res_init = {
.pasid = MPD_WCNSS_PAS_ID,
.share_upd_info_to_q6 = true,
@@ -781,6 +811,7 @@ static const struct wcss_data q6_ipq9574
};
static const struct of_device_id q6_wcss_of_match[] = {
+ { .compatible = "qcom,ipq5018-q6-mpd", .data = &q6_ipq5018_res_init },
{ .compatible = "qcom,ipq5332-q6-mpd", .data = &q6_ipq5332_res_init },
{ .compatible = "qcom,ipq9574-q6-mpd", .data = &q6_ipq9574_res_init },
{ },

View file

@ -1,163 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Mon, 09 Dec 2024 09:59:38 +0400
Subject: [PATCH] remoteproc: qcom_q6v5_mpd: add support for passing v1 bootargs
On multi-PD platforms such as IPQ5018, boot args are passed to the root PD
run on the Q6 processor which in turn boots the user PDs for internal
(IPQ5018) and external wifi radios (such as QCN6122). These boot args
let the user PD process know details like what PCIE index, user PD ID, and
reset GPIO is used. These are otherwise hardcoded in the firmware.
Below is the structure expected of the version 1 boot args including the
default values hardcoded in the firmware for IPQ5018:
+------------+------+--------------+--------------+
| Argument | type | def val UPD2 | def val UPD3 |
+------------+------+--------------+--------------+
| PCIE Index | u32 | 0x02 (PCIE1) | 0x01 (PCIE0) |
| Length | u32 | 0x04 | 0x04 |
| User PD ID | u32 | 0x02 | 0x03 |
| Reset GPIO | u32 | 0x12 | 0x0f |
| Reserved 1 | u32 | 0x00 | 0x00 |
| Reserved 2 | u32 | 0x00 | 0x00 |
+------------+------+--------------+--------------+
On IPQ5018/QCN6122 boards, the default mapping is as follows:
+-> UPD1 ----> IPQ5018 Internal 2.4G Radio
/
/
Root PD +---> UPD2 ----> QCN6122 6G Radio on PCIE1 (if available)
\
\
+-> UPD3 ----> QCN6102 5G Radio on PCIE0
To support (future) boards with other mappings or control what UPD ID is
used, let's add support for passing boot args for more flexibility.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/drivers/remoteproc/qcom_q6v5_mpd.c
+++ b/drivers/remoteproc/qcom_q6v5_mpd.c
@@ -43,7 +43,11 @@
#define UPD_BOOT_INFO_SMEM_SIZE 4096
#define UPD_BOOT_INFO_HEADER_TYPE 0x2
#define UPD_BOOT_INFO_SMEM_ID 507
-#define VERSION2 2
+
+enum q6_bootargs_version {
+ VERSION1 = 1,
+ VERSION2,
+};
/**
* struct userpd_boot_info_header - header of user pd bootinfo
@@ -95,6 +99,7 @@ struct userpd {
struct wcss_data {
u32 pasid;
bool share_upd_info_to_q6;
+ u8 bootargs_version;
};
/**
@@ -299,10 +304,13 @@ static void *q6_wcss_da_to_va(struct rpr
static int share_upd_bootinfo_to_q6(struct rproc *rproc)
{
int i, ret;
+ u32 rd_val;
size_t size;
u16 cnt = 0, version;
void *ptr;
+ u8 *bootargs_arr;
struct q6_wcss *wcss = rproc->priv;
+ struct device_node *np = wcss->dev->of_node;
struct userpd *upd;
struct userpd_boot_info upd_bootinfo = {0};
const struct firmware *fw;
@@ -324,10 +332,47 @@ static int share_upd_bootinfo_to_q6(stru
}
/*Version*/
- version = VERSION2;
+ version = (wcss->desc->bootargs_version) ? wcss->desc->bootargs_version : VERSION2;
memcpy_toio(ptr, &version, sizeof(version));
ptr += sizeof(version);
+ cnt = ret = of_property_count_u32_elems(np, "boot-args");
+ if (ret < 0) {
+ if (ret == -ENODATA) {
+ dev_err(wcss->dev, "failed to read boot args ret:%d\n", ret);
+ return ret;
+ }
+ cnt = 0;
+ }
+
+ /* No of elements */
+ memcpy_toio(ptr, &cnt, sizeof(u16));
+ ptr += sizeof(u16);
+
+ bootargs_arr = kzalloc(cnt, GFP_KERNEL);
+ if (!bootargs_arr) {
+ dev_err(wcss->dev, "failed to allocate memory\n");
+ return PTR_ERR(bootargs_arr);
+ }
+
+ for (i = 0; i < cnt; i++) {
+ ret = of_property_read_u32_index(np, "boot-args", i, &rd_val);
+ if (ret) {
+ dev_err(wcss->dev, "failed to read boot args\n");
+ kfree(bootargs_arr);
+ return ret;
+ }
+ bootargs_arr[i] = (u8)rd_val;
+ }
+
+ /* Copy bootargs */
+ memcpy_toio(ptr, bootargs_arr, cnt);
+ ptr += (cnt);
+
+ of_node_put(np);
+ kfree(bootargs_arr);
+ cnt = 0;
+
for (i = 0; i < ARRAY_SIZE(wcss->upd); i++)
if (wcss->upd[i])
cnt++;
@@ -383,12 +428,14 @@ static int q6_wcss_load(struct rproc *rp
/* Share user pd boot info to Q6 remote processor */
if (desc->share_upd_info_to_q6) {
- ret = share_upd_bootinfo_to_q6(rproc);
- if (ret) {
- dev_err(wcss->dev,
- "user pd boot info sharing with q6 failed %d\n",
- ret);
- return ret;
+ if (of_property_present(wcss->dev->of_node, "boot-args")) {
+ ret = share_upd_bootinfo_to_q6(rproc);
+ if (ret) {
+ dev_err(wcss->dev,
+ "user pd boot info sharing with q6 failed %d\n",
+ ret);
+ return ret;
+ }
}
}
@@ -797,13 +844,15 @@ static void q6_wcss_remove(struct platfo
static const struct wcss_data q6_ipq5018_res_init = {
.pasid = MPD_WCNSS_PAS_ID,
- // .share_upd_info_to_q6 = true, /* Version 1 */
+ .share_upd_info_to_q6 = true,
+ .bootargs_version = VERSION1,
// .mdt_load_sec = qcom_mdt_load_pd_seg,
};
static const struct wcss_data q6_ipq5332_res_init = {
.pasid = MPD_WCNSS_PAS_ID,
.share_upd_info_to_q6 = true,
+ .bootargs_version = VERSION2,
};
static const struct wcss_data q6_ipq9574_res_init = {

View file

@ -1,134 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] arm64: dts: qcom: ipq5018: add wifi support
The IPQ5018 SoC comes with an internal 2x2 2.4Ghz wifi radio.
QCN6122 is a PCIe based wifi solution specific to the IPQ5018 platform which
comes optinally packed with 1 or 2 QCN6122 chips or with an external
PCIe based wifi solution (such as QCN9074) for 5/6 Ghz support.
As such, add wifi nodes for both IPQ5018 and QCN6122.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -739,6 +739,118 @@
};
};
+ wifi: wifi@c000000 {
+ compatible = "qcom,ipq5018-wifi";
+ reg = <0x0c000000 0x1000000>;
+
+ interrupts = <GIC_SPI 288 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 289 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 290 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 291 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 292 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 293 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 294 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 295 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 296 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 297 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 298 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 299 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 300 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 301 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 302 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 303 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 304 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 305 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 306 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 307 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 308 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 309 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 310 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 311 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 334 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 313 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 314 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 315 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 316 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 317 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 318 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 319 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 320 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 321 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 322 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 323 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 324 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 325 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 326 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 327 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 328 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 329 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 330 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 331 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 332 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 333 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 312 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 335 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 336 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 337 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 338 IRQ_TYPE_EDGE_RISING>,
+ <GIC_SPI 339 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "misc-pulse1",
+ "misc-latch",
+ "sw-exception",
+ "watchdog",
+ "ce0",
+ "ce1",
+ "ce2",
+ "ce3",
+ "ce4",
+ "ce5",
+ "ce6",
+ "ce7",
+ "ce8",
+ "ce9",
+ "ce10",
+ "ce11",
+ "host2wbm-desc-feed",
+ "host2reo-re-injection",
+ "host2reo-command",
+ "host2rxdma-monitor-ring3",
+ "host2rxdma-monitor-ring2",
+ "host2rxdma-monitor-ring1",
+ "reo2ost-exception",
+ "wbm2host-rx-release",
+ "reo2host-status",
+ "reo2host-destination-ring4",
+ "reo2host-destination-ring3",
+ "reo2host-destination-ring2",
+ "reo2host-destination-ring1",
+ "rxdma2host-monitor-destination-mac3",
+ "rxdma2host-monitor-destination-mac2",
+ "rxdma2host-monitor-destination-mac1",
+ "ppdu-end-interrupts-mac3",
+ "ppdu-end-interrupts-mac2",
+ "ppdu-end-interrupts-mac1",
+ "rxdma2host-monitor-status-ring-mac3",
+ "rxdma2host-monitor-status-ring-mac2",
+ "rxdma2host-monitor-status-ring-mac1",
+ "host2rxdma-host-buf-ring-mac3",
+ "host2rxdma-host-buf-ring-mac2",
+ "host2rxdma-host-buf-ring-mac1",
+ "rxdma2host-destination-ring-mac3",
+ "rxdma2host-destination-ring-mac2",
+ "rxdma2host-destination-ring-mac1",
+ "host2tcl-input-ring4",
+ "host2tcl-input-ring3",
+ "host2tcl-input-ring2",
+ "host2tcl-input-ring1",
+ "wbm2host-tx-completions-ring3",
+ "wbm2host-tx-completions-ring2",
+ "wbm2host-tx-completions-ring1",
+ "tcl2host-status-ring";
+
+ status = "disabled";
+ };
+
q6v5_wcss: remoteproc@cd00000 {
compatible = "qcom,ipq5018-wcss-sec-pil";
reg = <0x0cd00000 0x10000>;

View file

@ -1,22 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 05 Feb 2025 12:12:47 +0400
Subject: [PATCH] arm64: dts: qcom: ipq5018: add tz_apps reserved memory region
Add tz_apps memory region needed for wifi to work.
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -136,6 +136,11 @@
#size-cells = <2>;
ranges;
+ tz_apps@4a400000 {
+ reg = <0x0 0x4a400000 0x0 0x400000>;
+ no-map;
+ };
+
bootloader@4a800000 {
reg = <0x0 0x4a800000 0x0 0x200000>;
no-map;

View file

@ -1,62 +0,0 @@
From: George Moussalem <george.moussalem@outlook.com>
Date: Wed, 27 Oct 2024 16:34:11 +0400
Subject: [PATCH] dt: bindings: net: add bindings for QCN6122
QCN6122 is a PCIe based solution that is attached to and enumerated
by the WPSS (Wireless Processor SubSystem) Q6 processor.
Though it is a PCIe device, since it is not attached to APSS processor
(Application Processor SubSystem), APSS will be unaware of such a decice
and hence it is registered to the APSS processor as a platform device(AHB).
Because of this hybrid nature, it is called as a hybrid bus device.
As such, QCN6122 is a hybrid bus type device and follows the same codepath
as for WCN6750.
This is a reversed engineered and heavily simplified version of below
downstream patch:
https://git.codelinaro.org/clo/qsdk/oss/system/feeds/wlan-open/-/ \
blob/NHSS.QSDK.12.4.5.r2/mac80211/patches/232-ath11k-qcn6122-support.patch
Signed-off-by: George Moussalem <george.moussalem@outlook.com>
---
--- a/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/qcom,ath11k.yaml
@@ -22,6 +22,7 @@ properties:
- qcom,ipq6018-wifi
- qcom,wcn6750-wifi
- qcom,ipq5018-wifi
+ - qcom,qcn6122-wifi
reg:
maxItems: 1
@@ -262,6 +263,29 @@ allOf:
- description: interrupt event for ring DP20
- description: interrupt event for ring DP21
- description: interrupt event for ring DP22
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcn6122-wifi
+ then:
+ properties:
+ interrupts:
+ items:
+ - description: interrupt event for ring CE1
+ - description: interrupt event for ring CE2
+ - description: interrupt event for ring CE3
+ - description: interrupt event for ring CE4
+ - description: interrupt event for ring CE5
+ - description: interrupt event for ring DP1
+ - description: interrupt event for ring DP2
+ - description: interrupt event for ring DP3
+ - description: interrupt event for ring DP4
+ - description: interrupt event for ring DP5
+ - description: interrupt event for ring DP6
+ - description: interrupt event for ring DP7
+ - description: interrupt event for ring DP8
examples:
- |

View file

@ -1,51 +0,0 @@
--- a/arch/arm64/boot/dts/qcom/ipq5018.dtsi
+++ b/arch/arm64/boot/dts/qcom/ipq5018.dtsi
@@ -9,6 +9,7 @@
#include <dt-bindings/clock/qcom,gcc-ipq5018.h>
#include <dt-bindings/clock/qcom,ipq5018-cmn-pll.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/net/qca-uniphy.h>
#include <dt-bindings/reset/qcom,gcc-ipq5018.h>
#include <dt-bindings/thermal/thermal.h>
@@ -258,6 +259,29 @@
status = "disabled";
};
+ uniphy0: ethernet-pcs@98000 {
+ compatible = "qualcomm,ipq5018-uniphy";
+ reg = <0x00098000 0x800>;
+ #clock-cells = <1>;
+ clocks = <&gcc GCC_UNIPHY_AHB_CLK>,
+ <&gcc GCC_UNIPHY_SYS_CLK>,
+ <&gcc GCC_UNIPHY_RX_CLK>,
+ <&gcc GCC_UNIPHY_TX_CLK>,
+ <&cmn_pll IPQ5018_ETH_50MHZ_CLK>;
+ clock-names = "ahb",
+ "sys",
+ "port5_rx",
+ "port5_tx",
+ "ref";
+ clock-output-names = "uniphy0_gcc_rx_clk",
+ "uniphy0_gcc_tx_clk",
+ "uniphy0_ref_clk";
+ resets = <&gcc GCC_UNIPHY_SOFT_RESET>;
+ reset-names = "soft";
+ #pcs-cells = <0>;
+ status = "disabled";
+ };
+
cmn_pll: clock-controller@9b000 {
compatible = "qcom,ipq5018-cmn-pll";
reg = <0x0009b000 0x800>;
@@ -449,8 +473,8 @@
<0>,
<&gephy_rx_clk>,
<&gephy_tx_clk>,
- <0>,
- <0>;
+ <&uniphy0 UNIPHY_CLK_RX>,
+ <&uniphy0 UNIPHY_CLK_TX>;
#clock-cells = <1>;
#reset-cells = <1>;
};

View file

@ -1,56 +0,0 @@
From ca732e990fc8222a2d6782ae750304719e212fe8 Mon Sep 17 00:00:00 2001
From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Date: Thu, 1 May 2025 12:45:11 +0100
Subject: [PATCH] net: stmmac: add get_interfaces() platform method
Add a get_interfaces() platform method to allow platforms to indicate
to phylink which interface modes they support - which then allows
phylink to validate on initialisation that the configured PHY interface
mode is actually supported.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://patch.msgid.link/E1uASLn-0021Qd-Mi@rmk-PC.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
---
.../net/ethernet/stmicro/stmmac/stmmac_main.c | 16 +++++++++++++---
include/linux/stmmac.h | 2 ++
2 files changed, 15 insertions(+), 3 deletions(-)
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1250,10 +1250,21 @@ static int stmmac_phy_setup(struct stmma
priv->phylink_config.default_an_inband =
mdio_bus_data->default_an_inband;
- /* Set the platform/firmware specified interface mode. Note, phylink
- * deals with the PHY interface mode, not the MAC interface mode.
+ /* Get the PHY interface modes (at the PHY end of the link) that
+ * are supported by the platform.
*/
- __set_bit(mode, priv->phylink_config.supported_interfaces);
+ if (priv->plat->get_interfaces)
+ priv->plat->get_interfaces(priv, priv->plat->bsp_priv,
+ priv->phylink_config.supported_interfaces);
+
+ /* Set the platform/firmware specified interface mode if the
+ * supported interfaces have not already been provided using
+ * phy_interface as a last resort.
+ */
+ if (phy_interface_empty(priv->phylink_config.supported_interfaces))
+ __set_bit(priv->plat->phy_interface,
+ priv->phylink_config.supported_interfaces);
+
/* If we have an xpcs, it defines which PHY interfaces are supported. */
if (priv->hw->xpcs)
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -229,6 +229,8 @@ struct plat_stmmacenet_data {
u8 tx_sched_algorithm;
struct stmmac_rxq_cfg rx_queues_cfg[MTL_MAX_RX_QUEUES];
struct stmmac_txq_cfg tx_queues_cfg[MTL_MAX_TX_QUEUES];
+ void (*get_interfaces)(struct stmmac_priv *priv, void *bsp_priv,
+ unsigned long *interfaces);
void (*fix_mac_speed)(void *priv, unsigned int speed, unsigned int mode);
int (*fix_soc_reset)(void *priv, void __iomem *ioaddr);
int (*serdes_powerup)(struct net_device *ndev, void *priv);

Some files were not shown because too many files have changed in this diff Show more