Drop support for 6.12 by removing config and patches.
Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
+++ /dev/null
-CONFIG_64BIT=y
-# CONFIG_ACPI is not set
-CONFIG_AMBA_PL08X=y
-# CONFIG_ARCH_CANAAN is not set
-CONFIG_ARCH_DMA_ADDR_T_64BIT=y
-CONFIG_ARCH_DMA_DEFAULT_COHERENT=y
-CONFIG_ARCH_HIBERNATION_POSSIBLE=y
-CONFIG_ARCH_MHP_MEMMAP_ON_MEMORY_ENABLE=y
-# CONFIG_ARCH_MICROCHIP is not set
-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_MAX=17
-CONFIG_ARCH_OPTIONAL_KERNEL_RWX=y
-CONFIG_ARCH_OPTIONAL_KERNEL_RWX_DEFAULT=y
-CONFIG_ARCH_PROC_KCORE_TEXT=y
-# CONFIG_ARCH_RV32I is not set
-CONFIG_ARCH_RV64I=y
-CONFIG_ARCH_SELECT_MEMORY_MODEL=y
-CONFIG_ARCH_SIFIVE=y
-# CONFIG_ARCH_SOPHGO is not set
-CONFIG_ARCH_SPARSEMEM_ENABLE=y
-CONFIG_ARCH_STACKWALK=y
-CONFIG_ARCH_STARFIVE=y
-CONFIG_ARCH_SUSPEND_POSSIBLE=y
-# CONFIG_ARCH_THEAD is not set
-CONFIG_ARCH_WANTS_NO_INSTR=y
-CONFIG_ARCH_WANTS_THP_SWAP=y
-CONFIG_ARM_AMBA=y
-# CONFIG_ARM_MHU_V2 is not set
-CONFIG_ASN1=y
-CONFIG_AUXILIARY_BUS=y
-# CONFIG_AX45MP_L2_CACHE is not set
-CONFIG_BLK_MQ_PCI=y
-CONFIG_BLK_MQ_VIRTIO=y
-CONFIG_BLK_PM=y
-CONFIG_BUFFER_HEAD=y
-# CONFIG_BUILTIN_DTB is not set
-CONFIG_CC_HAVE_STACKPROTECTOR_TLS=y
-CONFIG_CHECKPOINT_RESTORE=y
-CONFIG_CLKSRC_MMIO=y
-CONFIG_CLK_ANALOGBITS_WRPLL_CLN28HPC=y
-CONFIG_CLK_SIFIVE=y
-CONFIG_CLK_SIFIVE_PRCI=y
-CONFIG_CLK_STARFIVE_JH7100=y
-CONFIG_CLK_STARFIVE_JH7100_AUDIO=y
-CONFIG_CLK_STARFIVE_JH7110_AON=y
-CONFIG_CLK_STARFIVE_JH7110_ISP=y
-CONFIG_CLK_STARFIVE_JH7110_PLL=y
-CONFIG_CLK_STARFIVE_JH7110_STG=y
-CONFIG_CLK_STARFIVE_JH7110_SYS=y
-CONFIG_CLK_STARFIVE_JH7110_VOUT=y
-CONFIG_CLK_STARFIVE_JH71X0=y
-CONFIG_CLONE_BACKWARDS=y
-CONFIG_CLZ_TAB=y
-CONFIG_CMODEL_MEDANY=y
-# CONFIG_CMODEL_MEDLOW is not set
-CONFIG_COMMON_CLK=y
-CONFIG_COMPACT_UNEVICTABLE_DEFAULT=1
-# CONFIG_COMPAT_32BIT_TIME is not set
-CONFIG_CONFIGFS_FS=y
-CONFIG_CONTEXT_TRACKING=y
-CONFIG_CONTEXT_TRACKING_IDLE=y
-CONFIG_CPUFREQ_DT=y
-CONFIG_CPUFREQ_DT_PLATDEV=y
-CONFIG_CPU_FREQ=y
-CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_ATTR_SET=y
-CONFIG_CPU_FREQ_GOV_COMMON=y
-CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
-CONFIG_CPU_FREQ_GOV_ONDEMAND=y
-CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
-CONFIG_CPU_FREQ_GOV_POWERSAVE=y
-CONFIG_CPU_FREQ_GOV_USERSPACE=y
-CONFIG_CPU_FREQ_STAT=y
-CONFIG_CPU_IDLE=y
-CONFIG_CPU_IDLE_GOV_MENU=y
-CONFIG_CPU_IDLE_MULTIPLE_DRIVERS=y
-CONFIG_CPU_MITIGATIONS=y
-CONFIG_CPU_PM=y
-CONFIG_CPU_RMAP=y
-CONFIG_CRC16=y
-CONFIG_CRC7=y
-CONFIG_CRC_ITU_T=y
-CONFIG_CRYPTO_BLAKE2B=y
-CONFIG_CRYPTO_CBC=y
-CONFIG_CRYPTO_CMAC=y
-CONFIG_CRYPTO_CRC32C=y
-# CONFIG_CRYPTO_DEV_JH7110 is not set
-CONFIG_CRYPTO_DRBG=y
-CONFIG_CRYPTO_DRBG_HMAC=y
-CONFIG_CRYPTO_DRBG_MENU=y
-CONFIG_CRYPTO_ECB=y
-CONFIG_CRYPTO_ECC=y
-CONFIG_CRYPTO_ECDH=y
-CONFIG_CRYPTO_HMAC=y
-CONFIG_CRYPTO_HW=y
-CONFIG_CRYPTO_JITTERENTROPY=y
-CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKS=64
-CONFIG_CRYPTO_JITTERENTROPY_MEMORY_BLOCKSIZE=32
-CONFIG_CRYPTO_JITTERENTROPY_OSR=1
-CONFIG_CRYPTO_LIB_BLAKE2S_GENERIC=y
-CONFIG_CRYPTO_LIB_GF128MUL=y
-CONFIG_CRYPTO_LIB_POLY1305_RSIZE=1
-CONFIG_CRYPTO_LIB_SHA256=y
-CONFIG_CRYPTO_LIB_UTILS=y
-CONFIG_CRYPTO_RNG=y
-CONFIG_CRYPTO_RNG_DEFAULT=y
-CONFIG_CRYPTO_RSA=y
-CONFIG_CRYPTO_SHA256=y
-CONFIG_CRYPTO_SHA3=y
-CONFIG_CRYPTO_SHA512=y
-CONFIG_CRYPTO_SM3=y
-CONFIG_CRYPTO_SM3_GENERIC=y
-CONFIG_CRYPTO_XXHASH=y
-CONFIG_CRYPTO_ZSTD=y
-CONFIG_DEBUG_ATOMIC_SLEEP=y
-CONFIG_DEBUG_GPIO=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_PINCTRL=y
-CONFIG_DEBUG_RODATA_TEST=y
-CONFIG_DEBUG_RT_MUTEXES=y
-CONFIG_DEBUG_RWSEMS=y
-CONFIG_DEBUG_SECTION_MISMATCH=y
-CONFIG_DEBUG_SG=y
-CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_WX=y
-CONFIG_DECOMPRESS_GZIP=y
-# CONFIG_DEVFREQ_GOV_PASSIVE is not set
-# CONFIG_DEVFREQ_GOV_PERFORMANCE is not set
-# CONFIG_DEVFREQ_GOV_POWERSAVE is not set
-# CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND is not set
-# CONFIG_DEVFREQ_GOV_USERSPACE is not set
-# CONFIG_DEVFREQ_THERMAL is not set
-CONFIG_DEVTMPFS=y
-CONFIG_DEVTMPFS_MOUNT=y
-CONFIG_DMADEVICES=y
-CONFIG_DMADEVICES_DEBUG=y
-CONFIG_DMADEVICES_VDEBUG=y
-CONFIG_DMA_BOUNCE_UNALIGNED_KMALLOC=y
-CONFIG_DMA_ENGINE=y
-CONFIG_DMA_GLOBAL_POOL=y
-CONFIG_DMA_NEED_SYNC=y
-CONFIG_DMA_OF=y
-CONFIG_DMA_SHARED_BUFFER=y
-CONFIG_DMA_VIRTUAL_CHANNELS=y
-CONFIG_DMI=y
-CONFIG_DMIID=y
-# CONFIG_DMI_SYSFS is not set
-CONFIG_DTC=y
-CONFIG_DT_IDLE_GENPD=y
-CONFIG_DT_IDLE_STATES=y
-CONFIG_DWMAC_DWC_QOS_ETH=y
-# CONFIG_DWMAC_GENERIC is not set
-CONFIG_DWMAC_STARFIVE=y
-CONFIG_DW_AXI_DMAC=y
-CONFIG_E24=y
-CONFIG_EDAC_SUPPORT=y
-CONFIG_EEPROM_AT24=y
-CONFIG_EFI=y
-CONFIG_EFIVAR_FS=y
-# CONFIG_EFI_BOOTLOADER_CONTROL is not set
-# CONFIG_EFI_CAPSULE_LOADER is not set
-# CONFIG_EFI_COCO_SECRET is not set
-# CONFIG_EFI_DISABLE_PCI_DMA is not set
-CONFIG_EFI_DISABLE_RUNTIME=y
-CONFIG_EFI_EARLYCON=y
-CONFIG_EFI_ESRT=y
-CONFIG_EFI_GENERIC_STUB=y
-CONFIG_EFI_PARAMS_FROM_FDT=y
-CONFIG_EFI_RUNTIME_WRAPPERS=y
-CONFIG_EFI_STUB=y
-# CONFIG_EFI_TEST is not set
-# CONFIG_EFI_ZBOOT is not set
-# CONFIG_ERRATA_ANDES is not set
-CONFIG_ERRATA_SIFIVE=y
-CONFIG_ERRATA_SIFIVE_CIP_1200=y
-CONFIG_ERRATA_SIFIVE_CIP_453=y
-CONFIG_ERRATA_STARFIVE_JH7100=y
-# CONFIG_ERRATA_THEAD is not set
-CONFIG_EXCLUSIVE_SYSTEM_RAM=y
-CONFIG_EXT4_FS=y
-CONFIG_EXTCON=y
-CONFIG_FAILOVER=y
-CONFIG_FANOTIFY=y
-CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-15"
-CONFIG_FAT_DEFAULT_UTF8=y
-CONFIG_FAT_FS=y
-CONFIG_FIXED_PHY=y
-CONFIG_FIX_EARLYCON_MEM=y
-CONFIG_FONT_8x16=y
-CONFIG_FONT_AUTOSELECT=y
-CONFIG_FONT_SUPPORT=y
-CONFIG_FPU=y
-CONFIG_FRAME_POINTER=y
-CONFIG_FS_IOMAP=y
-CONFIG_FS_MBCACHE=y
-CONFIG_FUNCTION_ALIGNMENT=0
-CONFIG_FWNODE_MDIO=y
-CONFIG_FW_LOADER_PAGED_BUF=y
-CONFIG_FW_LOADER_SYSFS=y
-CONFIG_GCC_SUPPORTS_DYNAMIC_FTRACE=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_DEVICES=y
-CONFIG_GENERIC_CPU_VULNERABILITIES=y
-CONFIG_GENERIC_CSUM=y
-CONFIG_GENERIC_EARLY_IOREMAP=y
-CONFIG_GENERIC_ENTRY=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_IPI_MUX=y
-CONFIG_GENERIC_IRQ_MATRIX_ALLOCATOR=y
-CONFIG_GENERIC_IRQ_MIGRATION=y
-CONFIG_GENERIC_IRQ_MULTI_HANDLER=y
-CONFIG_GENERIC_IRQ_SHOW=y
-CONFIG_GENERIC_IRQ_SHOW_LEVEL=y
-CONFIG_GENERIC_LIB_DEVMEM_IS_ALLOWED=y
-CONFIG_GENERIC_MSI_IRQ=y
-CONFIG_GENERIC_PCI_IOMAP=y
-CONFIG_GENERIC_PHY=y
-CONFIG_GENERIC_PHY_MIPI_DPHY=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_GPIOLIB_FASTPATH_LIMIT=128
-CONFIG_GPIOLIB_IRQCHIP=y
-CONFIG_GPIO_CDEV=y
-CONFIG_GPIO_TPS65086=y
-CONFIG_HARDIRQS_SW_RESEND=y
-CONFIG_HAS_DMA=y
-CONFIG_HAS_IOMEM=y
-CONFIG_HAS_IOPORT=y
-CONFIG_HAS_IOPORT_MAP=y
-CONFIG_HOTPLUG_CORE_SYNC=y
-CONFIG_HOTPLUG_CORE_SYNC_DEAD=y
-CONFIG_HOTPLUG_CPU=y
-CONFIG_HUGETLBFS=y
-CONFIG_HUGETLB_PAGE=y
-CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING=y
-CONFIG_HVC_DRIVER=y
-CONFIG_HVC_RISCV_SBI=y
-CONFIG_HWMON=y
-CONFIG_HW_RANDOM=y
-CONFIG_HW_RANDOM_JH7110=y
-CONFIG_HW_RANDOM_STARFIVE_VIC=y
-CONFIG_I2C=y
-CONFIG_I2C_ALGOBIT=y
-CONFIG_I2C_BOARDINFO=y
-CONFIG_I2C_CHARDEV=y
-CONFIG_I2C_DESIGNWARE_CORE=y
-CONFIG_I2C_DESIGNWARE_PLATFORM=y
-CONFIG_IKCONFIG=y
-CONFIG_IKCONFIG_PROC=y
-CONFIG_ILLEGAL_POINTER_VALUE=0xdead000000000000
-CONFIG_INITRAMFS_SOURCE=""
-# CONFIG_IPMS_CAN is not set
-CONFIG_IRQCHIP=y
-CONFIG_IRQ_DOMAIN=y
-CONFIG_IRQ_DOMAIN_HIERARCHY=y
-CONFIG_IRQ_FORCED_THREADING=y
-CONFIG_IRQ_STACKS=y
-CONFIG_IRQ_WORK=y
-CONFIG_JBD2=y
-CONFIG_JH71XX_PMU=y
-CONFIG_KCMP=y
-# CONFIG_KERNEL_UNCOMPRESSED is not set
-CONFIG_LEGACY_DIRECT_IO=y
-CONFIG_LIBFDT=y
-CONFIG_LOCKUP_DETECTOR=y
-CONFIG_LOCK_DEBUGGING_SUPPORT=y
-CONFIG_LOCK_SPIN_ON_OWNER=y
-CONFIG_LSM=""
-CONFIG_MAILBOX=y
-# CONFIG_MAILBOX_TEST is not set
-CONFIG_MARVELL_PHY=y
-CONFIG_MDIO_BUS=y
-CONFIG_MDIO_DEVICE=y
-CONFIG_MDIO_DEVRES=y
-CONFIG_MEMTEST=y
-CONFIG_MFD_AXP20X=y
-CONFIG_MFD_AXP20X_I2C=y
-CONFIG_MFD_CORE=y
-CONFIG_MFD_SYSCON=y
-CONFIG_MFD_TPS65086=y
-CONFIG_MICREL_PHY=y
-CONFIG_MICROCHIP_PHY=y
-CONFIG_MIGRATION=y
-CONFIG_MMC=y
-CONFIG_MMC_BLOCK=y
-CONFIG_MMC_DEBUG=y
-CONFIG_MMC_DW=y
-# CONFIG_MMC_DW_BLUEFIELD is not set
-# CONFIG_MMC_DW_EXYNOS is not set
-# CONFIG_MMC_DW_HI3798CV200 is not set
-# CONFIG_MMC_DW_HI3798MV200 is not set
-# CONFIG_MMC_DW_K3 is not set
-# CONFIG_MMC_DW_PCI is not set
-CONFIG_MMC_DW_PLTFM=y
-CONFIG_MMC_DW_STARFIVE=y
-CONFIG_MMIOWB=y
-CONFIG_MMU_LAZY_TLB_REFCOUNT=y
-CONFIG_MODULES_TREE_LOOKUP=y
-CONFIG_MODULES_USE_ELF_RELA=y
-CONFIG_MOTORCOMM_PHY=y
-CONFIG_MPILIB=y
-CONFIG_MTD_SPI_NOR=y
-CONFIG_MUTEX_SPIN_ON_OWNER=y
-CONFIG_NAMESPACES=y
-CONFIG_NEED_DMA_MAP_STATE=y
-CONFIG_NET_DEVMEM=y
-CONFIG_NET_EGRESS=y
-CONFIG_NET_FAILOVER=y
-CONFIG_NET_FLOW_LIMIT=y
-CONFIG_NET_INGRESS=y
-CONFIG_NET_NS=y
-CONFIG_NET_PTP_CLASSIFY=y
-CONFIG_NET_SELFTESTS=y
-CONFIG_NET_XGRESS=y
-CONFIG_NLS=y
-CONFIG_NLS_CODEPAGE_437=y
-CONFIG_NLS_DEFAULT="iso8859-15"
-CONFIG_NLS_ISO8859_1=y
-CONFIG_NLS_ISO8859_15=y
-CONFIG_NONPORTABLE=y
-CONFIG_NO_HZ_COMMON=y
-CONFIG_NO_HZ_IDLE=y
-CONFIG_NR_CPUS=8
-# CONFIG_NSM is not set
-CONFIG_NVMEM=y
-CONFIG_NVMEM_LAYOUTS=y
-CONFIG_NVMEM_SYSFS=y
-CONFIG_OF=y
-CONFIG_OF_ADDRESS=y
-CONFIG_OF_DYNAMIC=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_OF_OVERLAY=y
-CONFIG_OF_RESOLVE=y
-CONFIG_OID_REGISTRY=y
-CONFIG_OVERLAY_FS_INDEX=y
-CONFIG_OVERLAY_FS_METACOPY=y
-CONFIG_OVERLAY_FS_REDIRECT_DIR=y
-CONFIG_PADATA=y
-CONFIG_PAGE_EXTENSION=y
-CONFIG_PAGE_OFFSET=0xff60000000000000
-CONFIG_PAGE_POOL=y
-CONFIG_PAGE_REPORTING=y
-CONFIG_PAGE_SIZE_LESS_THAN_256KB=y
-CONFIG_PAGE_SIZE_LESS_THAN_64KB=y
-CONFIG_PCI=y
-CONFIG_PCIE_CADENCE=y
-CONFIG_PCIE_CADENCE_HOST=y
-CONFIG_PCIE_CADENCE_PLAT=y
-CONFIG_PCIE_CADENCE_PLAT_HOST=y
-# CONFIG_PCIE_FU740 is not set
-CONFIG_PCIE_PLDA_HOST=y
-CONFIG_PCIE_STARFIVE_HOST=y
-CONFIG_PCI_DOMAINS=y
-CONFIG_PCI_DOMAINS_GENERIC=y
-CONFIG_PCI_LABEL=y
-CONFIG_PCI_MSI=y
-CONFIG_PCS_XPCS=y
-CONFIG_PERF_EVENTS=y
-CONFIG_PER_VMA_LOCK=y
-CONFIG_PGTABLE_HAS_HUGE_LEAVES=y
-CONFIG_PGTABLE_LEVELS=5
-CONFIG_PHYLIB=y
-CONFIG_PHYLIB_LEDS=y
-CONFIG_PHYLINK=y
-CONFIG_PHYS_ADDR_T_64BIT=y
-# CONFIG_PHYS_RAM_BASE_FIXED is not set
-CONFIG_PHY_STARFIVE_JH7110_DPHY_RX=y
-# CONFIG_PHY_STARFIVE_JH7110_DPHY_TX is not set
-CONFIG_PHY_STARFIVE_JH7110_PCIE=y
-CONFIG_PHY_STARFIVE_JH7110_USB=y
-CONFIG_PINCTRL=y
-CONFIG_PINCTRL_STARFIVE_JH7100=y
-CONFIG_PINCTRL_STARFIVE_JH7110=y
-CONFIG_PINCTRL_STARFIVE_JH7110_AON=y
-CONFIG_PINCTRL_STARFIVE_JH7110_SYS=y
-CONFIG_PM=y
-CONFIG_PM_ADVANCED_DEBUG=y
-CONFIG_PM_CLK=y
-CONFIG_PM_DEBUG=y
-CONFIG_PM_DEVFREQ=y
-# CONFIG_PM_DEVFREQ_EVENT is not set
-CONFIG_PM_GENERIC_DOMAINS=y
-CONFIG_PM_GENERIC_DOMAINS_OF=y
-CONFIG_PM_OPP=y
-CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y
-CONFIG_POSIX_MQUEUE=y
-CONFIG_POSIX_MQUEUE_SYSCTL=y
-CONFIG_POWER_RESET=y
-CONFIG_POWER_RESET_GPIO_RESTART=y
-CONFIG_POWER_RESET_SYSCON=y
-CONFIG_POWER_RESET_SYSCON_POWEROFF=y
-# CONFIG_POWER_RESET_TPS65086 is not set
-CONFIG_PPS=y
-CONFIG_PREEMPT_COUNT=y
-CONFIG_PRINTK_TIME=y
-CONFIG_PROC_CHILDREN=y
-CONFIG_PROC_KCORE=y
-CONFIG_PTDUMP_CORE=y
-CONFIG_PTP_1588_CLOCK=y
-CONFIG_PTP_1588_CLOCK_OPTIONAL=y
-CONFIG_PWM=y
-CONFIG_PWM_OCORES=y
-# CONFIG_PWM_SIFIVE is not set
-CONFIG_QUEUED_RWLOCKS=y
-CONFIG_RANDSTRUCT_NONE=y
-CONFIG_RATIONAL=y
-CONFIG_RCU_EQS_DEBUG=y
-CONFIG_RD_GZIP=y
-CONFIG_REALTEK_PHY=y
-# CONFIG_REALTEK_PHY_HWMON is not set
-CONFIG_REGMAP=y
-CONFIG_REGMAP_I2C=y
-CONFIG_REGMAP_IRQ=y
-CONFIG_REGMAP_MMIO=y
-CONFIG_REGULATOR=y
-CONFIG_REGULATOR_AXP20X=y
-CONFIG_REGULATOR_TPS65086=y
-# CONFIG_RESET_ATTACK_MITIGATION is not set
-CONFIG_RESET_CONTROLLER=y
-CONFIG_RESET_SIMPLE=y
-CONFIG_RESET_STARFIVE_JH7100=y
-CONFIG_RESET_STARFIVE_JH7100_AUDIO=m
-CONFIG_RESET_STARFIVE_JH7110=y
-CONFIG_RESET_STARFIVE_JH71X0=y
-CONFIG_RFS_ACCEL=y
-CONFIG_RISCV=y
-CONFIG_RISCV_ALTERNATIVE=y
-CONFIG_RISCV_APLIC=y
-CONFIG_RISCV_APLIC_MSI=y
-CONFIG_RISCV_BOOT_SPINWAIT=y
-CONFIG_RISCV_DMA_NONCOHERENT=y
-# CONFIG_RISCV_EFFICIENT_UNALIGNED_ACCESS is not set
-# CONFIG_RISCV_EMULATED_UNALIGNED_ACCESS is not set
-CONFIG_RISCV_IMSIC=y
-CONFIG_RISCV_IMSIC_PCI=y
-CONFIG_RISCV_INTC=y
-CONFIG_RISCV_ISA_C=y
-CONFIG_RISCV_ISA_FALLBACK=y
-CONFIG_RISCV_ISA_SVNAPOT=y
-# CONFIG_RISCV_ISA_SVPBMT is not set
-# CONFIG_RISCV_ISA_V is not set
-# CONFIG_RISCV_ISA_VENDOR_EXT_ANDES is not set
-CONFIG_RISCV_ISA_ZAWRS=y
-CONFIG_RISCV_ISA_ZBA=y
-CONFIG_RISCV_ISA_ZBB=y
-CONFIG_RISCV_ISA_ZBC=y
-# CONFIG_RISCV_ISA_ZICBOM is not set
-CONFIG_RISCV_ISA_ZICBOZ=y
-CONFIG_RISCV_MISALIGNED=y
-CONFIG_RISCV_NONSTANDARD_CACHE_OPS=y
-CONFIG_RISCV_PMU=y
-CONFIG_RISCV_PMU_LEGACY=y
-CONFIG_RISCV_PMU_SBI=y
-CONFIG_RISCV_PROBE_UNALIGNED_ACCESS=y
-CONFIG_RISCV_SBI=y
-CONFIG_RISCV_SBI_CPUIDLE=y
-CONFIG_RISCV_SBI_V01=y
-# CONFIG_RISCV_SLOW_UNALIGNED_ACCESS is not set
-CONFIG_RISCV_TIMER=y
-CONFIG_RISCV_USE_LINKER_RELAXATION=y
-CONFIG_RPMSG=y
-CONFIG_RPMSG_CHAR=y
-# CONFIG_RPMSG_CTRL is not set
-CONFIG_RPMSG_NS=y
-# CONFIG_RPMSG_TTY is not set
-CONFIG_RPMSG_VIRTIO=y
-CONFIG_RPS=y
-CONFIG_RTC_CLASS=y
-CONFIG_RTC_DRV_HYM8563=y
-CONFIG_RTC_DRV_STARFIVE=y
-CONFIG_RTC_I2C_AND_SPI=y
-# CONFIG_RUNTIME_KERNEL_TESTING_MENU is not set
-CONFIG_RWSEM_SPIN_ON_OWNER=y
-CONFIG_SCSI=y
-CONFIG_SCSI_COMMON=y
-CONFIG_SCSI_VIRTIO=y
-CONFIG_SENSORS_SFCTEMP=y
-# CONFIG_SERIAL_8250_16550A_VARIANTS is not set
-CONFIG_SERIAL_8250_DW=y
-CONFIG_SERIAL_8250_DWLIB=y
-CONFIG_SERIAL_8250_EXTENDED=y
-CONFIG_SERIAL_8250_MANY_PORTS=y
-CONFIG_SERIAL_8250_NR_UARTS=6
-CONFIG_SERIAL_8250_RUNTIME_UARTS=6
-# CONFIG_SERIAL_8250_SHARE_IRQ is not set
-CONFIG_SERIAL_EARLYCON_RISCV_SBI=y
-CONFIG_SERIAL_MCTRL_GPIO=y
-CONFIG_SERIAL_OF_PLATFORM=y
-CONFIG_SERIAL_SIFIVE=y
-CONFIG_SERIAL_SIFIVE_CONSOLE=y
-CONFIG_SGL_ALLOC=y
-CONFIG_SG_POOL=y
-CONFIG_SIFIVE_CCACHE=y
-CONFIG_SIFIVE_PLIC=y
-CONFIG_SMP=y
-# CONFIG_SND_SOC_STARFIVE is not set
-CONFIG_SOCK_RX_QUEUE_MAPPING=y
-CONFIG_SOC_STARFIVE=y
-CONFIG_SOFTIRQ_ON_OWN_STACK=y
-CONFIG_SOFTLOCKUP_DETECTOR=y
-CONFIG_SOUND=y
-CONFIG_SPARSEMEM_VMEMMAP_ENABLE=y
-CONFIG_SPARSE_IRQ=y
-CONFIG_SPI=y
-CONFIG_SPI_CADENCE_QUADSPI=y
-CONFIG_SPI_DYNAMIC=y
-CONFIG_SPI_MASTER=y
-CONFIG_SPI_MEM=y
-CONFIG_SPI_PL022=y
-CONFIG_SPI_SPIDEV=y
-CONFIG_SPLIT_PMD_PTLOCKS=y
-CONFIG_SPLIT_PTE_PTLOCKS=y
-CONFIG_STARFIVE_JH7110_TIMER=y
-CONFIG_STARFIVE_JH8100_INTC=y
-CONFIG_STARFIVE_MBOX=y
-# CONFIG_STARFIVE_MBOX_TEST is not set
-CONFIG_STARFIVE_STARLINK_CACHE=y
-# CONFIG_STARFIVE_STARLINK_PMU is not set
-CONFIG_STARFIVE_WATCHDOG=y
-CONFIG_STMMAC_ETH=y
-CONFIG_STMMAC_PLATFORM=y
-CONFIG_STMMAC_SELFTESTS=y
-CONFIG_SWIOTLB=y
-CONFIG_SWPHY=y
-CONFIG_SYNC_FILE=y
-CONFIG_SYSCTL_ARCH_UNALIGN_ALLOW=y
-CONFIG_SYSCTL_EXCEPTION_TRACE=y
-# CONFIG_SYSFB_SIMPLEFB is not set
-CONFIG_THERMAL=y
-CONFIG_THERMAL_DEFAULT_GOV_STEP_WISE=y
-CONFIG_THERMAL_EMERGENCY_POWEROFF_DELAY_MS=0
-CONFIG_THERMAL_GOV_STEP_WISE=y
-CONFIG_THERMAL_HWMON=y
-CONFIG_THERMAL_OF=y
-CONFIG_THREAD_INFO_IN_TASK=y
-CONFIG_THREAD_SIZE_ORDER=2
-CONFIG_TICK_CPU_ACCOUNTING=y
-CONFIG_TIMER_OF=y
-CONFIG_TIMER_PROBE=y
-CONFIG_TOOLCHAIN_HAS_V=y
-CONFIG_TOOLCHAIN_HAS_VECTOR_CRYPTO=y
-CONFIG_TOOLCHAIN_HAS_ZBB=y
-CONFIG_TOOLCHAIN_HAS_ZBC=y
-CONFIG_TOOLCHAIN_NEEDS_EXPLICIT_ZICSR_ZIFENCEI=y
-CONFIG_TREE_RCU=y
-CONFIG_TREE_SRCU=y
-CONFIG_TTY_PRINTK=y
-CONFIG_TTY_PRINTK_LEVEL=6
-CONFIG_TUNE_GENERIC=y
-CONFIG_UCS2_STRING=y
-CONFIG_UNINLINE_SPIN_UNLOCK=y
-CONFIG_USB=y
-CONFIG_USB_CDNS3=y
-CONFIG_USB_CDNS3_GADGET=y
-CONFIG_USB_CDNS3_HOST=y
-CONFIG_USB_CDNS3_STARFIVE=y
-CONFIG_USB_CDNS_HOST=y
-CONFIG_USB_CDNS_SUPPORT=y
-CONFIG_USB_COMMON=y
-CONFIG_USB_CONFIGFS=y
-# CONFIG_USB_CONFIGFS_ACM is not set
-# CONFIG_USB_CONFIGFS_ECM is not set
-# CONFIG_USB_CONFIGFS_ECM_SUBSET is not set
-# CONFIG_USB_CONFIGFS_EEM is not set
-CONFIG_USB_CONFIGFS_F_FS=y
-# CONFIG_USB_CONFIGFS_F_HID is not set
-# CONFIG_USB_CONFIGFS_F_LB_SS is not set
-# CONFIG_USB_CONFIGFS_F_MIDI is not set
-# CONFIG_USB_CONFIGFS_F_MIDI2 is not set
-# CONFIG_USB_CONFIGFS_F_PRINTER is not set
-# CONFIG_USB_CONFIGFS_F_UAC1 is not set
-# CONFIG_USB_CONFIGFS_F_UAC1_LEGACY is not set
-# CONFIG_USB_CONFIGFS_F_UAC2 is not set
-# CONFIG_USB_CONFIGFS_F_UVC is not set
-CONFIG_USB_CONFIGFS_MASS_STORAGE=y
-# CONFIG_USB_CONFIGFS_NCM is not set
-# CONFIG_USB_CONFIGFS_OBEX is not set
-# CONFIG_USB_CONFIGFS_RNDIS is not set
-# CONFIG_USB_CONFIGFS_SERIAL is not set
-CONFIG_USB_F_FS=y
-CONFIG_USB_F_MASS_STORAGE=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_LIBCOMPOSITE=y
-CONFIG_USB_PCI=y
-CONFIG_USB_ROLE_SWITCH=y
-CONFIG_USB_SUPPORT=y
-# CONFIG_USB_UHCI_HCD is not set
-CONFIG_USB_XHCI_HCD=y
-CONFIG_USB_XHCI_PCI=y
-CONFIG_USB_XHCI_PLATFORM=y
-CONFIG_USELIB=y
-CONFIG_USER_NS=y
-CONFIG_USER_STACKTRACE_SUPPORT=y
-CONFIG_VFAT_FS=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_VMCORE_INFO=y
-CONFIG_WATCHDOG_CORE=y
-CONFIG_WATCHDOG_SYSFS=y
-CONFIG_WERROR=y
-CONFIG_WQ_WATCHDOG=y
-CONFIG_XARRAY_MULTI=y
-CONFIG_XPS=y
-CONFIG_XXHASH=y
-CONFIG_ZLIB_INFLATE=y
-CONFIG_ZONE_DMA32=y
-CONFIG_ZSTD_COMMON=y
-CONFIG_ZSTD_COMPRESS=y
-CONFIG_ZSTD_DECOMPRESS=y
+++ /dev/null
-From 5605ebdd7f7033da8f1bcb77cb180ef16235d5c8 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 11 Apr 2023 16:31:15 +0800
-Subject: [PATCH 01/55] riscv: dts: starfive: Add full support (except VIN and
- VOUT) for JH7110 and VisionFive 2 board
-
-Merge all StarFive dts patches together except VIN and VOUT.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- .../boot/dts/starfive/jh7110-common.dtsi | 2 +
- .../jh7110-starfive-visionfive-2.dtsi | 100 ++++++++++++++++++
- arch/riscv/boot/dts/starfive/jh7110.dtsi | 21 ++++
- 3 files changed, 123 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-common.dtsi
-@@ -18,6 +18,8 @@
- i2c6 = &i2c6;
- mmc0 = &mmc0;
- mmc1 = &mmc1;
-+ pcie0 = &pcie0;
-+ pcie1 = &pcie1;
- serial0 = &uart0;
- };
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -29,6 +29,24 @@
- };
- };
-
-+&i2srx {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2srx_pins>;
-+ status = "okay";
-+};
-+
-+&i2stx0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&mclk_ext_pins>;
-+ status = "okay";
-+};
-+
-+&i2stx1 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&i2stx1_pins>;
-+ status = "okay";
-+};
-+
- &mmc0 {
- non-removable;
- };
-@@ -40,3 +58,85 @@
- &pcie1 {
- status = "okay";
- };
-+
-+&sysgpio {
-+ i2srx_pins: i2srx-0 {
-+ clk-sd-pins {
-+ pinmux = <GPIOMUX(38, GPOUT_LOW,
-+ GPOEN_DISABLE,
-+ GPI_SYS_I2SRX_BCLK)>,
-+ <GPIOMUX(63, GPOUT_LOW,
-+ GPOEN_DISABLE,
-+ GPI_SYS_I2SRX_LRCK)>,
-+ <GPIOMUX(38, GPOUT_LOW,
-+ GPOEN_DISABLE,
-+ GPI_SYS_I2STX1_BCLK)>,
-+ <GPIOMUX(63, GPOUT_LOW,
-+ GPOEN_DISABLE,
-+ GPI_SYS_I2STX1_LRCK)>,
-+ <GPIOMUX(61, GPOUT_LOW,
-+ GPOEN_DISABLE,
-+ GPI_SYS_I2SRX_SDIN0)>;
-+ input-enable;
-+ };
-+ };
-+
-+ i2stx1_pins: i2stx1-0 {
-+ sd-pins {
-+ pinmux = <GPIOMUX(44, GPOUT_SYS_I2STX1_SDO0,
-+ GPOEN_ENABLE,
-+ GPI_NONE)>;
-+ bias-disable;
-+ input-disable;
-+ };
-+ };
-+
-+ mclk_ext_pins: mclk-ext-0 {
-+ mclk-ext-pins {
-+ pinmux = <GPIOMUX(4, GPOUT_LOW,
-+ GPOEN_DISABLE,
-+ GPI_SYS_MCLK_EXT)>;
-+ input-enable;
-+ };
-+ };
-+
-+ tdm_pins: tdm-0 {
-+ tx-pins {
-+ pinmux = <GPIOMUX(44, GPOUT_SYS_TDM_TXD,
-+ GPOEN_ENABLE,
-+ GPI_NONE)>;
-+ bias-pull-up;
-+ drive-strength = <2>;
-+ input-disable;
-+ input-schmitt-disable;
-+ slew-rate = <0>;
-+ };
-+
-+ rx-pins {
-+ pinmux = <GPIOMUX(61, GPOUT_HIGH,
-+ GPOEN_DISABLE,
-+ GPI_SYS_TDM_RXD)>;
-+ input-enable;
-+ };
-+
-+ sync-pins {
-+ pinmux = <GPIOMUX(63, GPOUT_HIGH,
-+ GPOEN_DISABLE,
-+ GPI_SYS_TDM_SYNC)>;
-+ input-enable;
-+ };
-+
-+ pcmclk-pins {
-+ pinmux = <GPIOMUX(38, GPOUT_HIGH,
-+ GPOEN_DISABLE,
-+ GPI_SYS_TDM_CLK)>;
-+ input-enable;
-+ };
-+ };
-+};
-+
-+&tdm {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&tdm_pins>;
-+ status = "okay";
-+};
---- a/arch/riscv/boot/dts/starfive/jh7110.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110.dtsi
-@@ -259,6 +259,7 @@
- clock-output-names = "dvp_clk";
- #clock-cells = <0>;
- };
-+
- gmac0_rgmii_rxin: gmac0-rgmii-rxin-clock {
- compatible = "fixed-clock";
- clock-output-names = "gmac0_rgmii_rxin";
-@@ -919,6 +920,26 @@
- #gpio-cells = <2>;
- };
-
-+ timer@13050000 {
-+ compatible = "starfive,jh7110-timer";
-+ reg = <0x0 0x13050000 0x0 0x10000>;
-+ interrupts = <69>, <70>, <71>, <72>;
-+ clocks = <&syscrg JH7110_SYSCLK_TIMER_APB>,
-+ <&syscrg JH7110_SYSCLK_TIMER0>,
-+ <&syscrg JH7110_SYSCLK_TIMER1>,
-+ <&syscrg JH7110_SYSCLK_TIMER2>,
-+ <&syscrg JH7110_SYSCLK_TIMER3>;
-+ clock-names = "apb", "ch0", "ch1",
-+ "ch2", "ch3";
-+ resets = <&syscrg JH7110_SYSRST_TIMER_APB>,
-+ <&syscrg JH7110_SYSRST_TIMER0>,
-+ <&syscrg JH7110_SYSRST_TIMER1>,
-+ <&syscrg JH7110_SYSRST_TIMER2>,
-+ <&syscrg JH7110_SYSRST_TIMER3>;
-+ reset-names = "apb", "ch0", "ch1",
-+ "ch2", "ch3";
-+ };
-+
- watchdog@13070000 {
- compatible = "starfive,jh7110-wdt";
- reg = <0x0 0x13070000 0x0 0x10000>;
+++ /dev/null
-From 9e8b51600e4b0ea28c599303b87f6b1b8585eee4 Mon Sep 17 00:00:00 2001
-From: Xingyu Wu <xingyu.wu@starfivetech.com>
-Date: Thu, 19 Oct 2023 13:35:00 +0800
-Subject: [PATCH 02/55] clocksource: Add JH7110 timer driver
-
-Add timer driver for the StarFive JH7110 SoC.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
----
- drivers/clocksource/Kconfig | 11 +
- drivers/clocksource/Makefile | 1 +
- drivers/clocksource/timer-jh7110.c | 380 +++++++++++++++++++++++++++++
- 3 files changed, 392 insertions(+)
- create mode 100644 drivers/clocksource/timer-jh7110.c
-
---- a/drivers/clocksource/Kconfig
-+++ b/drivers/clocksource/Kconfig
-@@ -653,6 +653,17 @@ config RISCV_TIMER
- is accessed via both the SBI and the rdcycle instruction. This is
- required for all RISC-V systems.
-
-+config STARFIVE_JH7110_TIMER
-+ bool "Timer for the STARFIVE JH7110 SoC"
-+ depends on ARCH_STARFIVE || COMPILE_TEST
-+ select TIMER_OF
-+ select CLKSRC_MMIO
-+ default ARCH_STARFIVE
-+ help
-+ This enables the timer for StarFive JH7110 SoC. On RISC-V platform,
-+ the system has started RISCV_TIMER, but you can also use this timer
-+ which can provide four channels to do a lot more things on JH7110 SoC.
-+
- config CLINT_TIMER
- bool "CLINT Timer for the RISC-V platform" if COMPILE_TEST
- depends on GENERIC_SCHED_CLOCK && RISCV
---- a/drivers/clocksource/Makefile
-+++ b/drivers/clocksource/Makefile
-@@ -81,6 +81,7 @@ obj-$(CONFIG_INGENIC_TIMER) += ingenic-
- obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o
- obj-$(CONFIG_X86_NUMACHIP) += numachip.o
- obj-$(CONFIG_RISCV_TIMER) += timer-riscv.o
-+obj-$(CONFIG_STARFIVE_JH7110_TIMER) += timer-jh7110.o
- obj-$(CONFIG_CLINT_TIMER) += timer-clint.o
- obj-$(CONFIG_CSKY_MP_TIMER) += timer-mp-csky.o
- obj-$(CONFIG_GX6605S_TIMER) += timer-gx6605s.o
---- /dev/null
-+++ b/drivers/clocksource/timer-jh7110.c
-@@ -0,0 +1,380 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * Starfive JH7110 Timer driver
-+ *
-+ * Copyright (C) 2022-2023 StarFive Technology Co., Ltd.
-+ *
-+ * Author:
-+ * Xingyu Wu <xingyu.wu@starfivetech.com>
-+ * Samin Guo <samin.guo@starfivetech.com>
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/clockchips.h>
-+#include <linux/clocksource.h>
-+#include <linux/err.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/iopoll.h>
-+#include <linux/irq.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/reset.h>
-+#include <linux/sched_clock.h>
-+
-+/* Bias: Ch0-0x0, Ch1-0x40, Ch2-0x80, and so on. */
-+#define JH7110_TIMER_CH_LEN 0x40
-+#define JH7110_TIMER_CH_BASE(x) ((x) * JH7110_TIMER_CH_LEN)
-+#define JH7110_TIMER_CH_MAX 4
-+
-+#define JH7110_CLOCK_SOURCE_RATING 200
-+#define JH7110_VALID_BITS 32
-+#define JH7110_DELAY_US 0
-+#define JH7110_TIMEOUT_US 10000
-+#define JH7110_CLOCKEVENT_RATING 300
-+#define JH7110_TIMER_MAX_TICKS 0xffffffff
-+#define JH7110_TIMER_MIN_TICKS 0xf
-+#define JH7110_TIMER_RELOAD_VALUE 0
-+
-+#define JH7110_TIMER_INT_STATUS 0x00 /* RO[0:4]: Interrupt Status for channel0~4 */
-+#define JH7110_TIMER_CTL 0x04 /* RW[0]: 0-continuous run, 1-single run */
-+#define JH7110_TIMER_LOAD 0x08 /* RW: load value to counter */
-+#define JH7110_TIMER_ENABLE 0x10 /* RW[0]: timer enable register */
-+#define JH7110_TIMER_RELOAD 0x14 /* RW: write 1 or 0 both reload counter */
-+#define JH7110_TIMER_VALUE 0x18 /* RO: timer value register */
-+#define JH7110_TIMER_INT_CLR 0x20 /* RW: timer interrupt clear register */
-+#define JH7110_TIMER_INT_MASK 0x24 /* RW[0]: timer interrupt mask register */
-+
-+#define JH7110_TIMER_INT_CLR_ENA BIT(0)
-+#define JH7110_TIMER_INT_CLR_AVA_MASK BIT(1)
-+
-+struct jh7110_clkevt {
-+ struct clock_event_device evt;
-+ struct clocksource cs;
-+ bool cs_is_valid;
-+ struct clk *clk;
-+ struct reset_control *rst;
-+ u32 rate;
-+ u32 reload_val;
-+ void __iomem *base;
-+ char name[sizeof("jh7110-timer.chX")];
-+};
-+
-+struct jh7110_timer_priv {
-+ struct clk *pclk;
-+ struct reset_control *prst;
-+ struct jh7110_clkevt clkevt[JH7110_TIMER_CH_MAX];
-+};
-+
-+/* 0:continuous-run mode, 1:single-run mode */
-+enum jh7110_timer_mode {
-+ JH7110_TIMER_MODE_CONTIN,
-+ JH7110_TIMER_MODE_SINGLE,
-+};
-+
-+/* Interrupt Mask, 0:Unmask, 1:Mask */
-+enum jh7110_timer_int_mask {
-+ JH7110_TIMER_INT_ENA,
-+ JH7110_TIMER_INT_DIS,
-+};
-+
-+enum jh7110_timer_enable {
-+ JH7110_TIMER_DIS,
-+ JH7110_TIMER_ENA,
-+};
-+
-+static inline struct jh7110_clkevt *to_jh7110_clkevt(struct clock_event_device *evt)
-+{
-+ return container_of(evt, struct jh7110_clkevt, evt);
-+}
-+
-+/*
-+ * BIT(0): Read value represent channel int status.
-+ * Write 1 to this bit to clear interrupt. Write 0 has no effects.
-+ * BIT(1): "1" means that it is clearing interrupt. BIT(0) can not be written.
-+ */
-+static inline int jh7110_timer_int_clear(struct jh7110_clkevt *clkevt)
-+{
-+ u32 value;
-+ int ret;
-+
-+ /* Waiting interrupt can be cleared */
-+ ret = readl_poll_timeout_atomic(clkevt->base + JH7110_TIMER_INT_CLR, value,
-+ !(value & JH7110_TIMER_INT_CLR_AVA_MASK),
-+ JH7110_DELAY_US, JH7110_TIMEOUT_US);
-+ if (!ret)
-+ writel(JH7110_TIMER_INT_CLR_ENA, clkevt->base + JH7110_TIMER_INT_CLR);
-+
-+ return ret;
-+}
-+
-+static int jh7110_timer_start(struct jh7110_clkevt *clkevt)
-+{
-+ int ret;
-+
-+ /* Disable and clear interrupt first */
-+ writel(JH7110_TIMER_INT_DIS, clkevt->base + JH7110_TIMER_INT_MASK);
-+ ret = jh7110_timer_int_clear(clkevt);
-+ if (ret)
-+ return ret;
-+
-+ writel(JH7110_TIMER_INT_ENA, clkevt->base + JH7110_TIMER_INT_MASK);
-+ writel(JH7110_TIMER_ENA, clkevt->base + JH7110_TIMER_ENABLE);
-+
-+ return 0;
-+}
-+
-+static int jh7110_timer_shutdown(struct clock_event_device *evt)
-+{
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+ writel(JH7110_TIMER_DIS, clkevt->base + JH7110_TIMER_ENABLE);
-+ return jh7110_timer_int_clear(clkevt);
-+}
-+
-+static void jh7110_timer_suspend(struct clock_event_device *evt)
-+{
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+ clkevt->reload_val = readl(clkevt->base + JH7110_TIMER_LOAD);
-+ jh7110_timer_shutdown(evt);
-+}
-+
-+static void jh7110_timer_resume(struct clock_event_device *evt)
-+{
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+ writel(clkevt->reload_val, clkevt->base + JH7110_TIMER_LOAD);
-+ writel(JH7110_TIMER_RELOAD_VALUE, clkevt->base + JH7110_TIMER_RELOAD);
-+ jh7110_timer_start(clkevt);
-+}
-+
-+static int jh7110_timer_tick_resume(struct clock_event_device *evt)
-+{
-+ jh7110_timer_resume(evt);
-+
-+ return 0;
-+}
-+
-+/* IRQ handler for the timer */
-+static irqreturn_t jh7110_timer_interrupt(int irq, void *priv)
-+{
-+ struct clock_event_device *evt = (struct clock_event_device *)priv;
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+ if (jh7110_timer_int_clear(clkevt))
-+ return IRQ_NONE;
-+
-+ if (evt->event_handler)
-+ evt->event_handler(evt);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int jh7110_timer_set_periodic(struct clock_event_device *evt)
-+{
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+ u32 periodic = DIV_ROUND_CLOSEST(clkevt->rate, HZ);
-+
-+ writel(JH7110_TIMER_MODE_CONTIN, clkevt->base + JH7110_TIMER_CTL);
-+ writel(periodic, clkevt->base + JH7110_TIMER_LOAD);
-+
-+ return jh7110_timer_start(clkevt);
-+}
-+
-+static int jh7110_timer_set_oneshot(struct clock_event_device *evt)
-+{
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+ writel(JH7110_TIMER_MODE_SINGLE, clkevt->base + JH7110_TIMER_CTL);
-+ writel(JH7110_TIMER_MAX_TICKS, clkevt->base + JH7110_TIMER_LOAD);
-+
-+ return jh7110_timer_start(clkevt);
-+}
-+
-+static int jh7110_timer_set_next_event(unsigned long next,
-+ struct clock_event_device *evt)
-+{
-+ struct jh7110_clkevt *clkevt = to_jh7110_clkevt(evt);
-+
-+ writel(JH7110_TIMER_MODE_SINGLE, clkevt->base + JH7110_TIMER_CTL);
-+ writel(next, clkevt->base + JH7110_TIMER_LOAD);
-+
-+ return jh7110_timer_start(clkevt);
-+}
-+
-+static void jh7110_set_clockevent(struct clock_event_device *evt)
-+{
-+ evt->features = CLOCK_EVT_FEAT_PERIODIC |
-+ CLOCK_EVT_FEAT_ONESHOT |
-+ CLOCK_EVT_FEAT_DYNIRQ;
-+ evt->set_state_shutdown = jh7110_timer_shutdown;
-+ evt->set_state_periodic = jh7110_timer_set_periodic;
-+ evt->set_state_oneshot = jh7110_timer_set_oneshot;
-+ evt->set_state_oneshot_stopped = jh7110_timer_shutdown;
-+ evt->tick_resume = jh7110_timer_tick_resume;
-+ evt->set_next_event = jh7110_timer_set_next_event;
-+ evt->suspend = jh7110_timer_suspend;
-+ evt->resume = jh7110_timer_resume;
-+ evt->rating = JH7110_CLOCKEVENT_RATING;
-+}
-+
-+static u64 jh7110_timer_clocksource_read(struct clocksource *cs)
-+{
-+ struct jh7110_clkevt *clkevt = container_of(cs, struct jh7110_clkevt, cs);
-+
-+ return (u64)readl(clkevt->base + JH7110_TIMER_VALUE);
-+}
-+
-+static int jh7110_clocksource_init(struct jh7110_clkevt *clkevt)
-+{
-+ int ret;
-+
-+ clkevt->cs.name = clkevt->name;
-+ clkevt->cs.rating = JH7110_CLOCK_SOURCE_RATING;
-+ clkevt->cs.read = jh7110_timer_clocksource_read;
-+ clkevt->cs.mask = CLOCKSOURCE_MASK(JH7110_VALID_BITS);
-+ clkevt->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS;
-+
-+ ret = clocksource_register_hz(&clkevt->cs, clkevt->rate);
-+ if (ret)
-+ return ret;
-+
-+ clkevt->cs_is_valid = true; /* clocksource register done */
-+ writel(JH7110_TIMER_MODE_CONTIN, clkevt->base + JH7110_TIMER_CTL);
-+ writel(JH7110_TIMER_MAX_TICKS, clkevt->base + JH7110_TIMER_LOAD);
-+
-+ return jh7110_timer_start(clkevt);
-+}
-+
-+static void jh7110_clockevents_register(struct jh7110_clkevt *clkevt)
-+{
-+ clkevt->rate = clk_get_rate(clkevt->clk);
-+
-+ jh7110_set_clockevent(&clkevt->evt);
-+ clkevt->evt.name = clkevt->name;
-+ clkevt->evt.cpumask = cpu_possible_mask;
-+
-+ clockevents_config_and_register(&clkevt->evt, clkevt->rate,
-+ JH7110_TIMER_MIN_TICKS, JH7110_TIMER_MAX_TICKS);
-+}
-+
-+static void jh7110_timer_release(void *data)
-+{
-+ struct jh7110_timer_priv *priv = data;
-+ int i;
-+
-+ for (i = 0; i < JH7110_TIMER_CH_MAX; i++) {
-+ /* Disable each channel of timer */
-+ if (priv->clkevt[i].base)
-+ writel(JH7110_TIMER_DIS, priv->clkevt[i].base + JH7110_TIMER_ENABLE);
-+
-+ /* Avoid no initialization in the loop of the probe */
-+ if (!IS_ERR_OR_NULL(priv->clkevt[i].rst))
-+ reset_control_assert(priv->clkevt[i].rst);
-+
-+ if (priv->clkevt[i].cs_is_valid)
-+ clocksource_unregister(&priv->clkevt[i].cs);
-+ }
-+
-+ reset_control_assert(priv->prst);
-+}
-+
-+static int jh7110_timer_probe(struct platform_device *pdev)
-+{
-+ struct jh7110_timer_priv *priv;
-+ struct jh7110_clkevt *clkevt;
-+ char name[sizeof("chX")];
-+ int ch;
-+ int ret;
-+ void __iomem *base;
-+
-+ priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-+ if (!priv)
-+ return -ENOMEM;
-+
-+ base = devm_platform_ioremap_resource(pdev, 0);
-+ if (IS_ERR(base))
-+ return dev_err_probe(&pdev->dev, PTR_ERR(base),
-+ "failed to map registers\n");
-+
-+ priv->prst = devm_reset_control_get_exclusive(&pdev->dev, "apb");
-+ if (IS_ERR(priv->prst))
-+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->prst),
-+ "failed to get apb reset\n");
-+
-+ priv->pclk = devm_clk_get_enabled(&pdev->dev, "apb");
-+ if (IS_ERR(priv->pclk))
-+ return dev_err_probe(&pdev->dev, PTR_ERR(priv->pclk),
-+ "failed to get & enable apb clock\n");
-+
-+ ret = reset_control_deassert(priv->prst);
-+ if (ret)
-+ return dev_err_probe(&pdev->dev, ret, "failed to deassert apb reset\n");
-+
-+ ret = devm_add_action_or_reset(&pdev->dev, jh7110_timer_release, priv);
-+ if (ret)
-+ return ret;
-+
-+ for (ch = 0; ch < JH7110_TIMER_CH_MAX; ch++) {
-+ clkevt = &priv->clkevt[ch];
-+ snprintf(name, sizeof(name), "ch%d", ch);
-+
-+ clkevt->base = base + JH7110_TIMER_CH_BASE(ch);
-+ /* Ensure timer is disabled */
-+ writel(JH7110_TIMER_DIS, clkevt->base + JH7110_TIMER_ENABLE);
-+
-+ clkevt->rst = devm_reset_control_get_exclusive(&pdev->dev, name);
-+ if (IS_ERR(clkevt->rst))
-+ return PTR_ERR(clkevt->rst);
-+
-+ clkevt->clk = devm_clk_get_enabled(&pdev->dev, name);
-+ if (IS_ERR(clkevt->clk))
-+ return PTR_ERR(clkevt->clk);
-+
-+ ret = reset_control_deassert(clkevt->rst);
-+ if (ret)
-+ return ret;
-+
-+ clkevt->evt.irq = platform_get_irq(pdev, ch);
-+ if (clkevt->evt.irq < 0)
-+ return clkevt->evt.irq;
-+
-+ snprintf(clkevt->name, sizeof(clkevt->name), "jh7110-timer.ch%d", ch);
-+ jh7110_clockevents_register(clkevt);
-+
-+ ret = devm_request_irq(&pdev->dev, clkevt->evt.irq, jh7110_timer_interrupt,
-+ IRQF_TIMER | IRQF_IRQPOLL,
-+ clkevt->name, &clkevt->evt);
-+ if (ret)
-+ return ret;
-+
-+ ret = jh7110_clocksource_init(clkevt);
-+ if (ret)
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id jh7110_timer_match[] = {
-+ { .compatible = "starfive,jh7110-timer", },
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, jh7110_timer_match);
-+
-+static struct platform_driver jh7110_timer_driver = {
-+ .probe = jh7110_timer_probe,
-+ .driver = {
-+ .name = "jh7110-timer",
-+ .of_match_table = jh7110_timer_match,
-+ },
-+};
-+module_platform_driver(jh7110_timer_driver);
-+
-+MODULE_AUTHOR("Xingyu Wu <xingyu.wu@starfivetech.com>");
-+MODULE_DESCRIPTION("StarFive JH7110 timer driver");
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From 4afaa19bcf6eac558a38468417520b65801e0cfd Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Fri, 22 Dec 2023 17:45:46 +0800
-Subject: [PATCH 03/55] pwm: opencores: Add PWM driver support
-
-Add driver for OpenCores PWM Controller. And add compatibility code
-which based on StarFive SoC.
-
-Co-developed-by: Hal Feng <hal.feng@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
----
- drivers/pwm/Kconfig | 12 ++
- drivers/pwm/Makefile | 1 +
- drivers/pwm/pwm-ocores.c | 230 +++++++++++++++++++++++++++++++++++++++
- 3 files changed, 243 insertions(+)
- create mode 100644 drivers/pwm/pwm-ocores.c
-
---- a/drivers/pwm/Kconfig
-+++ b/drivers/pwm/Kconfig
-@@ -471,6 +471,18 @@ config PWM_NTXEC
- controller found in certain e-book readers designed by the original
- design manufacturer Netronix.
-
-+config PWM_OCORES
-+ tristate "OpenCores PWM support"
-+ depends on HAS_IOMEM && OF
-+ depends on COMMON_CLK
-+ depends on ARCH_STARFIVE || COMPILE_TEST
-+ help
-+ If you say yes to this option, support will be included for the
-+ OpenCores PWM. For details see https://opencores.org/projects/ptc.
-+
-+ To compile this driver as a module, choose M here: the module
-+ will be called pwm-ocores.
-+
- config PWM_OMAP_DMTIMER
- tristate "OMAP Dual-Mode Timer PWM support"
- depends on OF
---- a/drivers/pwm/Makefile
-+++ b/drivers/pwm/Makefile
-@@ -42,6 +42,7 @@ obj-$(CONFIG_PWM_MICROCHIP_CORE) += pwm-
- obj-$(CONFIG_PWM_MTK_DISP) += pwm-mtk-disp.o
- obj-$(CONFIG_PWM_MXS) += pwm-mxs.o
- obj-$(CONFIG_PWM_NTXEC) += pwm-ntxec.o
-+obj-$(CONFIG_PWM_OCORES) += pwm-ocores.o
- obj-$(CONFIG_PWM_OMAP_DMTIMER) += pwm-omap-dmtimer.o
- obj-$(CONFIG_PWM_PCA9685) += pwm-pca9685.o
- obj-$(CONFIG_PWM_PXA) += pwm-pxa.o
---- /dev/null
-+++ b/drivers/pwm/pwm-ocores.c
-@@ -0,0 +1,225 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * OpenCores PWM Driver
-+ *
-+ * https://opencores.org/projects/ptc
-+ *
-+ * Copyright (C) 2018-2023 StarFive Technology Co., Ltd.
-+ *
-+ * Limitations:
-+ * - The hardware only do inverted polarity.
-+ * - The hardware minimum period / duty_cycle is (1 / pwm_apb clock frequency) ns.
-+ * - The hardware maximum period / duty_cycle is (U32_MAX / pwm_apb clock frequency) ns.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_device.h>
-+#include <linux/platform_device.h>
-+#include <linux/pwm.h>
-+#include <linux/reset.h>
-+#include <linux/slab.h>
-+
-+/* OCPWM_CTRL register bits*/
-+#define REG_OCPWM_EN BIT(0)
-+#define REG_OCPWM_ECLK BIT(1)
-+#define REG_OCPWM_NEC BIT(2)
-+#define REG_OCPWM_OE BIT(3)
-+#define REG_OCPWM_SIGNLE BIT(4)
-+#define REG_OCPWM_INTE BIT(5)
-+#define REG_OCPWM_INT BIT(6)
-+#define REG_OCPWM_CNTRRST BIT(7)
-+#define REG_OCPWM_CAPTE BIT(8)
-+
-+struct ocores_pwm_device {
-+ struct clk *clk;
-+ struct reset_control *rst;
-+ const struct ocores_pwm_data *data;
-+ void __iomem *regs;
-+ u32 clk_rate; /* PWM APB clock frequency */
-+};
-+
-+struct ocores_pwm_data {
-+ void __iomem *(*get_ch_base)(void __iomem *base, unsigned int channel);
-+};
-+
-+static inline u32 ocores_readl(struct ocores_pwm_device *ddata,
-+ unsigned int channel,
-+ unsigned int offset)
-+{
-+ void __iomem *base = ddata->data->get_ch_base ?
-+ ddata->data->get_ch_base(ddata->regs, channel) : ddata->regs;
-+
-+ return readl(base + offset);
-+}
-+
-+static inline void ocores_writel(struct ocores_pwm_device *ddata,
-+ unsigned int channel,
-+ unsigned int offset, u32 val)
-+{
-+ void __iomem *base = ddata->data->get_ch_base ?
-+ ddata->data->get_ch_base(ddata->regs, channel) : ddata->regs;
-+
-+ writel(val, base + offset);
-+}
-+
-+static inline struct ocores_pwm_device *chip_to_ocores(struct pwm_chip *chip)
-+{
-+ return pwmchip_get_drvdata(chip);
-+}
-+
-+static void __iomem *starfive_jh71x0_get_ch_base(void __iomem *base,
-+ unsigned int channel)
-+{
-+ unsigned int offset = (channel > 3 ? 1 << 15 : 0) + (channel & 3) * 0x10;
-+
-+ return base + offset;
-+}
-+
-+static int ocores_pwm_get_state(struct pwm_chip *chip,
-+ struct pwm_device *pwm,
-+ struct pwm_state *state)
-+{
-+ struct ocores_pwm_device *ddata = chip_to_ocores(chip);
-+ u32 period_data, duty_data, ctrl_data;
-+
-+ period_data = ocores_readl(ddata, pwm->hwpwm, 0x8);
-+ duty_data = ocores_readl(ddata, pwm->hwpwm, 0x4);
-+ ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
-+
-+ state->period = DIV_ROUND_UP_ULL((u64)period_data * NSEC_PER_SEC, ddata->clk_rate);
-+ state->duty_cycle = DIV_ROUND_UP_ULL((u64)duty_data * NSEC_PER_SEC, ddata->clk_rate);
-+ state->polarity = PWM_POLARITY_INVERSED;
-+ state->enabled = (ctrl_data & REG_OCPWM_EN) ? true : false;
-+
-+ return 0;
-+}
-+
-+static int ocores_pwm_apply(struct pwm_chip *chip,
-+ struct pwm_device *pwm,
-+ const struct pwm_state *state)
-+{
-+ struct ocores_pwm_device *ddata = chip_to_ocores(chip);
-+ u32 ctrl_data = 0;
-+ u64 period_data, duty_data;
-+
-+ if (state->polarity != PWM_POLARITY_INVERSED)
-+ return -EINVAL;
-+
-+ ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
-+ ocores_writel(ddata, pwm->hwpwm, 0xC, 0);
-+
-+ period_data = DIV_ROUND_DOWN_ULL(state->period * ddata->clk_rate, NSEC_PER_SEC);
-+ if (period_data <= U32_MAX)
-+ ocores_writel(ddata, pwm->hwpwm, 0x8, (u32)period_data);
-+ else
-+ return -EINVAL;
-+
-+ duty_data = DIV_ROUND_DOWN_ULL(state->duty_cycle * ddata->clk_rate, NSEC_PER_SEC);
-+ if (duty_data <= U32_MAX)
-+ ocores_writel(ddata, pwm->hwpwm, 0x4, (u32)duty_data);
-+ else
-+ return -EINVAL;
-+
-+ ocores_writel(ddata, pwm->hwpwm, 0xC, 0);
-+
-+ if (state->enabled) {
-+ ctrl_data = ocores_readl(ddata, pwm->hwpwm, 0xC);
-+ ocores_writel(ddata, pwm->hwpwm, 0xC, ctrl_data | REG_OCPWM_EN | REG_OCPWM_OE);
-+ }
-+
-+ return 0;
-+}
-+
-+static const struct pwm_ops ocores_pwm_ops = {
-+ .get_state = ocores_pwm_get_state,
-+ .apply = ocores_pwm_apply,
-+};
-+
-+static const struct ocores_pwm_data jh7100_pwm_data = {
-+ .get_ch_base = starfive_jh71x0_get_ch_base,
-+};
-+
-+static const struct ocores_pwm_data jh7110_pwm_data = {
-+ .get_ch_base = starfive_jh71x0_get_ch_base,
-+};
-+
-+static const struct of_device_id ocores_pwm_of_match[] = {
-+ { .compatible = "opencores,pwm-v1" },
-+ { .compatible = "starfive,jh7100-pwm", .data = &jh7100_pwm_data},
-+ { .compatible = "starfive,jh7110-pwm", .data = &jh7110_pwm_data},
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, ocores_pwm_of_match);
-+
-+static void ocores_reset_control_assert(void *data)
-+{
-+ reset_control_assert(data);
-+}
-+
-+static int ocores_pwm_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct ocores_pwm_device *ddata;
-+ struct pwm_chip *chip;
-+ int ret;
-+
-+ chip = devm_pwmchip_alloc(dev, 8, sizeof(*ddata));
-+ if (IS_ERR(chip))
-+ return PTR_ERR(chip);
-+
-+ chip->ops = &ocores_pwm_ops;
-+
-+ ddata = chip_to_ocores(chip);
-+ ddata->data = of_device_get_match_data(dev);
-+
-+ ddata->regs = devm_platform_ioremap_resource(pdev, 0);
-+ if (IS_ERR(ddata->regs))
-+ return dev_err_probe(dev, PTR_ERR(ddata->regs),
-+ "Unable to map IO resources\n");
-+
-+ ddata->clk = devm_clk_get_enabled(dev, NULL);
-+ if (IS_ERR(ddata->clk))
-+ return dev_err_probe(dev, PTR_ERR(ddata->clk),
-+ "Unable to get pwm's clock\n");
-+
-+ ddata->rst = devm_reset_control_get_optional_exclusive(dev, NULL);
-+ if (IS_ERR(ddata->rst))
-+ return dev_err_probe(dev, PTR_ERR(ddata->rst),
-+ "Unable to get pwm's reset\n");
-+
-+ reset_control_deassert(ddata->rst);
-+
-+ ret = devm_add_action_or_reset(dev, ocores_reset_control_assert, ddata->rst);
-+ if (ret)
-+ return ret;
-+
-+ ddata->clk_rate = clk_get_rate(ddata->clk);
-+ if (ddata->clk_rate <= 0)
-+ return dev_err_probe(dev, ddata->clk_rate,
-+ "Unable to get clock's rate\n");
-+
-+ ret = devm_pwmchip_add(dev, chip);
-+ if (ret < 0)
-+ return dev_err_probe(dev, ret, "Could not register PWM chip\n");
-+
-+ platform_set_drvdata(pdev, ddata);
-+
-+ return ret;
-+}
-+
-+static struct platform_driver ocores_pwm_driver = {
-+ .probe = ocores_pwm_probe,
-+ .driver = {
-+ .name = "ocores-pwm",
-+ .of_match_table = ocores_pwm_of_match,
-+ },
-+};
-+module_platform_driver(ocores_pwm_driver);
-+
-+MODULE_AUTHOR("Jieqin Chen");
-+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("OpenCores PWM PTC driver");
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From c0d35bd6e76ccabfbbbddc41a0d77ecdfbb4ee31 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfivetech.com>
-Date: Sun, 4 Feb 2024 10:35:24 +0800
-Subject: [PATCH 04/55] spi: spl022: Get and deassert reset in probe()
-
-This fix spi1~6 communication time out.
-
-Signed-off-by: ziv.xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 17 +++++++++++++++++
- 1 file changed, 17 insertions(+)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -33,6 +33,7 @@
- #include <linux/pm_runtime.h>
- #include <linux/of.h>
- #include <linux/pinctrl/consumer.h>
-+#include <linux/reset.h>
-
- /*
- * This macro is used to define some register default values.
-@@ -363,6 +364,7 @@ struct pl022 {
- resource_size_t phybase;
- void __iomem *virtbase;
- struct clk *clk;
-+ struct reset_control *rst;
- struct spi_controller *host;
- struct pl022_ssp_controller *host_info;
- struct spi_transfer *cur_transfer;
-@@ -1930,6 +1932,19 @@ static int pl022_probe(struct amba_devic
- goto err_no_clk;
- }
-
-+ pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-+ if (IS_ERR(pl022->rst)) {
-+ status = PTR_ERR(pl022->rst);
-+ dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
-+ goto err_no_rst;
-+ }
-+
-+ status = reset_control_deassert(pl022->rst);
-+ if (status) {
-+ dev_err(&adev->dev, "could not deassert SSP/SPI bus reset\n");
-+ goto err_no_rst_de;
-+ }
-+
- /* Disable SSP */
- writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
- SSP_CR1(pl022->virtbase));
-@@ -1985,6 +2000,8 @@ static int pl022_probe(struct amba_devic
- if (platform_info->enable_dma)
- pl022_dma_remove(pl022);
- err_no_irq:
-+ err_no_rst_de:
-+ err_no_rst:
- err_no_clk:
- err_no_ioremap:
- amba_release_regions(adev);
+++ /dev/null
-From a37f1f4370af69644c512e5e296a10357338c310 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Fri, 12 May 2023 17:33:20 +0800
-Subject: [PATCH 05/55] i2c: designware: Delete SMBus functionalities
-
-The driver didn't implement the smbus interface,
-so replace the SMBus functionalities with
-I2C_FUNC_SMBUS_EMUL.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/i2c/busses/i2c-designware-core.h | 10 ++++------
- 1 file changed, 4 insertions(+), 6 deletions(-)
-
---- a/drivers/i2c/busses/i2c-designware-core.h
-+++ b/drivers/i2c/busses/i2c-designware-core.h
-@@ -17,12 +17,10 @@
- #include <linux/regmap.h>
- #include <linux/types.h>
-
--#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | \
-- I2C_FUNC_SMBUS_BYTE | \
-- I2C_FUNC_SMBUS_BYTE_DATA | \
-- I2C_FUNC_SMBUS_WORD_DATA | \
-- I2C_FUNC_SMBUS_BLOCK_DATA | \
-- I2C_FUNC_SMBUS_I2C_BLOCK)
-+#define DW_IC_DEFAULT_FUNCTIONALITY (I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL \
-+ & ~I2C_FUNC_SMBUS_QUICK \
-+ & ~I2C_FUNC_SMBUS_PROC_CALL \
-+ & ~I2C_FUNC_SMBUS_PEC))
-
- #define DW_IC_CON_MASTER BIT(0)
- #define DW_IC_CON_SPEED_STD (1 << 1)
+++ /dev/null
-From 8850887a7b71b55250be2a15802963d6b32ea8ab Mon Sep 17 00:00:00 2001
-From: Ziv Xu <ziv.xu@starfivetech.com>
-Date: Fri, 19 Jan 2024 15:22:55 +0800
-Subject: [PATCH 06/55] drivers: mtd: gigadevice: add gd25lq256d 32M flash
- support
-
-add gd25lq256d 32M flash support
-
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/mtd/spi-nor/gigadevice.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/mtd/spi-nor/gigadevice.c
-+++ b/drivers/mtd/spi-nor/gigadevice.c
-@@ -95,6 +95,12 @@ static const struct flash_info gigadevic
- .size = SZ_16M,
- .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB,
- .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
-+ }, {
-+ .id = SNOR_ID(0xc8, 0x60, 0x19),
-+ .name = "gd25lq256d",
-+ .size = SZ_32M,
-+ .flags = SPI_NOR_HAS_LOCK | SPI_NOR_HAS_TB | SPI_NOR_QUAD_PP,
-+ .no_sfdp_flags = SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ,
- },
- };
-
+++ /dev/null
-From f7db05ea5fffebed6db6693333a6877aa707b16d Mon Sep 17 00:00:00 2001
-From: "shanlong.li" <shanlong.li@starfivetech.com>
-Date: Thu, 8 Jun 2023 00:07:15 -0700
-Subject: [PATCH 07/55] driver: mailbox: Add mailbox driver
-
-Add mailbox driver.
-
-Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/mailbox/Kconfig | 13 +
- drivers/mailbox/Makefile | 4 +
- drivers/mailbox/starfive_mailbox-test.c | 405 ++++++++++++++++++++++++
- drivers/mailbox/starfive_mailbox.c | 345 ++++++++++++++++++++
- 4 files changed, 767 insertions(+)
- create mode 100644 drivers/mailbox/starfive_mailbox-test.c
- create mode 100644 drivers/mailbox/starfive_mailbox.c
-
---- a/drivers/mailbox/Kconfig
-+++ b/drivers/mailbox/Kconfig
-@@ -295,4 +295,17 @@ config QCOM_IPCC
- acts as an interrupt controller for receiving interrupts from clients.
- Say Y here if you want to build this driver.
-
-+config STARFIVE_MBOX
-+ tristate "Platform Starfive Mailbox"
-+ depends on OF
-+ help
-+ Say Y here if you want to build a platform specific variant RISCV
-+ controller driver.
-+
-+config STARFIVE_MBOX_TEST
-+ tristate "Starfive Mailbox Test Client"
-+ depends on OF
-+ depends on HAS_IOMEM
-+ help
-+ Test client to help with testing new Controller driver implementations.
- endif
---- a/drivers/mailbox/Makefile
-+++ b/drivers/mailbox/Makefile
-@@ -64,3 +64,7 @@ obj-$(CONFIG_SPRD_MBOX) += sprd-mailbox
- obj-$(CONFIG_QCOM_CPUCP_MBOX) += qcom-cpucp-mbox.o
-
- obj-$(CONFIG_QCOM_IPCC) += qcom-ipcc.o
-+
-+obj-$(CONFIG_STARFIVE_MBOX) += starfive_mailbox.o
-+ccflags-$(CONFIG_STARFIVE_MBOX) := -Wno-error=missing-prototypes
-+obj-$(CONFIG_STARFIVE_MBOX_TEST) += starfive_mailbox-test.o
---- /dev/null
-+++ b/drivers/mailbox/starfive_mailbox-test.c
-@@ -0,0 +1,405 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2015 ST Microelectronics
-+ *
-+ * Author: Lee Jones <lee.jones@linaro.org>
-+ */
-+
-+#include <linux/debugfs.h>
-+#include <linux/err.h>
-+#include <linux/fs.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/mailbox_client.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/poll.h>
-+#include <linux/slab.h>
-+#include <linux/uaccess.h>
-+#include <linux/sched/signal.h>
-+
-+#include <linux/mailbox_controller.h>
-+
-+#define MBOX_MAX_SIG_LEN 8
-+#define MBOX_MAX_MSG_LEN 16
-+#define MBOX_BYTES_PER_LINE 16
-+#define MBOX_HEXDUMP_LINE_LEN ((MBOX_BYTES_PER_LINE * 4) + 2)
-+#define MBOX_HEXDUMP_MAX_LEN (MBOX_HEXDUMP_LINE_LEN * (MBOX_MAX_MSG_LEN / MBOX_BYTES_PER_LINE))
-+
-+static bool mbox_data_ready;
-+
-+struct mbox_test_device {
-+ struct device *dev;
-+ void __iomem *tx_mmio;
-+ void __iomem *rx_mmio;
-+ struct mbox_chan *tx_channel;
-+ struct mbox_chan *rx_channel;
-+ char *rx_buffer;
-+ char *signal;
-+ char *message;
-+ spinlock_t lock;
-+ wait_queue_head_t waitq;
-+ struct fasync_struct *async_queue;
-+ struct dentry *root_debugfs_dir;
-+};
-+
-+static ssize_t mbox_test_signal_write(struct file *filp,
-+ const char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct mbox_test_device *tdev = filp->private_data;
-+
-+ if (!tdev->tx_channel) {
-+ dev_err(tdev->dev, "Channel cannot do Tx\n");
-+ return -EINVAL;
-+ }
-+
-+ if (count > MBOX_MAX_SIG_LEN) {
-+ dev_err(tdev->dev,
-+ "Signal length %zd greater than max allowed %d\n",
-+ count, MBOX_MAX_SIG_LEN);
-+ return -EINVAL;
-+ }
-+
-+ /* Only allocate memory if we need to */
-+ if (!tdev->signal) {
-+ tdev->signal = kzalloc(MBOX_MAX_SIG_LEN, GFP_KERNEL);
-+ if (!tdev->signal)
-+ return -ENOMEM;
-+ }
-+
-+ if (copy_from_user(tdev->signal, userbuf, count)) {
-+ kfree(tdev->signal);
-+ tdev->signal = NULL;
-+ return -EFAULT;
-+ }
-+
-+ return count;
-+}
-+
-+static const struct file_operations mbox_test_signal_ops = {
-+ .write = mbox_test_signal_write,
-+ .open = simple_open,
-+ .llseek = generic_file_llseek,
-+};
-+
-+static int mbox_test_message_fasync(int fd, struct file *filp, int on)
-+{
-+ struct mbox_test_device *tdev = filp->private_data;
-+
-+ return fasync_helper(fd, filp, on, &tdev->async_queue);
-+}
-+
-+static ssize_t mbox_test_message_write(struct file *filp,
-+ const char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct mbox_test_device *tdev = filp->private_data;
-+ void *data;
-+ int ret;
-+
-+ if (!tdev->tx_channel) {
-+ dev_err(tdev->dev, "Channel cannot do Tx\n");
-+ return -EINVAL;
-+ }
-+
-+ if (count > MBOX_MAX_MSG_LEN) {
-+ dev_err(tdev->dev,
-+ "Message length %zd greater than max allowed %d\n",
-+ count, MBOX_MAX_MSG_LEN);
-+ return -EINVAL;
-+ }
-+
-+ tdev->message = kzalloc(MBOX_MAX_MSG_LEN, GFP_KERNEL);
-+ if (!tdev->message)
-+ return -ENOMEM;
-+
-+ ret = copy_from_user(tdev->message, userbuf, count);
-+ if (ret) {
-+ ret = -EFAULT;
-+ goto out;
-+ }
-+
-+ if (tdev->tx_mmio && tdev->signal) {
-+ print_hex_dump_bytes("Client: Sending: Signal: ", DUMP_PREFIX_ADDRESS,
-+ tdev->signal, MBOX_MAX_SIG_LEN);
-+
-+ data = tdev->signal;
-+ } else
-+ data = tdev->message;
-+
-+ print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
-+ tdev->message, MBOX_MAX_MSG_LEN);
-+
-+ ret = mbox_send_message(tdev->tx_channel, data);
-+ mbox_chan_txdone(tdev->tx_channel, ret);
-+ if (ret < 0)
-+ dev_err(tdev->dev, "Failed to send message via mailbox\n");
-+
-+out:
-+ kfree(tdev->signal);
-+ kfree(tdev->message);
-+ tdev->signal = NULL;
-+
-+ return ret < 0 ? ret : count;
-+}
-+
-+static bool mbox_test_message_data_ready(struct mbox_test_device *tdev)
-+{
-+ bool data_ready;
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&tdev->lock, flags);
-+ data_ready = mbox_data_ready;
-+ spin_unlock_irqrestore(&tdev->lock, flags);
-+
-+ return data_ready;
-+}
-+
-+static ssize_t mbox_test_message_read(struct file *filp, char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct mbox_test_device *tdev = filp->private_data;
-+ unsigned long flags;
-+ char *touser, *ptr;
-+ int ret;
-+
-+ touser = kzalloc(MBOX_HEXDUMP_MAX_LEN + 1, GFP_KERNEL);
-+ if (!touser)
-+ return -ENOMEM;
-+
-+ if (!tdev->rx_channel) {
-+ ret = snprintf(touser, 20, "<NO RX CAPABILITY>\n");
-+ ret = simple_read_from_buffer(userbuf, count, ppos,
-+ touser, ret);
-+ goto kfree_err;
-+ }
-+
-+ do {
-+ if (mbox_test_message_data_ready(tdev))
-+ break;
-+
-+ if (filp->f_flags & O_NONBLOCK) {
-+ ret = -EAGAIN;
-+ goto waitq_err;
-+ }
-+
-+ if (signal_pending(current)) {
-+ ret = -ERESTARTSYS;
-+ goto waitq_err;
-+ }
-+ schedule();
-+
-+ } while (1);
-+
-+ spin_lock_irqsave(&tdev->lock, flags);
-+
-+ ptr = tdev->rx_buffer;
-+
-+ mbox_data_ready = false;
-+
-+ spin_unlock_irqrestore(&tdev->lock, flags);
-+ if (copy_to_user((void __user *)userbuf, ptr, 4))
-+ ret = -EFAULT;
-+
-+waitq_err:
-+ __set_current_state(TASK_RUNNING);
-+kfree_err:
-+ kfree(touser);
-+ return ret;
-+}
-+
-+static __poll_t
-+mbox_test_message_poll(struct file *filp, struct poll_table_struct *wait)
-+{
-+ struct mbox_test_device *tdev = filp->private_data;
-+
-+ poll_wait(filp, &tdev->waitq, wait);
-+
-+ if (mbox_test_message_data_ready(tdev))
-+ return EPOLLIN | EPOLLRDNORM;
-+ return 0;
-+}
-+
-+static const struct file_operations mbox_test_message_ops = {
-+ .write = mbox_test_message_write,
-+ .read = mbox_test_message_read,
-+ .fasync = mbox_test_message_fasync,
-+ .poll = mbox_test_message_poll,
-+ .open = simple_open,
-+ .llseek = generic_file_llseek,
-+};
-+
-+static int mbox_test_add_debugfs(struct platform_device *pdev,
-+ struct mbox_test_device *tdev)
-+{
-+ if (!debugfs_initialized())
-+ return 0;
-+
-+ tdev->root_debugfs_dir = debugfs_create_dir(dev_name(&pdev->dev), NULL);
-+ if (!tdev->root_debugfs_dir) {
-+ dev_err(&pdev->dev, "Failed to create Mailbox debugfs\n");
-+ return -EINVAL;
-+ }
-+
-+ debugfs_create_file("message", 0600, tdev->root_debugfs_dir,
-+ tdev, &mbox_test_message_ops);
-+
-+ debugfs_create_file("signal", 0200, tdev->root_debugfs_dir,
-+ tdev, &mbox_test_signal_ops);
-+
-+ return 0;
-+}
-+
-+static void mbox_test_receive_message(struct mbox_client *client, void *message)
-+{
-+ struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
-+ unsigned long flags;
-+
-+ spin_lock_irqsave(&tdev->lock, flags);
-+ if (tdev->rx_mmio) {
-+ memcpy_fromio(tdev->rx_buffer, tdev->rx_mmio, MBOX_MAX_MSG_LEN);
-+ print_hex_dump_bytes("Client: Received [MMIO]: ", DUMP_PREFIX_ADDRESS,
-+ tdev->rx_buffer, MBOX_MAX_MSG_LEN);
-+ } else if (message) {
-+ print_hex_dump_bytes("Client: Received [API]: ", DUMP_PREFIX_ADDRESS,
-+ message, MBOX_MAX_MSG_LEN);
-+ memcpy(tdev->rx_buffer, message, MBOX_MAX_MSG_LEN);
-+ }
-+ mbox_data_ready = true;
-+ spin_unlock_irqrestore(&tdev->lock, flags);
-+}
-+
-+static void mbox_test_prepare_message(struct mbox_client *client, void *message)
-+{
-+ struct mbox_test_device *tdev = dev_get_drvdata(client->dev);
-+
-+ if (tdev->tx_mmio) {
-+ if (tdev->signal)
-+ memcpy_toio(tdev->tx_mmio, tdev->message, MBOX_MAX_MSG_LEN);
-+ else
-+ memcpy_toio(tdev->tx_mmio, message, MBOX_MAX_MSG_LEN);
-+ }
-+}
-+
-+static struct mbox_chan *
-+mbox_test_request_channel(struct platform_device *pdev, const char *name)
-+{
-+ struct mbox_client *client;
-+ struct mbox_chan *channel;
-+
-+ client = devm_kzalloc(&pdev->dev, sizeof(*client), GFP_KERNEL);
-+ if (!client)
-+ return ERR_PTR(-ENOMEM);
-+
-+ client->dev = &pdev->dev;
-+ client->rx_callback = mbox_test_receive_message;
-+ client->tx_prepare = mbox_test_prepare_message;
-+ client->tx_block = false;
-+ client->knows_txdone = false;
-+ client->tx_tout = 500;
-+
-+ channel = mbox_request_channel_byname(client, name);
-+ if (IS_ERR(channel)) {
-+ dev_warn(&pdev->dev, "Failed to request %s channel\n", name);
-+ return NULL;
-+ }
-+
-+ return channel;
-+}
-+
-+static int mbox_test_probe(struct platform_device *pdev)
-+{
-+ struct mbox_test_device *tdev;
-+ struct resource *res;
-+ resource_size_t size;
-+ int ret;
-+
-+ tdev = devm_kzalloc(&pdev->dev, sizeof(*tdev), GFP_KERNEL);
-+ if (!tdev)
-+ return -ENOMEM;
-+
-+ /* It's okay for MMIO to be NULL */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ tdev->tx_mmio = devm_ioremap_resource(&pdev->dev, res);
-+ if (PTR_ERR(tdev->tx_mmio) == -EBUSY) {
-+ /* if reserved area in SRAM, try just ioremap */
-+ size = resource_size(res);
-+ tdev->tx_mmio = devm_ioremap(&pdev->dev, res->start, size);
-+ } else if (IS_ERR(tdev->tx_mmio)) {
-+ tdev->tx_mmio = NULL;
-+ }
-+
-+ /* If specified, second reg entry is Rx MMIO */
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-+ tdev->rx_mmio = devm_ioremap_resource(&pdev->dev, res);
-+ if (PTR_ERR(tdev->rx_mmio) == -EBUSY) {
-+ size = resource_size(res);
-+ tdev->rx_mmio = devm_ioremap(&pdev->dev, res->start, size);
-+ } else if (IS_ERR(tdev->rx_mmio)) {
-+ tdev->rx_mmio = tdev->tx_mmio;
-+ }
-+
-+ tdev->tx_channel = mbox_test_request_channel(pdev, "tx");
-+ tdev->rx_channel = mbox_test_request_channel(pdev, "rx");
-+
-+ if (!tdev->tx_channel && !tdev->rx_channel)
-+ return -EPROBE_DEFER;
-+
-+ /* If Rx is not specified but has Rx MMIO, then Rx = Tx */
-+ if (!tdev->rx_channel && (tdev->rx_mmio != tdev->tx_mmio))
-+ tdev->rx_channel = tdev->tx_channel;
-+
-+ tdev->dev = &pdev->dev;
-+ platform_set_drvdata(pdev, tdev);
-+
-+ spin_lock_init(&tdev->lock);
-+
-+ if (tdev->rx_channel) {
-+ tdev->rx_buffer = devm_kzalloc(&pdev->dev,
-+ MBOX_MAX_MSG_LEN, GFP_KERNEL);
-+ if (!tdev->rx_buffer)
-+ return -ENOMEM;
-+ }
-+
-+ ret = mbox_test_add_debugfs(pdev, tdev);
-+ if (ret)
-+ return ret;
-+
-+ dev_info(&pdev->dev, "Successfully registered\n");
-+
-+ return 0;
-+}
-+
-+static void mbox_test_remove(struct platform_device *pdev)
-+{
-+ struct mbox_test_device *tdev = platform_get_drvdata(pdev);
-+
-+ debugfs_remove_recursive(tdev->root_debugfs_dir);
-+
-+ if (tdev->tx_channel)
-+ mbox_free_channel(tdev->tx_channel);
-+ if (tdev->rx_channel)
-+ mbox_free_channel(tdev->rx_channel);
-+}
-+
-+static const struct of_device_id mbox_test_match[] = {
-+ { .compatible = "starfive,mailbox-test" },
-+ {},
-+};
-+MODULE_DEVICE_TABLE(of, mbox_test_match);
-+
-+static struct platform_driver mbox_test_driver = {
-+ .driver = {
-+ .name = "mailbox_test",
-+ .of_match_table = mbox_test_match,
-+ },
-+ .probe = mbox_test_probe,
-+ .remove = mbox_test_remove,
-+};
-+module_platform_driver(mbox_test_driver);
-+
-+MODULE_DESCRIPTION("Generic Mailbox Testing Facility");
-+MODULE_AUTHOR("Lee Jones <lee.jones@linaro.org");
-+MODULE_LICENSE("GPL v2");
---- /dev/null
-+++ b/drivers/mailbox/starfive_mailbox.c
-@@ -0,0 +1,345 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * mailbox driver for StarFive JH7110 SoC
-+ *
-+ * Copyright (c) 2021 StarFive Technology Co., Ltd.
-+ * Author: Shanlong Li <shanlong.li@starfivetech.com>
-+ */
-+
-+#include <linux/bitops.h>
-+#include <linux/delay.h>
-+#include <linux/device.h>
-+#include <linux/err.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/iopoll.h>
-+#include <linux/mailbox_controller.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+#include <linux/slab.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/pm_runtime.h>
-+
-+#include "mailbox.h"
-+
-+#define MBOX_CHAN_MAX 4
-+
-+#define MBOX_BASE(mbox, ch) ((mbox)->base + ((ch) * 0x10))
-+#define MBOX_IRQ_REG 0x00
-+#define MBOX_SET_REG 0x04
-+#define MBOX_CLR_REG 0x08
-+#define MBOX_CMD_REG 0x0c
-+#define MBC_PEND_SMRY 0x100
-+
-+typedef enum {
-+ MAILBOX_CORE_U7 = 0,
-+ MAILBOX_CORE_HIFI4,
-+ MAILBOX_CORE_E2,
-+ MAILBOX_CORE_RSVD0,
-+ MAILBOX_CORE_NUM,
-+} mailbox_core_t;
-+
-+struct mailbox_irq_name_c{
-+ int id;
-+ char name[16];
-+};
-+
-+static const struct mailbox_irq_name_c irq_peer_name[MBOX_CHAN_MAX] = {
-+ {MAILBOX_CORE_U7, "u74_core"},
-+ {MAILBOX_CORE_HIFI4, "hifi4_core"},
-+ {MAILBOX_CORE_E2, "e24_core"},
-+ {MAILBOX_CORE_RSVD0, "" },
-+};
-+
-+/**
-+ * starfive mailbox channel information
-+ *
-+ * A channel can be used for TX or RX, it can trigger remote
-+ * processor interrupt to notify remote processor and can receive
-+ * interrupt if has incoming message.
-+ *
-+ * @dst_irq: Interrupt vector for remote processor
-+ * @core_id: id for remote processor
-+ */
-+struct starfive_chan_info {
-+ unsigned int dst_irq;
-+ mailbox_core_t core_id;
-+};
-+
-+/**
-+ * starfive mailbox controller data
-+ *
-+ * Mailbox controller includes 4 channels and can allocate
-+ * channel for message transferring.
-+ *
-+ * @dev: Device to which it is attached
-+ * @base: Base address of the register mapping region
-+ * @chan: Representation of channels in mailbox controller
-+ * @mchan: Representation of channel info
-+ * @controller: Representation of a communication channel controller
-+ */
-+struct starfive_mbox {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct mbox_chan chan[MBOX_CHAN_MAX];
-+ struct starfive_chan_info mchan[MBOX_CHAN_MAX];
-+ struct mbox_controller controller;
-+ struct clk *clk;
-+ struct reset_control *rst_rresetn;
-+};
-+
-+static struct starfive_mbox *to_starfive_mbox(struct mbox_controller *mbox)
-+{
-+ return container_of(mbox, struct starfive_mbox, controller);
-+}
-+
-+static struct mbox_chan *
-+starfive_of_mbox_index_xlate(struct mbox_controller *mbox,
-+ const struct of_phandle_args *sp)
-+{
-+ struct starfive_mbox *sbox;
-+
-+ int ind = sp->args[0];
-+ int core_id = sp->args[1];
-+
-+ if (ind >= mbox->num_chans || core_id >= MAILBOX_CORE_NUM)
-+ return ERR_PTR(-EINVAL);
-+
-+ sbox = to_starfive_mbox(mbox);
-+
-+ sbox->mchan[ind].core_id = core_id;
-+
-+ return &mbox->chans[ind];
-+}
-+
-+static irqreturn_t starfive_rx_irq_handler(int irq, void *p)
-+{
-+ struct mbox_chan *chan = p;
-+ unsigned long ch = (unsigned long)chan->con_priv;
-+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+ void __iomem *base = MBOX_BASE(mbox, ch);
-+ u32 val;
-+
-+ val = readl(base + MBOX_CMD_REG);
-+ if (!val)
-+ return IRQ_NONE;
-+
-+ mbox_chan_received_data(chan, (void *)&val);
-+ writel(val, base + MBOX_CLR_REG);
-+ return IRQ_HANDLED;
-+}
-+
-+static int starfive_mbox_check_state(struct mbox_chan *chan)
-+{
-+ unsigned long ch = (unsigned long)chan->con_priv;
-+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+ unsigned long irq_flag = IRQF_SHARED;
-+ long ret = 0;
-+
-+ pm_runtime_get_sync(mbox->dev);
-+ /* MAILBOX should be with IRQF_NO_SUSPEND set */
-+ if (!mbox->dev->pm_domain)
-+ irq_flag |= IRQF_NO_SUSPEND;
-+
-+ /* Mailbox is idle so directly bail out */
-+ if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch))
-+ return -EBUSY;
-+
-+ if (mbox->mchan[ch].dst_irq > 0) {
-+ dev_dbg(mbox->dev, "%s: host IRQ = %d, ch:%ld", __func__, mbox->mchan[ch].dst_irq, ch);
-+ ret = devm_request_irq(mbox->dev, mbox->mchan[ch].dst_irq, starfive_rx_irq_handler,
-+ irq_flag, irq_peer_name[ch].name, chan);
-+ if (ret < 0)
-+ dev_err(mbox->dev, "request_irq %d failed\n", mbox->mchan[ch].dst_irq);
-+ }
-+
-+ return ret;
-+}
-+
-+static int starfive_mbox_startup(struct mbox_chan *chan)
-+{
-+ return starfive_mbox_check_state(chan);
-+}
-+
-+static void starfive_mbox_shutdown(struct mbox_chan *chan)
-+{
-+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+ unsigned long ch = (unsigned long)chan->con_priv;
-+ void __iomem *base = MBOX_BASE(mbox, ch);
-+
-+ writel(0x0, base + MBOX_IRQ_REG);
-+ writel(0x0, base + MBOX_CLR_REG);
-+
-+ if (mbox->mchan[ch].dst_irq > 0)
-+ devm_free_irq(mbox->dev, mbox->mchan[ch].dst_irq, chan);
-+ pm_runtime_put_sync(mbox->dev);
-+}
-+
-+static int starfive_mbox_send_data(struct mbox_chan *chan, void *msg)
-+{
-+ unsigned long ch = (unsigned long)chan->con_priv;
-+ struct starfive_mbox *mbox = to_starfive_mbox(chan->mbox);
-+ struct starfive_chan_info *mchan = &mbox->mchan[ch];
-+ void __iomem *base = MBOX_BASE(mbox, ch);
-+ u32 *buf = msg;
-+
-+ /* Ensure channel is released */
-+ if (readl(mbox->base + MBC_PEND_SMRY) & BIT(ch)) {
-+ pr_debug("%s:%d. busy\n", __func__, __LINE__);
-+ return -EBUSY;
-+ }
-+
-+ /* Clear mask for destination interrupt */
-+ writel(BIT(mchan->core_id), base + MBOX_IRQ_REG);
-+
-+ /* Fill message data */
-+ writel(*buf, base + MBOX_SET_REG);
-+ return 0;
-+}
-+
-+static struct mbox_chan_ops starfive_mbox_ops = {
-+ .startup = starfive_mbox_startup,
-+ .send_data = starfive_mbox_send_data,
-+ .shutdown = starfive_mbox_shutdown,
-+};
-+
-+static const struct of_device_id starfive_mbox_of_match[] = {
-+ { .compatible = "starfive,mail_box",},
-+ {},
-+};
-+
-+MODULE_DEVICE_TABLE(of, starfive_mbox_of_match);
-+
-+void starfive_mailbox_init(struct starfive_mbox *mbox)
-+{
-+ mbox->clk = devm_clk_get_optional(mbox->dev, "clk_apb");
-+ if (IS_ERR(mbox->clk)) {
-+ dev_err(mbox->dev, "failed to get mailbox\n");
-+ return;
-+ }
-+
-+ mbox->rst_rresetn = devm_reset_control_get_exclusive(mbox->dev, "mbx_rre");
-+ if (IS_ERR(mbox->rst_rresetn)) {
-+ dev_err(mbox->dev, "failed to get mailbox reset\n");
-+ return;
-+ }
-+
-+ clk_prepare_enable(mbox->clk);
-+ reset_control_deassert(mbox->rst_rresetn);
-+}
-+
-+static int starfive_mbox_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct starfive_mbox *mbox;
-+ struct mbox_chan *chan;
-+ struct resource *res;
-+ unsigned long ch;
-+ int err;
-+
-+ mbox = devm_kzalloc(dev, sizeof(*mbox), GFP_KERNEL);
-+ if (!mbox)
-+ return -ENOMEM;
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ mbox->base = devm_ioremap_resource(dev, res);
-+ mbox->dev = dev;
-+
-+ if (IS_ERR(mbox->base))
-+ return PTR_ERR(mbox->base);
-+
-+ starfive_mailbox_init(mbox);
-+
-+ mbox->controller.dev = dev;
-+ mbox->controller.chans = mbox->chan;
-+ mbox->controller.num_chans = MBOX_CHAN_MAX;
-+ mbox->controller.ops = &starfive_mbox_ops;
-+ mbox->controller.of_xlate = starfive_of_mbox_index_xlate;
-+ mbox->controller.txdone_irq = true;
-+ mbox->controller.txdone_poll = false;
-+
-+ /* Initialize mailbox channel data */
-+ chan = mbox->chan;
-+ for (ch = 0; ch < MBOX_CHAN_MAX; ch++) {
-+ mbox->mchan[ch].dst_irq = 0;
-+ mbox->mchan[ch].core_id = (mailbox_core_t)ch;
-+ chan[ch].con_priv = (void *)ch;
-+ }
-+ mbox->mchan[MAILBOX_CORE_HIFI4].dst_irq = platform_get_irq(pdev, 0);
-+ mbox->mchan[MAILBOX_CORE_E2].dst_irq = platform_get_irq(pdev, 1);
-+
-+ err = mbox_controller_register(&mbox->controller);
-+ if (err) {
-+ dev_err(dev, "Failed to register mailbox %d\n", err);
-+ return err;
-+ }
-+
-+ platform_set_drvdata(pdev, mbox);
-+ dev_info(dev, "Mailbox enabled\n");
-+ pm_runtime_set_active(dev);
-+ pm_runtime_enable(dev);
-+
-+ return 0;
-+}
-+
-+static void starfive_mbox_remove(struct platform_device *pdev)
-+{
-+ struct starfive_mbox *mbox = platform_get_drvdata(pdev);
-+
-+ mbox_controller_unregister(&mbox->controller);
-+ devm_clk_put(mbox->dev, mbox->clk);
-+ pm_runtime_disable(mbox->dev);
-+}
-+
-+static int __maybe_unused starfive_mbox_suspend(struct device *dev)
-+{
-+ struct starfive_mbox *mbox = dev_get_drvdata(dev);
-+
-+ clk_disable_unprepare(mbox->clk);
-+
-+ return 0;
-+}
-+
-+static int __maybe_unused starfive_mbox_resume(struct device *dev)
-+{
-+ struct starfive_mbox *mbox = dev_get_drvdata(dev);
-+ int ret;
-+
-+ ret = clk_prepare_enable(mbox->clk);
-+ if (ret)
-+ dev_err(dev, "failed to enable clock\n");
-+
-+ return ret;
-+}
-+
-+static const struct dev_pm_ops starfive_mbox_pm_ops = {
-+ .suspend = starfive_mbox_suspend,
-+ .resume = starfive_mbox_resume,
-+ SET_RUNTIME_PM_OPS(starfive_mbox_suspend, starfive_mbox_resume, NULL)
-+};
-+static struct platform_driver starfive_mbox_driver = {
-+ .probe = starfive_mbox_probe,
-+ .remove = starfive_mbox_remove,
-+ .driver = {
-+ .name = "mailbox",
-+ .of_match_table = starfive_mbox_of_match,
-+ .pm = &starfive_mbox_pm_ops,
-+ },
-+};
-+
-+static int __init starfive_mbox_init(void)
-+{
-+ return platform_driver_register(&starfive_mbox_driver);
-+}
-+core_initcall(starfive_mbox_init);
-+
-+static void __exit starfive_mbox_exit(void)
-+{
-+ platform_driver_unregister(&starfive_mbox_driver);
-+}
-+module_exit(starfive_mbox_exit);
-+
-+MODULE_DESCRIPTION("StarFive Mailbox Controller driver");
-+MODULE_AUTHOR("Shanlong Li <shanlong.li@starfivetech.com>");
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From 5969d5b6f7cac455f6f9afc0fe64ac706002e5b5 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfivetech.com>
-Date: Fri, 9 Jun 2023 15:31:53 +0800
-Subject: [PATCH 08/55] driver: rtc: Add StarFive JH7110 rtc driver
-
-Add RTC driver and support for StarFive JH7110 SoC.
-
-Signed-off-by: ziv.xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/rtc/Kconfig | 8 +
- drivers/rtc/Makefile | 1 +
- drivers/rtc/rtc-starfive.c | 741 +++++++++++++++++++++++++++++++++++++
- 3 files changed, 750 insertions(+)
- create mode 100644 drivers/rtc/rtc-starfive.c
-
---- a/drivers/rtc/Kconfig
-+++ b/drivers/rtc/Kconfig
-@@ -1372,6 +1372,14 @@ config RTC_DRV_NTXEC
- embedded controller found in certain e-book readers designed by the
- original design manufacturer Netronix.
-
-+config RTC_DRV_STARFIVE
-+ tristate "StarFive 32.768k-RTC"
-+ depends on ARCH_STARFIVE
-+ depends on OF
-+ help
-+ If you say Y here you will get support for the RTC found on
-+ StarFive SOCS.
-+
- comment "on-CPU RTC drivers"
-
- config RTC_DRV_ASM9260
---- a/drivers/rtc/Makefile
-+++ b/drivers/rtc/Makefile
-@@ -169,6 +169,7 @@ obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
- obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
- obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
- obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o
-+obj-$(CONFIG_RTC_DRV_STARFIVE) += rtc-starfive.o
- obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o
- obj-$(CONFIG_RTC_DRV_ST_LPC) += rtc-st-lpc.o
- obj-$(CONFIG_RTC_DRV_STM32) += rtc-stm32.o
---- /dev/null
-+++ b/drivers/rtc/rtc-starfive.c
-@@ -0,0 +1,741 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * RTC driver for the StarFive JH7110 SoC
-+ *
-+ * Copyright (C) 2021 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <asm/delay.h>
-+#include <linux/bcd.h>
-+#include <linux/bitfield.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/completion.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_irq.h>
-+#include <linux/iopoll.h>
-+#include <linux/platform_device.h>
-+#include <linux/rtc.h>
-+
-+/* Registers */
-+#define SFT_RTC_CFG 0x00
-+#define SFT_RTC_SW_CAL_VALUE 0x04
-+#define SFT_RTC_HW_CAL_CFG 0x08
-+#define SFT_RTC_CMP_CFG 0x0C
-+#define SFT_RTC_IRQ_EN 0x10
-+#define SFT_RTC_IRQ_EVEVT 0x14
-+#define SFT_RTC_IRQ_STATUS 0x18
-+#define SFT_RTC_CAL_VALUE 0x24
-+#define SFT_RTC_CFG_TIME 0x28
-+#define SFT_RTC_CFG_DATE 0x2C
-+#define SFT_RTC_ACT_TIME 0x34
-+#define SFT_RTC_ACT_DATE 0x38
-+#define SFT_RTC_TIME 0x3C
-+#define SFT_RTC_DATE 0x40
-+#define SFT_RTC_TIME_LATCH 0x44
-+#define SFT_RTC_DATE_LATCH 0x48
-+
-+/* RTC_CFG */
-+#define RTC_CFG_ENABLE_SHIFT 0 /* RW: RTC Enable. */
-+#define RTC_CFG_CAL_EN_HW_SHIFT 1 /* RW: Enable of hardware calibretion. */
-+#define RTC_CFG_CAL_SEL_SHIFT 2 /* RW: select the hw/sw calibretion mode.*/
-+#define RTC_CFG_HOUR_MODE_SHIFT 3 /* RW: time hour mode. 24h|12h */
-+
-+/* RTC_SW_CAL_VALUE */
-+#define RTC_SW_CAL_VALUE_MASK GENMASK(15, 0)
-+#define RTC_SW_CAL_MAX RTC_SW_CAL_VALUE_MASK
-+#define RTC_SW_CAL_MIN 0
-+#define RTC_TICKS_PER_SEC 32768 /* Number of ticks per second */
-+#define RTC_PPB_MULT 1000000000LL /* Multiplier for ppb conversions */
-+
-+/* RTC_HW_CAL_CFG */
-+#define RTC_HW_CAL_REF_SEL_SHIFT 0
-+#define RTC_HW_CAL_FRQ_SEL_SHIFT 1
-+
-+/* IRQ_EN/IRQ_EVEVT/IRQ_STATUS */
-+#define RTC_IRQ_CAL_START BIT(0)
-+#define RTC_IRQ_CAL_FINISH BIT(1)
-+#define RTC_IRQ_CMP BIT(2)
-+#define RTC_IRQ_1SEC BIT(3)
-+#define RTC_IRQ_ALAEM BIT(4)
-+#define RTC_IRQ_EVT_UPDATE_PSE BIT(31) /* WO: Enable of update time&&date, IRQ_EVEVT only */
-+#define RTC_IRQ_ALL (RTC_IRQ_CAL_START \
-+ | RTC_IRQ_CAL_FINISH \
-+ | RTC_IRQ_CMP \
-+ | RTC_IRQ_1SEC \
-+ | RTC_IRQ_ALAEM)
-+
-+/* CAL_VALUE */
-+#define RTC_CAL_VALUE_MASK GENMASK(15, 0)
-+
-+/* CFG_TIME/ACT_TIME/RTC_TIME */
-+#define TIME_SEC_MASK GENMASK(6, 0)
-+#define TIME_MIN_MASK GENMASK(13, 7)
-+#define TIME_HOUR_MASK GENMASK(20, 14)
-+
-+/* CFG_DATE/ACT_DATE/RTC_DATE */
-+#define DATE_DAY_MASK GENMASK(5, 0)
-+#define DATE_MON_MASK GENMASK(10, 6)
-+#define DATE_YEAR_MASK GENMASK(18, 11)
-+
-+#define INT_TIMEOUT_US 180
-+
-+enum RTC_HOUR_MODE {
-+ RTC_HOUR_MODE_12H = 0,
-+ RTC_HOUR_MODE_24H = 1
-+};
-+
-+enum RTC_CAL_MODE {
-+ RTC_CAL_MODE_SW = 0,
-+ RTC_CAL_MODE_HW = 1
-+};
-+
-+enum RTC_HW_CAL_REF_MODE {
-+ RTC_CAL_CLK_REF = 0,
-+ RTC_CAL_CLK_MARK = 1
-+};
-+
-+static const unsigned long refclk_list[] = {
-+ 1000000,
-+ 2000000,
-+ 4000000,
-+ 5927000,
-+ 6000000,
-+ 7200000,
-+ 8000000,
-+ 10250000,
-+ 11059200,
-+ 12000000,
-+ 12288000,
-+ 13560000,
-+ 16000000,
-+ 19200000,
-+ 20000000,
-+ 22118000,
-+ 24000000,
-+ 24567000,
-+ 25000000,
-+ 26000000,
-+ 27000000,
-+ 30000000,
-+ 32000000,
-+ 33868800,
-+ 36000000,
-+ 36860000,
-+ 40000000,
-+ 44000000,
-+ 50000000,
-+ 54000000,
-+ 28224000,
-+ 28000000,
-+};
-+
-+struct sft_rtc {
-+ struct rtc_device *rtc_dev;
-+ struct completion cal_done;
-+ struct completion onesec_done;
-+ struct clk *pclk;
-+ struct clk *cal_clk;
-+ struct reset_control *rst_array;
-+ int hw_cal_map;
-+ void __iomem *regs;
-+ int rtc_irq;
-+ int ms_pulse_irq;
-+ int one_sec_pulse_irq;
-+};
-+
-+static inline void sft_rtc_set_enabled(struct sft_rtc *srtc, bool enabled)
-+{
-+ u32 val;
-+
-+ if (enabled) {
-+ val = readl(srtc->regs + SFT_RTC_CFG);
-+ val |= BIT(RTC_CFG_ENABLE_SHIFT);
-+ writel(val, srtc->regs + SFT_RTC_CFG);
-+ } else {
-+ val = readl(srtc->regs + SFT_RTC_CFG);
-+ val &= ~BIT(RTC_CFG_ENABLE_SHIFT);
-+ writel(val, srtc->regs + SFT_RTC_CFG);
-+ }
-+}
-+
-+static inline bool sft_rtc_get_enabled(struct sft_rtc *srtc)
-+{
-+ return !!(readl(srtc->regs + SFT_RTC_CFG) & BIT(RTC_CFG_ENABLE_SHIFT));
-+}
-+
-+static inline void sft_rtc_set_mode(struct sft_rtc *srtc, enum RTC_HOUR_MODE mode)
-+{
-+ u32 val;
-+
-+ val = readl(srtc->regs + SFT_RTC_CFG);
-+ val |= mode << RTC_CFG_HOUR_MODE_SHIFT;
-+ writel(val, srtc->regs + SFT_RTC_CFG);
-+}
-+
-+static inline int sft_rtc_irq_enable(struct sft_rtc *srtc, u32 irq, bool enable)
-+{
-+ u32 val;
-+
-+ if (!(irq & RTC_IRQ_ALL))
-+ return -EINVAL;
-+
-+ if (enable) {
-+ val = readl(srtc->regs + SFT_RTC_IRQ_EN);
-+ val |= irq;
-+ writel(val, srtc->regs + SFT_RTC_IRQ_EN);
-+ } else {
-+ val = readl(srtc->regs + SFT_RTC_IRQ_EN);
-+ val &= ~irq;
-+ writel(val, srtc->regs + SFT_RTC_IRQ_EN);
-+ }
-+ return 0;
-+}
-+
-+static inline void
-+sft_rtc_set_cal_hw_enable(struct sft_rtc *srtc, bool enable)
-+{
-+ u32 val;
-+
-+ if (enable) {
-+ val = readl(srtc->regs + SFT_RTC_CFG);
-+ val |= BIT(RTC_CFG_CAL_EN_HW_SHIFT);
-+ writel(val, srtc->regs + SFT_RTC_CFG);
-+ } else {
-+ val = readl(srtc->regs + SFT_RTC_CFG);
-+ val &= ~BIT(RTC_CFG_CAL_EN_HW_SHIFT);
-+ writel(val, srtc->regs + SFT_RTC_CFG);
-+ }
-+}
-+
-+static inline void
-+sft_rtc_set_cal_mode(struct sft_rtc *srtc, enum RTC_CAL_MODE mode)
-+{
-+ u32 val;
-+
-+ val = readl(srtc->regs + SFT_RTC_CFG);
-+ val |= mode << RTC_CFG_CAL_SEL_SHIFT;
-+ writel(val, srtc->regs + SFT_RTC_CFG);
-+}
-+
-+static int sft_rtc_get_hw_calclk(struct device *dev, unsigned long freq)
-+{
-+ int i;
-+
-+ for (i = 0; i < ARRAY_SIZE(refclk_list); i++)
-+ if (refclk_list[i] == freq)
-+ return i;
-+
-+ dev_err(dev, "refclk: %ldHz do not support.\n", freq);
-+ return -EINVAL;
-+}
-+
-+static inline void sft_rtc_reg2time(struct rtc_time *tm, u32 reg)
-+{
-+ tm->tm_hour = bcd2bin(FIELD_GET(TIME_HOUR_MASK, reg));
-+ tm->tm_min = bcd2bin(FIELD_GET(TIME_MIN_MASK, reg));
-+ tm->tm_sec = bcd2bin(FIELD_GET(TIME_SEC_MASK, reg));
-+}
-+
-+static inline void sft_rtc_reg2date(struct rtc_time *tm, u32 reg)
-+{
-+ tm->tm_year = bcd2bin(FIELD_GET(DATE_YEAR_MASK, reg)) + 100;
-+ tm->tm_mon = bcd2bin(FIELD_GET(DATE_MON_MASK, reg)) - 1;
-+ tm->tm_mday = bcd2bin(FIELD_GET(DATE_DAY_MASK, reg));
-+}
-+
-+static inline u32 sft_rtc_time2reg(struct rtc_time *tm)
-+{
-+ return FIELD_PREP(TIME_HOUR_MASK, bin2bcd(tm->tm_hour)) |
-+ FIELD_PREP(TIME_MIN_MASK, bin2bcd(tm->tm_min)) |
-+ FIELD_PREP(TIME_SEC_MASK, bin2bcd(tm->tm_sec));
-+}
-+
-+static inline u32 sft_rtc_date2reg(struct rtc_time *tm)
-+{
-+ return FIELD_PREP(DATE_YEAR_MASK, bin2bcd(tm->tm_year - 100)) |
-+ FIELD_PREP(DATE_MON_MASK, bin2bcd(tm->tm_mon + 1)) |
-+ FIELD_PREP(DATE_DAY_MASK, bin2bcd(tm->tm_mday));
-+}
-+
-+static inline void sft_rtc_update_pulse(struct sft_rtc *srtc)
-+{
-+ u32 val;
-+
-+ val = readl(srtc->regs + SFT_RTC_IRQ_EVEVT);
-+ val |= RTC_IRQ_EVT_UPDATE_PSE;
-+ writel(val, srtc->regs + SFT_RTC_IRQ_EVEVT);
-+}
-+
-+static irqreturn_t sft_rtc_irq_handler(int irq, void *data)
-+{
-+ struct sft_rtc *srtc = data;
-+ struct timerqueue_node *next;
-+ u32 irq_flags = 0;
-+ u32 irq_mask = 0;
-+ u32 val;
-+ int ret = 0;
-+
-+ val = readl(srtc->regs + SFT_RTC_IRQ_EVEVT);
-+ if (val & RTC_IRQ_CAL_START)
-+ irq_mask |= RTC_IRQ_CAL_START;
-+
-+ if (val & RTC_IRQ_CAL_FINISH) {
-+ irq_mask |= RTC_IRQ_CAL_FINISH;
-+ complete(&srtc->cal_done);
-+ }
-+
-+ if (val & RTC_IRQ_CMP)
-+ irq_mask |= RTC_IRQ_CMP;
-+
-+ if (val & RTC_IRQ_1SEC) {
-+ irq_flags |= RTC_PF;
-+ irq_mask |= RTC_IRQ_1SEC;
-+ complete(&srtc->onesec_done);
-+ }
-+
-+ if (val & RTC_IRQ_ALAEM) {
-+ irq_flags |= RTC_AF;
-+ irq_mask |= RTC_IRQ_ALAEM;
-+
-+ next = timerqueue_getnext(&srtc->rtc_dev->timerqueue);
-+ if (next == &srtc->rtc_dev->aie_timer.node)
-+ dev_info(&srtc->rtc_dev->dev, "alarm expires");
-+ }
-+
-+ writel(irq_mask, srtc->regs + SFT_RTC_IRQ_EVEVT);
-+
-+ /* Wait interrupt flag clear */
-+ ret = readl_poll_timeout_atomic(srtc->regs + SFT_RTC_IRQ_EVEVT, val,
-+ (val & irq_mask) == 0, 0, INT_TIMEOUT_US);
-+ if (ret)
-+ dev_warn(&srtc->rtc_dev->dev, "fail to clear rtc interrupt flag\n");
-+
-+ if (irq_flags)
-+ rtc_update_irq(srtc->rtc_dev, 1, irq_flags | RTC_IRQF);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int sft_rtc_read_time(struct device *dev, struct rtc_time *tm)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ u32 val;
-+ int irq_1sec_state_start, irq_1sec_state_end;
-+
-+ /* If the RTC is disabled, assume the values are invalid */
-+ if (!sft_rtc_get_enabled(srtc))
-+ return -EINVAL;
-+
-+ irq_1sec_state_start =
-+ (readl(srtc->regs + SFT_RTC_IRQ_STATUS) & RTC_IRQ_1SEC) == 0 ? 0 : 1;
-+
-+read_again:
-+ val = readl(srtc->regs + SFT_RTC_TIME);
-+ sft_rtc_reg2time(tm, val);
-+
-+ val = readl(srtc->regs + SFT_RTC_DATE);
-+ sft_rtc_reg2date(tm, val);
-+
-+ if (irq_1sec_state_start == 0) {
-+ irq_1sec_state_end =
-+ (readl(srtc->regs + SFT_RTC_IRQ_STATUS) & RTC_IRQ_1SEC) == 0 ? 0 : 1;
-+ if (irq_1sec_state_end == 1) {
-+ irq_1sec_state_start = 1;
-+ goto read_again;
-+ }
-+ }
-+
-+ return 0;
-+}
-+
-+static int sft_rtc_set_time(struct device *dev, struct rtc_time *tm)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ u32 val;
-+ int ret;
-+
-+ val = sft_rtc_time2reg(tm);
-+ writel(val, srtc->regs + SFT_RTC_CFG_TIME);
-+
-+ val = sft_rtc_date2reg(tm);
-+ writel(val, srtc->regs + SFT_RTC_CFG_DATE);
-+
-+ /* Update pulse */
-+ sft_rtc_update_pulse(srtc);
-+
-+ /* Ensure that data is fully written */
-+ ret = wait_for_completion_interruptible_timeout(&srtc->onesec_done,
-+ usecs_to_jiffies(120));
-+ if (ret) {
-+ dev_warn(dev,
-+ "rtc wait for completion interruptible timeout.\n");
-+ }
-+ return 0;
-+}
-+
-+static int sft_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+
-+ return sft_rtc_irq_enable(srtc, RTC_IRQ_ALAEM, enabled);
-+}
-+
-+static int sft_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ u32 val;
-+
-+ val = readl(srtc->regs + SFT_RTC_ACT_TIME);
-+ sft_rtc_reg2time(&alarm->time, val);
-+
-+ val = readl(srtc->regs + SFT_RTC_ACT_DATE);
-+ sft_rtc_reg2date(&alarm->time, val);
-+
-+ return 0;
-+}
-+
-+static int sft_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ u32 val;
-+
-+ sft_rtc_alarm_irq_enable(dev, 0);
-+
-+ val = sft_rtc_time2reg(&alarm->time);
-+ writel(val, srtc->regs + SFT_RTC_ACT_TIME);
-+
-+ val = sft_rtc_date2reg(&alarm->time);
-+ writel(val, srtc->regs + SFT_RTC_ACT_DATE);
-+
-+ sft_rtc_alarm_irq_enable(dev, alarm->enabled);
-+
-+ return 0;
-+}
-+
-+static int sft_rtc_get_offset(struct device *dev, long *offset)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ s64 tmp;
-+ u32 val;
-+
-+ val = readl(srtc->regs + SFT_RTC_CAL_VALUE)
-+ & RTC_SW_CAL_VALUE_MASK;
-+ val += 1;
-+ /*
-+ * the adjust val range is [0x0000-0xffff],
-+ * the default val is 0x7fff (32768-1),mapping offset=0 ;
-+ */
-+ tmp = (s64)val - RTC_TICKS_PER_SEC;
-+ tmp *= RTC_PPB_MULT;
-+ tmp = div_s64(tmp, RTC_TICKS_PER_SEC);
-+
-+ /* Offset value operates in negative way, so swap sign */
-+ *offset = -tmp;
-+
-+ return 0;
-+}
-+
-+static int sft_rtc_set_offset(struct device *dev, long offset)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ s64 tmp;
-+ u32 val;
-+
-+ tmp = offset * RTC_TICKS_PER_SEC;
-+ tmp = div_s64(tmp, RTC_PPB_MULT);
-+
-+ tmp = RTC_TICKS_PER_SEC - tmp;
-+ tmp -= 1;
-+ if (tmp > RTC_SW_CAL_MAX || tmp < RTC_SW_CAL_MIN) {
-+ dev_err(dev, "offset is out of range.\n");
-+ return -EINVAL;
-+ }
-+
-+ val = tmp & RTC_SW_CAL_VALUE_MASK;
-+ /* set software calibration value */
-+ writel(val, srtc->regs + SFT_RTC_SW_CAL_VALUE);
-+
-+ /* set CFG_RTC-cal_sel to select calibretion by software. */
-+ sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_SW);
-+
-+ return 0;
-+}
-+
-+static __maybe_unused int
-+sft_rtc_hw_adjustment(struct device *dev, unsigned int enable)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+ u32 val;
-+
-+ if (srtc->hw_cal_map <= 0) {
-+ dev_err(dev, "fail to get cal-clock-freq.\n");
-+ return -EFAULT;
-+ }
-+
-+ if (enable) {
-+ sft_rtc_irq_enable(srtc, RTC_IRQ_CAL_FINISH, true);
-+
-+ /* Set reference clock frequency value */
-+ val = readl(srtc->regs + SFT_RTC_HW_CAL_CFG);
-+ val |= (srtc->hw_cal_map << RTC_HW_CAL_FRQ_SEL_SHIFT);
-+ writel(val, srtc->regs + SFT_RTC_HW_CAL_CFG);
-+
-+ /* Set CFG_RTC-cal_sel to select calibretion by hardware. */
-+ sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_HW);
-+
-+ /* Set CFG_RTC-cal_en_hw to launch hardware calibretion.*/
-+ sft_rtc_set_cal_hw_enable(srtc, true);
-+
-+ wait_for_completion_interruptible_timeout(&srtc->cal_done,
-+ usecs_to_jiffies(100));
-+
-+ sft_rtc_irq_enable(srtc, RTC_IRQ_CAL_FINISH, false);
-+ } else {
-+ sft_rtc_set_cal_mode(srtc, RTC_CAL_MODE_SW);
-+ sft_rtc_set_cal_hw_enable(srtc, false);
-+ }
-+
-+ return 0;
-+}
-+
-+static int sft_rtc_get_cal_clk(struct device *dev, struct sft_rtc *srtc)
-+{
-+ struct device_node *np = dev->of_node;
-+ unsigned long cal_clk_freq;
-+ u32 freq;
-+ int ret;
-+
-+ srtc->cal_clk = devm_clk_get(dev, "cal_clk");
-+ if (IS_ERR(srtc->cal_clk))
-+ return PTR_ERR(srtc->cal_clk);
-+
-+ clk_prepare_enable(srtc->cal_clk);
-+
-+ cal_clk_freq = clk_get_rate(srtc->cal_clk);
-+ if (!cal_clk_freq) {
-+ dev_warn(dev,
-+ "get rate failed, next try to get from dts.\n");
-+ ret = of_property_read_u32(np, "rtc,cal-clock-freq", &freq);
-+ if (!ret) {
-+ cal_clk_freq = (u64)freq;
-+ } else {
-+ dev_err(dev,
-+ "Need rtc,cal-clock-freq define in dts.\n");
-+ goto err_disable_cal_clk;
-+ }
-+ }
-+
-+ srtc->hw_cal_map = sft_rtc_get_hw_calclk(dev, cal_clk_freq);
-+ if (srtc->hw_cal_map < 0) {
-+ ret = srtc->hw_cal_map;
-+ goto err_disable_cal_clk;
-+ }
-+
-+ return 0;
-+
-+err_disable_cal_clk:
-+ clk_disable_unprepare(srtc->cal_clk);
-+
-+ return ret;
-+}
-+
-+static int sft_rtc_get_irq(struct platform_device *pdev, struct sft_rtc *srtc)
-+{
-+ int ret;
-+
-+ srtc->rtc_irq = platform_get_irq_byname(pdev, "rtc");
-+ if (srtc->rtc_irq < 0)
-+ return -EINVAL;
-+
-+ ret = devm_request_irq(&pdev->dev, srtc->rtc_irq,
-+ sft_rtc_irq_handler, 0,
-+ KBUILD_MODNAME, srtc);
-+ if (ret)
-+ dev_err(&pdev->dev, "Failed to request interrupt, %d\n", ret);
-+
-+ return ret;
-+}
-+
-+static const struct rtc_class_ops starfive_rtc_ops = {
-+ .read_time = sft_rtc_read_time,
-+ .set_time = sft_rtc_set_time,
-+ .read_alarm = sft_rtc_read_alarm,
-+ .set_alarm = sft_rtc_set_alarm,
-+ .alarm_irq_enable = sft_rtc_alarm_irq_enable,
-+ .set_offset = sft_rtc_set_offset,
-+ .read_offset = sft_rtc_get_offset,
-+};
-+
-+static int sft_rtc_probe(struct platform_device *pdev)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct sft_rtc *srtc;
-+ struct rtc_time tm;
-+ struct irq_desc *desc;
-+ int ret;
-+
-+ srtc = devm_kzalloc(dev, sizeof(*srtc), GFP_KERNEL);
-+ if (!srtc)
-+ return -ENOMEM;
-+
-+ srtc->regs = devm_platform_ioremap_resource(pdev, 0);
-+ if (IS_ERR(srtc->regs))
-+ return PTR_ERR(srtc->regs);
-+
-+ srtc->pclk = devm_clk_get(dev, "pclk");
-+ if (IS_ERR(srtc->pclk)) {
-+ ret = PTR_ERR(srtc->pclk);
-+ dev_err(dev,
-+ "Failed to retrieve the peripheral clock, %d\n", ret);
-+ return ret;
-+ }
-+
-+ srtc->rst_array = devm_reset_control_array_get_exclusive(dev);
-+ if (IS_ERR(srtc->rst_array)) {
-+ ret = PTR_ERR(srtc->rst_array);
-+ dev_err(dev,
-+ "Failed to retrieve the rtc reset, %d\n", ret);
-+ return ret;
-+ }
-+
-+ init_completion(&srtc->cal_done);
-+ init_completion(&srtc->onesec_done);
-+
-+ ret = clk_prepare_enable(srtc->pclk);
-+ if (ret) {
-+ dev_err(dev,
-+ "Failed to enable the peripheral clock, %d\n", ret);
-+ return ret;
-+ }
-+
-+ ret = sft_rtc_get_cal_clk(dev, srtc);
-+ if (ret)
-+ goto err_disable_pclk;
-+
-+ ret = reset_control_deassert(srtc->rst_array);
-+ if (ret) {
-+ dev_err(dev,
-+ "Failed to deassert rtc resets, %d\n", ret);
-+ goto err_disable_cal_clk;
-+ }
-+
-+ ret = sft_rtc_get_irq(pdev, srtc);
-+ if (ret)
-+ goto err_disable_cal_clk;
-+
-+ srtc->rtc_dev = devm_rtc_allocate_device(dev);
-+ if (IS_ERR(srtc->rtc_dev))
-+ return PTR_ERR(srtc->rtc_dev);
-+
-+ platform_set_drvdata(pdev, srtc);
-+
-+ /* The RTC supports 01.01.2001 - 31.12.2099 */
-+ srtc->rtc_dev->range_min = mktime64(2001, 1, 1, 0, 0, 0);
-+ srtc->rtc_dev->range_max = mktime64(2099, 12, 31, 23, 59, 59);
-+
-+ srtc->rtc_dev->ops = &starfive_rtc_ops;
-+ device_init_wakeup(dev, true);
-+
-+ desc = irq_to_desc(srtc->rtc_irq);
-+ irq_desc_get_chip(desc)->flags = IRQCHIP_SKIP_SET_WAKE;
-+
-+ /* Always use 24-hour mode and keep the RTC values */
-+ sft_rtc_set_mode(srtc, RTC_HOUR_MODE_24H);
-+
-+ sft_rtc_set_enabled(srtc, true);
-+
-+ if (device_property_read_bool(dev, "rtc,hw-adjustment"))
-+ sft_rtc_hw_adjustment(dev, true);
-+
-+ /*
-+ * If rtc time is out of supported range, reset it to the minimum time.
-+ * notice that, actual year = 1900 + tm.tm_year
-+ * actual month = 1 + tm.tm_mon
-+ */
-+ sft_rtc_read_time(dev, &tm);
-+ if (tm.tm_year < 101 || tm.tm_year > 199 || tm.tm_mon < 0 || tm.tm_mon > 11 ||
-+ tm.tm_mday < 1 || tm.tm_mday > 31 || tm.tm_hour < 0 || tm.tm_hour > 23 ||
-+ tm.tm_min < 0 || tm.tm_min > 59 || tm.tm_sec < 0 || tm.tm_sec > 59) {
-+ rtc_time64_to_tm(srtc->rtc_dev->range_min, &tm);
-+ sft_rtc_set_time(dev, &tm);
-+ }
-+
-+ ret = devm_rtc_register_device(srtc->rtc_dev);
-+ if (ret)
-+ goto err_disable_wakeup;
-+
-+ return 0;
-+
-+err_disable_wakeup:
-+ device_init_wakeup(dev, false);
-+
-+err_disable_cal_clk:
-+ clk_disable_unprepare(srtc->cal_clk);
-+
-+err_disable_pclk:
-+ clk_disable_unprepare(srtc->pclk);
-+
-+ return ret;
-+}
-+
-+static void sft_rtc_remove(struct platform_device *pdev)
-+{
-+ struct sft_rtc *srtc = platform_get_drvdata(pdev);
-+
-+ sft_rtc_alarm_irq_enable(&pdev->dev, 0);
-+ device_init_wakeup(&pdev->dev, 0);
-+
-+ clk_disable_unprepare(srtc->pclk);
-+ clk_disable_unprepare(srtc->cal_clk);
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int sft_rtc_suspend(struct device *dev)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+
-+ if (device_may_wakeup(dev))
-+ enable_irq_wake(srtc->rtc_irq);
-+
-+ return 0;
-+}
-+
-+static int sft_rtc_resume(struct device *dev)
-+{
-+ struct sft_rtc *srtc = dev_get_drvdata(dev);
-+
-+ if (device_may_wakeup(dev))
-+ disable_irq_wake(srtc->rtc_irq);
-+
-+ return 0;
-+}
-+#endif
-+
-+static SIMPLE_DEV_PM_OPS(sft_rtc_pm_ops, sft_rtc_suspend, sft_rtc_resume);
-+
-+static const struct of_device_id sft_rtc_of_match[] = {
-+ { .compatible = "starfive,jh7110-rtc" },
-+ { },
-+};
-+MODULE_DEVICE_TABLE(of, sft_rtc_of_match);
-+
-+static struct platform_driver starfive_rtc_driver = {
-+ .driver = {
-+ .name = "starfive-rtc",
-+ .of_match_table = sft_rtc_of_match,
-+ .pm = &sft_rtc_pm_ops,
-+ },
-+ .probe = sft_rtc_probe,
-+ .remove = sft_rtc_remove,
-+};
-+module_platform_driver(starfive_rtc_driver);
-+
-+MODULE_AUTHOR("Samin Guo <samin.guo@starfivetech.com>");
-+MODULE_AUTHOR("Hal Feng <hal.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("StarFive RTC driver");
-+MODULE_LICENSE("GPL v2");
-+MODULE_ALIAS("platform:starfive-rtc");
+++ /dev/null
-From 20c14bbdff9e3be2ddbeffa266f08bae04216e63 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Sun, 25 Jun 2023 09:40:29 +0800
-Subject: [PATCH 09/55] uart: 8250: Add dw auto flow ctrl support
-
-Add designeware 8250 auto flow ctrl support. Enable
-it by add auto-flow-control in dts.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
----
- drivers/tty/serial/8250/8250_core.c | 2 ++
- drivers/tty/serial/8250/8250_dw.c | 3 +++
- drivers/tty/serial/8250/8250_port.c | 14 +++++++++++++-
- include/linux/serial_8250.h | 1 +
- include/uapi/linux/serial_core.h | 2 ++
- 5 files changed, 21 insertions(+), 1 deletion(-)
-
---- a/drivers/tty/serial/8250/8250_core.c
-+++ b/drivers/tty/serial/8250/8250_core.c
-@@ -810,6 +810,8 @@ int serial8250_register_8250_port(const
- uart->dl_read = up->dl_read;
- if (up->dl_write)
- uart->dl_write = up->dl_write;
-+ if (up->probe)
-+ uart->probe = up->probe;
-
- if (uart->port.type != PORT_8250_CIR) {
- if (uart_console_registered(&uart->port))
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -594,6 +594,9 @@ static int dw8250_probe(struct platform_
- data->msr_mask_off |= UART_MSR_TERI;
- }
-
-+ if (device_property_read_bool(dev, "auto-flow-control"))
-+ up->probe |= UART_PROBE_AFE;
-+
- /* If there is separate baudclk, get the rate from it. */
- data->clk = devm_clk_get_optional_enabled(dev, "baudclk");
- if (data->clk == NULL)
---- a/drivers/tty/serial/8250/8250_port.c
-+++ b/drivers/tty/serial/8250/8250_port.c
-@@ -319,6 +319,14 @@ static const struct serial8250_config ua
- .rxtrig_bytes = {1, 8, 16, 30},
- .flags = UART_CAP_FIFO | UART_CAP_AFE,
- },
-+ [PORT_16550A_AFE] = {
-+ .name = "16550A_AFE",
-+ .fifo_size = 16,
-+ .tx_loadsz = 16,
-+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
-+ .rxtrig_bytes = {1, 4, 8, 14},
-+ .flags = UART_CAP_FIFO | UART_CAP_AFE,
-+ },
- };
-
- /* Uart divisor latch read */
-@@ -1124,6 +1132,11 @@ static void autoconfig_16550a(struct uar
- up->port.type = PORT_U6_16550A;
- up->capabilities |= UART_CAP_AFE;
- }
-+
-+ if ((up->port.type == PORT_16550A) && (up->probe & UART_PROBE_AFE)) {
-+ up->port.type = PORT_16550A_AFE;
-+ up->capabilities |= UART_CAP_AFE;
-+ }
- }
-
- /*
-@@ -2774,7 +2787,6 @@ serial8250_do_set_termios(struct uart_po
- if (termios->c_cflag & CRTSCTS)
- up->mcr |= UART_MCR_AFE;
- }
--
- /*
- * Update the per-port timeout.
- */
---- a/include/linux/serial_8250.h
-+++ b/include/linux/serial_8250.h
-@@ -141,6 +141,7 @@ struct uart_8250_port {
- unsigned char probe;
- struct mctrl_gpios *gpios;
- #define UART_PROBE_RSA (1 << 0)
-+#define UART_PROBE_AFE (1 << 1)
-
- /*
- * Some bits in registers are cleared on a read, so they must
---- a/include/uapi/linux/serial_core.h
-+++ b/include/uapi/linux/serial_core.h
-@@ -231,6 +231,8 @@
- /* Sunplus UART */
- #define PORT_SUNPLUS 123
-
-+#define PORT_16550A_AFE 124
-+
- /* Generic type identifier for ports which type is not important to userspace. */
- #define PORT_GENERIC (-1)
-
+++ /dev/null
-From ee5aab642d8a99a7a48d9b30f098ca2a97f463c4 Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Wed, 20 Sep 2023 17:19:59 +0800
-Subject: [PATCH 10/55] uart: 8250: add reset operation in runtime PM
-
-add reset operation in runtime PM
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
----
- drivers/tty/serial/8250/8250_dw.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -712,6 +712,8 @@ static int dw8250_runtime_suspend(struct
- {
- struct dw8250_data *data = dev_get_drvdata(dev);
-
-+ reset_control_assert(data->rst);
-+
- clk_disable_unprepare(data->clk);
-
- clk_disable_unprepare(data->pclk);
-@@ -734,6 +736,8 @@ static int dw8250_runtime_resume(struct
- return ret;
- }
-
-+ reset_control_deassert(data->rst);
-+
- return 0;
- }
-
+++ /dev/null
-From 94de8add412dffdfa0389c6ae0f6aaad64d34fcd Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Thu, 15 Jun 2023 20:15:25 +0800
-Subject: [PATCH 11/55] CAN: starfive - Add CAN engine support
-
-Adding device probe StarFive CAN module.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/net/can/Kconfig | 5 +
- drivers/net/can/Makefile | 2 +
- drivers/net/can/ipms_canfd.c | 1273 ++++++++++++++++++++++++++++++++++
- 3 files changed, 1280 insertions(+)
- create mode 100644 drivers/net/can/ipms_canfd.c
-
---- a/drivers/net/can/Kconfig
-+++ b/drivers/net/can/Kconfig
-@@ -216,6 +216,11 @@ config CAN_XILINXCAN
- Xilinx CAN driver. This driver supports both soft AXI CAN IP and
- Zynq CANPS IP.
-
-+config IPMS_CAN
-+ tristate "IPMS CAN"
-+ help
-+ IPMS CANFD driver. This driver supports IPMS CANFD IP.
-+
- source "drivers/net/can/c_can/Kconfig"
- source "drivers/net/can/cc770/Kconfig"
- source "drivers/net/can/ctucanfd/Kconfig"
---- a/drivers/net/can/Makefile
-+++ b/drivers/net/can/Makefile
-@@ -33,5 +33,7 @@ obj-$(CONFIG_CAN_SJA1000) += sja1000/
- obj-$(CONFIG_CAN_SUN4I) += sun4i_can.o
- obj-$(CONFIG_CAN_TI_HECC) += ti_hecc.o
- obj-$(CONFIG_CAN_XILINXCAN) += xilinx_can.o
-+obj-$(CONFIG_IPMS_CAN) += ipms_canfd.o
-+ccflags-$(CONFIG_IPMS_CAN) := -Wno-error=missing-prototypes
-
- subdir-ccflags-$(CONFIG_CAN_DEBUG_DEVICES) += -DDEBUG
---- /dev/null
-+++ b/drivers/net/can/ipms_canfd.c
-@@ -0,0 +1,1273 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * StarFive Controller Area Network Host Controller Driver
-+ *
-+ * Copyright (c) 2022 StarFive Technology Co., Ltd.
-+ */
-+
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/errno.h>
-+#include <linux/init.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/netdevice.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/skbuff.h>
-+#include <linux/string.h>
-+#include <linux/types.h>
-+#include <linux/can/dev.h>
-+#include <linux/can/error.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/of_device.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/regmap.h>
-+
-+#define DRIVER_NAME "ipms_canfd"
-+
-+/* CAN registers set */
-+enum canfd_device_reg {
-+ CANFD_RUBF_OFFSET = 0x00, /* Receive Buffer Registers 0x00-0x4f */
-+ CANFD_RUBF_ID_OFFSET = 0x00,
-+ CANFD_RBUF_CTL_OFFSET = 0x04,
-+ CANFD_RBUF_DATA_OFFSET = 0x08,
-+ CANFD_TBUF_OFFSET = 0x50, /* Transmit Buffer Registers 0x50-0x97 */
-+ CANFD_TBUF_ID_OFFSET = 0x50,
-+ CANFD_TBUF_CTL_OFFSET = 0x54,
-+ CANFD_TBUF_DATA_OFFSET = 0x58,
-+ CANFD_TTS_OFFSET = 0x98, /* Transmission Time Stamp 0x98-0x9f */
-+ CANFD_CFG_STAT_OFFSET = 0xa0,
-+ CANFD_TCMD_OFFSET = 0xa1,
-+ CANFD_TCTRL_OFFSET = 0xa2,
-+ CANFD_RCTRL_OFFSET = 0xa3,
-+ CANFD_RTIE_OFFSET = 0xa4,
-+ CANFD_RTIF_OFFSET = 0xa5,
-+ CANFD_ERRINT_OFFSET = 0xa6,
-+ CANFD_LIMIT_OFFSET = 0xa7,
-+ CANFD_S_SEG_1_OFFSET = 0xa8,
-+ CANFD_S_SEG_2_OFFSET = 0xa9,
-+ CANFD_S_SJW_OFFSET = 0xaa,
-+ CANFD_S_PRESC_OFFSET = 0xab,
-+ CANFD_F_SEG_1_OFFSET = 0xac,
-+ CANFD_F_SEG_2_OFFSET = 0xad,
-+ CANFD_F_SJW_OFFSET = 0xae,
-+ CANFD_F_PRESC_OFFSET = 0xaf,
-+ CANFD_EALCAP_OFFSET = 0xb0,
-+ CANFD_RECNT_OFFSET = 0xb2,
-+ CANFD_TECNT_OFFSET = 0xb3,
-+};
-+
-+enum canfd_reg_bitchange {
-+ CAN_FD_SET_RST_MASK = 0x80, /* Set Reset Bit */
-+ CAN_FD_OFF_RST_MASK = 0x7f, /* Reset Off Bit */
-+ CAN_FD_SET_FULLCAN_MASK = 0x10, /* set TTTBM as 1->full TTCAN mode */
-+ CAN_FD_OFF_FULLCAN_MASK = 0xef, /* set TTTBM as 0->separate PTB and STB mode */
-+ CAN_FD_SET_FIFO_MASK = 0x20, /* set TSMODE as 1->FIFO mode */
-+ CAN_FD_OFF_FIFO_MASK = 0xdf, /* set TSMODE as 0->Priority mode */
-+ CAN_FD_SET_TSONE_MASK = 0x04,
-+ CAN_FD_OFF_TSONE_MASK = 0xfb,
-+ CAN_FD_SET_TSALL_MASK = 0x02,
-+ CAN_FD_OFF_TSALL_MASK = 0xfd,
-+ CAN_FD_LBMEMOD_MASK = 0x40, /* set loop back mode, external */
-+ CAN_FD_LBMIMOD_MASK = 0x20, /* set loopback internal mode */
-+ CAN_FD_SET_BUSOFF_MASK = 0x01,
-+ CAN_FD_OFF_BUSOFF_MASK = 0xfe,
-+ CAN_FD_SET_TTSEN_MASK = 0x80, /* set ttsen, tts update enable */
-+ CAN_FD_SET_BRS_MASK = 0x10, /* can fd Bit Rate Switch mask */
-+ CAN_FD_OFF_BRS_MASK = 0xef,
-+ CAN_FD_SET_EDL_MASK = 0x20, /* Extended Data Length */
-+ CAN_FD_OFF_EDL_MASK = 0xdf,
-+ CAN_FD_SET_DLC_MASK = 0x0f,
-+ CAN_FD_SET_TENEXT_MASK = 0x40,
-+ CAN_FD_SET_IDE_MASK = 0x80,
-+ CAN_FD_OFF_IDE_MASK = 0x7f,
-+ CAN_FD_SET_RTR_MASK = 0x40,
-+ CAN_FD_OFF_RTR_MASK = 0xbf,
-+ CAN_FD_INTR_ALL_MASK = 0xff, /* all interrupts enable mask */
-+ CAN_FD_SET_RIE_MASK = 0x80,
-+ CAN_FD_OFF_RIE_MASK = 0x7f,
-+ CAN_FD_SET_RFIE_MASK = 0x20,
-+ CAN_FD_OFF_RFIE_MASK = 0xdf,
-+ CAN_FD_SET_RAFIE_MASK = 0x10,
-+ CAN_FD_OFF_RAFIE_MASK = 0xef,
-+ CAN_FD_SET_EIE_MASK = 0x02,
-+ CAN_FD_OFF_EIE_MASK = 0xfd,
-+ CAN_FD_TASCTIVE_MASK = 0x02,
-+ CAN_FD_RASCTIVE_MASK = 0x04,
-+ CAN_FD_SET_TBSEL_MASK = 0x80, /* message writen in STB */
-+ CAN_FD_OFF_TBSEL_MASK = 0x7f, /* message writen in PTB */
-+ CAN_FD_SET_STBY_MASK = 0x20,
-+ CAN_FD_OFF_STBY_MASK = 0xdf,
-+ CAN_FD_SET_TPE_MASK = 0x10, /* Transmit primary enable */
-+ CAN_FD_SET_TPA_MASK = 0x08,
-+ CAN_FD_SET_SACK_MASK = 0x80,
-+ CAN_FD_SET_RREL_MASK = 0x10,
-+ CAN_FD_RSTAT_NOT_EMPTY_MASK = 0x03,
-+ CAN_FD_SET_RIF_MASK = 0x80,
-+ CAN_FD_OFF_RIF_MASK = 0x7f,
-+ CAN_FD_SET_RAFIF_MASK = 0x10,
-+ CAN_FD_SET_RFIF_MASK = 0x20,
-+ CAN_FD_SET_TPIF_MASK = 0x08, /* Transmission Primary Interrupt Flag */
-+ CAN_FD_SET_TSIF_MASK = 0x04,
-+ CAN_FD_SET_EIF_MASK = 0x02,
-+ CAN_FD_SET_AIF_MASK = 0x01,
-+ CAN_FD_SET_EWARN_MASK = 0x80,
-+ CAN_FD_SET_EPASS_MASK = 0x40,
-+ CAN_FD_SET_EPIE_MASK = 0x20,
-+ CAN_FD_SET_EPIF_MASK = 0x10,
-+ CAN_FD_SET_ALIE_MASK = 0x08,
-+ CAN_FD_SET_ALIF_MASK = 0x04,
-+ CAN_FD_SET_BEIE_MASK = 0x02,
-+ CAN_FD_SET_BEIF_MASK = 0x01,
-+ CAN_FD_OFF_EPIE_MASK = 0xdf,
-+ CAN_FD_OFF_BEIE_MASK = 0xfd,
-+ CAN_FD_SET_AFWL_MASK = 0x40,
-+ CAN_FD_SET_EWL_MASK = 0x0b,
-+ CAN_FD_SET_KOER_MASK = 0xe0,
-+ CAN_FD_SET_BIT_ERROR_MASK = 0x20,
-+ CAN_FD_SET_FORM_ERROR_MASK = 0x40,
-+ CAN_FD_SET_STUFF_ERROR_MASK = 0x60,
-+ CAN_FD_SET_ACK_ERROR_MASK = 0x80,
-+ CAN_FD_SET_CRC_ERROR_MASK = 0xa0,
-+ CAN_FD_SET_OTH_ERROR_MASK = 0xc0,
-+};
-+
-+/* seg1,seg2,sjw,prescaler all have 8 bits */
-+#define BITS_OF_BITTIMING_REG 8
-+
-+/* in can_bittiming strucure every field has 32 bits---->u32 */
-+#define FBITS_IN_BITTIMING_STR 32
-+#define SEG_1_SHIFT 0
-+#define SEG_2_SHIFT 8
-+#define SJW_SHIFT 16
-+#define PRESC_SHIFT 24
-+
-+/* TTSEN bit used for 32 bit register read or write */
-+#define TTSEN_8_32_SHIFT 24
-+#define RTR_32_8_SHIFT 24
-+
-+/* transmit mode */
-+#define XMIT_FULL 0
-+#define XMIT_SEP_FIFO 1
-+#define XMIT_SEP_PRIO 2
-+#define XMIT_PTB_MODE 3
-+
-+enum IPMS_CAN_TYPE {
-+ IPMS_CAN_TYPY_CAN = 0,
-+ IPMS_CAN_TYPE_CANFD,
-+};
-+
-+struct ipms_canfd_priv {
-+ struct can_priv can;
-+ struct napi_struct napi;
-+ struct device *dev;
-+ struct regmap *reg_syscon;
-+ void __iomem *reg_base;
-+ u32 (*read_reg)(const struct ipms_canfd_priv *priv, enum canfd_device_reg reg);
-+ void (*write_reg)(const struct ipms_canfd_priv *priv, enum canfd_device_reg reg, u32 val);
-+ struct clk *can_clk;
-+ u32 tx_mode;
-+ struct reset_control *resets;
-+ struct clk_bulk_data *clks;
-+ int nr_clks;
-+ u32 can_or_canfd;
-+};
-+
-+static struct can_bittiming_const canfd_bittiming_const = {
-+ .name = DRIVER_NAME,
-+ .tseg1_min = 2,
-+ .tseg1_max = 16,
-+ .tseg2_min = 2,
-+ .tseg2_max = 8,
-+ .sjw_max = 4,
-+ .brp_min = 1,
-+ .brp_max = 512,
-+ .brp_inc = 1,
-+
-+};
-+
-+static struct can_bittiming_const canfd_data_bittiming_const = {
-+ .name = DRIVER_NAME,
-+ .tseg1_min = 1,
-+ .tseg1_max = 16,
-+ .tseg2_min = 2,
-+ .tseg2_max = 8,
-+ .sjw_max = 8,
-+ .brp_min = 1,
-+ .brp_max = 512,
-+ .brp_inc = 1,
-+};
-+
-+static void canfd_write_reg_le(const struct ipms_canfd_priv *priv,
-+ enum canfd_device_reg reg, u32 val)
-+{
-+ iowrite32(val, priv->reg_base + reg);
-+}
-+
-+static u32 canfd_read_reg_le(const struct ipms_canfd_priv *priv,
-+ enum canfd_device_reg reg)
-+{
-+ return ioread32(priv->reg_base + reg);
-+}
-+
-+static inline unsigned char can_ioread8(const void *addr)
-+{
-+ void *addr_down;
-+ union val {
-+ u8 val_8[4];
-+ u32 val_32;
-+ } val;
-+ u32 offset = 0;
-+
-+ addr_down = (void *)ALIGN_DOWN((unsigned long)addr, 4);
-+ offset = addr - addr_down;
-+ val.val_32 = ioread32(addr_down);
-+ return val.val_8[offset];
-+}
-+
-+static inline void can_iowrite8(unsigned char value, void *addr)
-+{
-+ void *addr_down;
-+ union val {
-+ u8 val_8[4];
-+ u32 val_32;
-+ } val;
-+ u8 offset = 0;
-+
-+ addr_down = (void *)ALIGN_DOWN((unsigned long)addr, 4);
-+ offset = addr - addr_down;
-+ val.val_32 = ioread32(addr_down);
-+ val.val_8[offset] = value;
-+ iowrite32(val.val_32, addr_down);
-+}
-+
-+static void canfd_reigister_set_bit(const struct ipms_canfd_priv *priv,
-+ enum canfd_device_reg reg,
-+ enum canfd_reg_bitchange set_mask)
-+{
-+ void *addr_down;
-+ union val {
-+ u8 val_8[4];
-+ u32 val_32;
-+ } val;
-+ u8 offset = 0;
-+
-+ addr_down = (void *)ALIGN_DOWN((unsigned long)(priv->reg_base + reg), 4);
-+ offset = (priv->reg_base + reg) - addr_down;
-+ val.val_32 = ioread32(addr_down);
-+ val.val_8[offset] |= set_mask;
-+ iowrite32(val.val_32, addr_down);
-+}
-+
-+static void canfd_reigister_off_bit(const struct ipms_canfd_priv *priv,
-+ enum canfd_device_reg reg,
-+ enum canfd_reg_bitchange set_mask)
-+{
-+ void *addr_down;
-+ union val {
-+ u8 val_8[4];
-+ u32 val_32;
-+ } val;
-+ u8 offset = 0;
-+
-+ addr_down = (void *)ALIGN_DOWN((unsigned long)(priv->reg_base + reg), 4);
-+ offset = (priv->reg_base + reg) - addr_down;
-+ val.val_32 = ioread32(addr_down);
-+ val.val_8[offset] &= set_mask;
-+ iowrite32(val.val_32, addr_down);
-+}
-+
-+static int canfd_device_driver_bittime_configuration(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ struct can_bittiming *bt = &priv->can.bittiming;
-+ struct can_bittiming *dbt = &priv->can.data_bittiming;
-+ u32 reset_test, bittiming_temp, dat_bittiming;
-+
-+ reset_test = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+ if (!(reset_test & CAN_FD_SET_RST_MASK)) {
-+ netdev_alert(ndev, "Not in reset mode, cannot set bit timing\n");
-+ return -EPERM;
-+ }
-+
-+ bittiming_temp = ((bt->phase_seg1 + bt->prop_seg + 1 - 2) << SEG_1_SHIFT) |
-+ ((bt->phase_seg2 - 1) << SEG_2_SHIFT) |
-+ ((bt->sjw - 1) << SJW_SHIFT) |
-+ ((bt->brp - 1) << PRESC_SHIFT);
-+
-+ /* Check the bittime parameter */
-+ if ((((int)(bt->phase_seg1 + bt->prop_seg + 1) - 2) < 0) ||
-+ (((int)(bt->phase_seg2) - 1) < 0) ||
-+ (((int)(bt->sjw) - 1) < 0) ||
-+ (((int)(bt->brp) - 1) < 0))
-+ return -EINVAL;
-+
-+ priv->write_reg(priv, CANFD_S_SEG_1_OFFSET, bittiming_temp);
-+
-+ if (priv->can_or_canfd == IPMS_CAN_TYPE_CANFD) {
-+ dat_bittiming = ((dbt->phase_seg1 + dbt->prop_seg + 1 - 2) << SEG_1_SHIFT) |
-+ ((dbt->phase_seg2 - 1) << SEG_2_SHIFT) |
-+ ((dbt->sjw - 1) << SJW_SHIFT) |
-+ ((dbt->brp - 1) << PRESC_SHIFT);
-+
-+ if ((((int)(dbt->phase_seg1 + dbt->prop_seg + 1) - 2) < 0) ||
-+ (((int)(dbt->phase_seg2) - 1) < 0) ||
-+ (((int)(dbt->sjw) - 1) < 0) ||
-+ (((int)(dbt->brp) - 1) < 0))
-+ return -EINVAL;
-+
-+ priv->write_reg(priv, CANFD_F_SEG_1_OFFSET, dat_bittiming);
-+ }
-+
-+ canfd_reigister_off_bit(priv, CANFD_CFG_STAT_OFFSET, CAN_FD_OFF_RST_MASK);
-+
-+ netdev_dbg(ndev, "Slow bit rate: %08x\n", priv->read_reg(priv, CANFD_S_SEG_1_OFFSET));
-+ netdev_dbg(ndev, "Fast bit rate: %08x\n", priv->read_reg(priv, CANFD_F_SEG_1_OFFSET));
-+
-+ return 0;
-+}
-+
-+int canfd_get_freebuffer(struct ipms_canfd_priv *priv)
-+{
-+ /* Get next transmit buffer */
-+ canfd_reigister_set_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_SET_TENEXT_MASK);
-+
-+ if (can_ioread8(priv->reg_base + CANFD_TCTRL_OFFSET) & CAN_FD_SET_TENEXT_MASK)
-+ return -1;
-+
-+ return 0;
-+}
-+
-+static void canfd_tx_interrupt(struct net_device *ndev, u8 isr)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+ /* wait till transmission of the PTB or STB finished */
-+ while (isr & (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK)) {
-+ if (isr & CAN_FD_SET_TPIF_MASK)
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_TPIF_MASK);
-+
-+ if (isr & CAN_FD_SET_TSIF_MASK)
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_TSIF_MASK);
-+
-+ isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET);
-+ }
-+ netif_wake_queue(ndev);
-+}
-+
-+static int can_rx(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ struct net_device_stats *stats = &ndev->stats;
-+ struct can_frame *cf;
-+ struct sk_buff *skb;
-+ u32 can_id;
-+ u8 dlc, control, rx_status;
-+
-+ rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+
-+ if (!(rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK))
-+ return 0;
-+ control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+ can_id = priv->read_reg(priv, CANFD_RUBF_ID_OFFSET);
-+ dlc = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET) & CAN_FD_SET_DLC_MASK;
-+
-+ skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
-+ if (!skb) {
-+ stats->rx_dropped++;
-+ return 0;
-+ }
-+ cf->can_dlc = can_cc_dlc2len(dlc);
-+
-+ /* change the CANFD id into socketcan id format */
-+ if (control & CAN_FD_SET_IDE_MASK) {
-+ cf->can_id = can_id;
-+ cf->can_id |= CAN_EFF_FLAG;
-+ } else {
-+ cf->can_id = can_id;
-+ cf->can_id &= (~CAN_EFF_FLAG);
-+ }
-+
-+ if (control & CAN_FD_SET_RTR_MASK)
-+ cf->can_id |= CAN_RTR_FLAG;
-+
-+ if (!(control & CAN_FD_SET_RTR_MASK)) {
-+ *((u32 *)(cf->data + 0)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET);
-+ *((u32 *)(cf->data + 4)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET + 4);
-+ }
-+
-+ canfd_reigister_set_bit(priv, CANFD_RCTRL_OFFSET, CAN_FD_SET_RREL_MASK);
-+ stats->rx_bytes += can_fd_dlc2len(cf->can_dlc);
-+ stats->rx_packets++;
-+ netif_receive_skb(skb);
-+
-+ return 1;
-+}
-+
-+static int canfd_rx(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ struct net_device_stats *stats = &ndev->stats;
-+ struct canfd_frame *cf;
-+ struct sk_buff *skb;
-+ u32 can_id;
-+ u8 dlc, control, rx_status;
-+ int i;
-+
-+ rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+
-+ if (!(rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK))
-+ return 0;
-+ control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+ can_id = priv->read_reg(priv, CANFD_RUBF_ID_OFFSET);
-+ dlc = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET) & CAN_FD_SET_DLC_MASK;
-+
-+ if (control & CAN_FD_SET_EDL_MASK)
-+ /* allocate sk_buffer for canfd frame */
-+ skb = alloc_canfd_skb(ndev, &cf);
-+ else
-+ /* allocate sk_buffer for can frame */
-+ skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
-+
-+ if (!skb) {
-+ stats->rx_dropped++;
-+ return 0;
-+ }
-+
-+ /* change the CANFD or CAN2.0 data into socketcan data format */
-+ if (control & CAN_FD_SET_EDL_MASK)
-+ cf->len = can_fd_dlc2len(dlc);
-+ else
-+ cf->len = can_cc_dlc2len(dlc);
-+
-+ /* change the CANFD id into socketcan id format */
-+ if (control & CAN_FD_SET_EDL_MASK) {
-+ cf->can_id = can_id;
-+ if (control & CAN_FD_SET_IDE_MASK)
-+ cf->can_id |= CAN_EFF_FLAG;
-+ else
-+ cf->can_id &= (~CAN_EFF_FLAG);
-+ } else {
-+ cf->can_id = can_id;
-+ if (control & CAN_FD_SET_IDE_MASK)
-+ cf->can_id |= CAN_EFF_FLAG;
-+ else
-+ cf->can_id &= (~CAN_EFF_FLAG);
-+
-+ if (control & CAN_FD_SET_RTR_MASK)
-+ cf->can_id |= CAN_RTR_FLAG;
-+ }
-+
-+ /* CANFD frames handed over to SKB */
-+ if (control & CAN_FD_SET_EDL_MASK) {
-+ for (i = 0; i < cf->len; i += 4)
-+ *((u32 *)(cf->data + i)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET + i);
-+ } else {
-+ /* skb reads the received datas, if the RTR bit not set */
-+ if (!(control & CAN_FD_SET_RTR_MASK)) {
-+ *((u32 *)(cf->data + 0)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET);
-+ *((u32 *)(cf->data + 4)) = priv->read_reg(priv, CANFD_RBUF_DATA_OFFSET + 4);
-+ }
-+ }
-+
-+ canfd_reigister_set_bit(priv, CANFD_RCTRL_OFFSET, CAN_FD_SET_RREL_MASK);
-+
-+ stats->rx_bytes += cf->len;
-+ stats->rx_packets++;
-+ netif_receive_skb(skb);
-+
-+ return 1;
-+}
-+
-+static int canfd_rx_poll(struct napi_struct *napi, int quota)
-+{
-+ struct net_device *ndev = napi->dev;
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ int work_done = 0;
-+ u8 rx_status = 0, control = 0;
-+
-+ control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+ rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+
-+ /* clear receive interrupt and deal with all the received frames */
-+ while ((rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK) && (work_done < quota)) {
-+ (control & CAN_FD_SET_EDL_MASK) ? (work_done += canfd_rx(ndev)) : (work_done += can_rx(ndev));
-+
-+ control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
-+ rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+ }
-+ napi_complete(napi);
-+ canfd_reigister_set_bit(priv, CANFD_RTIE_OFFSET, CAN_FD_SET_RIE_MASK);
-+ return work_done;
-+}
-+
-+static void canfd_rxfull_interrupt(struct net_device *ndev, u8 isr)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+ if (isr & CAN_FD_SET_RAFIF_MASK)
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_RAFIF_MASK);
-+
-+ if (isr & (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK))
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET,
-+ (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK));
-+}
-+
-+static int set_canfd_xmit_mode(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+ switch (priv->tx_mode) {
-+ case XMIT_FULL:
-+ canfd_reigister_set_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_SET_FULLCAN_MASK);
-+ break;
-+ case XMIT_SEP_FIFO:
-+ canfd_reigister_off_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_OFF_FULLCAN_MASK);
-+ canfd_reigister_set_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_SET_FIFO_MASK);
-+ canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_SET_TBSEL_MASK);
-+ break;
-+ case XMIT_SEP_PRIO:
-+ canfd_reigister_off_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_OFF_FULLCAN_MASK);
-+ canfd_reigister_off_bit(priv, CANFD_TCTRL_OFFSET, CAN_FD_OFF_FIFO_MASK);
-+ canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_SET_TBSEL_MASK);
-+ break;
-+ case XMIT_PTB_MODE:
-+ canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_OFF_TBSEL_MASK);
-+ break;
-+ default:
-+ break;
-+ }
-+ return 0;
-+}
-+
-+static netdev_tx_t canfd_driver_start_xmit(struct sk_buff *skb, struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ struct canfd_frame *cf = (struct canfd_frame *)skb->data;
-+ struct net_device_stats *stats = &ndev->stats;
-+ u32 ttsen, id, ctl, addr_off;
-+ int i;
-+
-+ priv->tx_mode = XMIT_PTB_MODE;
-+
-+ if (can_dropped_invalid_skb(ndev, skb))
-+ return NETDEV_TX_OK;
-+
-+ switch (priv->tx_mode) {
-+ case XMIT_FULL:
-+ return NETDEV_TX_BUSY;
-+ case XMIT_PTB_MODE:
-+ set_canfd_xmit_mode(ndev);
-+ canfd_reigister_off_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_OFF_STBY_MASK);
-+
-+ if (cf->can_id & CAN_EFF_FLAG) {
-+ id = (cf->can_id & CAN_EFF_MASK);
-+ ttsen = 0 << TTSEN_8_32_SHIFT;
-+ id |= ttsen;
-+ } else {
-+ id = (cf->can_id & CAN_SFF_MASK);
-+ ttsen = 0 << TTSEN_8_32_SHIFT;
-+ id |= ttsen;
-+ }
-+
-+ ctl = can_fd_len2dlc(cf->len);
-+
-+ /* transmit can fd frame */
-+ if (priv->can_or_canfd == IPMS_CAN_TYPE_CANFD) {
-+ if (can_is_canfd_skb(skb)) {
-+ if (cf->can_id & CAN_EFF_FLAG)
-+ ctl |= CAN_FD_SET_IDE_MASK;
-+ else
-+ ctl &= CAN_FD_OFF_IDE_MASK;
-+
-+ if (cf->flags & CANFD_BRS)
-+ ctl |= CAN_FD_SET_BRS_MASK;
-+
-+ ctl |= CAN_FD_SET_EDL_MASK;
-+
-+ addr_off = CANFD_TBUF_DATA_OFFSET;
-+
-+ for (i = 0; i < cf->len; i += 4) {
-+ priv->write_reg(priv, addr_off,
-+ *((u32 *)(cf->data + i)));
-+ addr_off += 4;
-+ }
-+ } else {
-+ ctl &= CAN_FD_OFF_EDL_MASK;
-+ ctl &= CAN_FD_OFF_BRS_MASK;
-+
-+ if (cf->can_id & CAN_EFF_FLAG)
-+ ctl |= CAN_FD_SET_IDE_MASK;
-+ else
-+ ctl &= CAN_FD_OFF_IDE_MASK;
-+
-+ if (cf->can_id & CAN_RTR_FLAG) {
-+ ctl |= CAN_FD_SET_RTR_MASK;
-+ priv->write_reg(priv,
-+ CANFD_TBUF_ID_OFFSET, id);
-+ priv->write_reg(priv,
-+ CANFD_TBUF_CTL_OFFSET, ctl);
-+ } else {
-+ ctl &= CAN_FD_OFF_RTR_MASK;
-+ addr_off = CANFD_TBUF_DATA_OFFSET;
-+ priv->write_reg(priv, addr_off,
-+ *((u32 *)(cf->data + 0)));
-+ priv->write_reg(priv, addr_off + 4,
-+ *((u32 *)(cf->data + 4)));
-+ }
-+ }
-+ priv->write_reg(priv, CANFD_TBUF_ID_OFFSET, id);
-+ priv->write_reg(priv, CANFD_TBUF_CTL_OFFSET, ctl);
-+ addr_off = CANFD_TBUF_DATA_OFFSET;
-+ } else {
-+ ctl &= CAN_FD_OFF_EDL_MASK;
-+ ctl &= CAN_FD_OFF_BRS_MASK;
-+
-+ if (cf->can_id & CAN_EFF_FLAG)
-+ ctl |= CAN_FD_SET_IDE_MASK;
-+ else
-+ ctl &= CAN_FD_OFF_IDE_MASK;
-+
-+ if (cf->can_id & CAN_RTR_FLAG) {
-+ ctl |= CAN_FD_SET_RTR_MASK;
-+ priv->write_reg(priv, CANFD_TBUF_ID_OFFSET, id);
-+ priv->write_reg(priv, CANFD_TBUF_CTL_OFFSET, ctl);
-+ } else {
-+ ctl &= CAN_FD_OFF_RTR_MASK;
-+ priv->write_reg(priv, CANFD_TBUF_ID_OFFSET, id);
-+ priv->write_reg(priv, CANFD_TBUF_CTL_OFFSET, ctl);
-+ addr_off = CANFD_TBUF_DATA_OFFSET;
-+ priv->write_reg(priv, addr_off,
-+ *((u32 *)(cf->data + 0)));
-+ priv->write_reg(priv, addr_off + 4,
-+ *((u32 *)(cf->data + 4)));
-+ }
-+ }
-+ canfd_reigister_set_bit(priv, CANFD_TCMD_OFFSET, CAN_FD_SET_TPE_MASK);
-+ stats->tx_bytes += cf->len;
-+ break;
-+ default:
-+ break;
-+ }
-+
-+ /*Due to cache blocking, we need call dev_kfree_skb() here to free the socket
-+ buffer and return NETDEV_TX_OK */
-+ dev_kfree_skb(skb);
-+
-+ return NETDEV_TX_OK;
-+}
-+
-+static int set_reset_mode(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ u8 ret;
-+
-+ ret = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+ ret |= CAN_FD_SET_RST_MASK;
-+ can_iowrite8(ret, priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+ return 0;
-+}
-+
-+static void canfd_driver_stop(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ int ret;
-+
-+ ret = set_reset_mode(ndev);
-+ if (ret)
-+ netdev_err(ndev, "Mode Resetting Failed!\n");
-+
-+ priv->can.state = CAN_STATE_STOPPED;
-+}
-+
-+static int canfd_driver_close(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+ netif_stop_queue(ndev);
-+ napi_disable(&priv->napi);
-+ canfd_driver_stop(ndev);
-+
-+ free_irq(ndev->irq, ndev);
-+ close_candev(ndev);
-+
-+ pm_runtime_put(priv->dev);
-+
-+ return 0;
-+}
-+
-+static enum can_state get_of_chip_status(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ u8 can_stat, eir;
-+
-+ can_stat = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+ eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET);
-+
-+ if (can_stat & CAN_FD_SET_BUSOFF_MASK)
-+ return CAN_STATE_BUS_OFF;
-+
-+ if ((eir & CAN_FD_SET_EPASS_MASK) && ~(can_stat & CAN_FD_SET_BUSOFF_MASK))
-+ return CAN_STATE_ERROR_PASSIVE;
-+
-+ if (eir & CAN_FD_SET_EWARN_MASK && ~(eir & CAN_FD_SET_EPASS_MASK))
-+ return CAN_STATE_ERROR_WARNING;
-+
-+ if (~(eir & CAN_FD_SET_EPASS_MASK))
-+ return CAN_STATE_ERROR_ACTIVE;
-+
-+ return CAN_STATE_ERROR_ACTIVE;
-+}
-+
-+static void canfd_error_interrupt(struct net_device *ndev, u8 isr, u8 eir)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ struct net_device_stats *stats = &ndev->stats;
-+ struct can_frame *cf;
-+ struct sk_buff *skb;
-+ u8 koer, recnt = 0, tecnt = 0, can_stat = 0;
-+
-+ skb = alloc_can_err_skb(ndev, &cf);
-+
-+ koer = can_ioread8(priv->reg_base + CANFD_EALCAP_OFFSET) & CAN_FD_SET_KOER_MASK;
-+ recnt = can_ioread8(priv->reg_base + CANFD_RECNT_OFFSET);
-+ tecnt = can_ioread8(priv->reg_base + CANFD_TECNT_OFFSET);
-+
-+ /*Read can status*/
-+ can_stat = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+ /* Bus off --->active error mode */
-+ if ((isr & CAN_FD_SET_EIF_MASK) && priv->can.state == CAN_STATE_BUS_OFF)
-+ priv->can.state = get_of_chip_status(ndev);
-+
-+ /* State selection */
-+ if (can_stat & CAN_FD_SET_BUSOFF_MASK) {
-+ priv->can.state = get_of_chip_status(ndev);
-+ priv->can.can_stats.bus_off++;
-+ canfd_reigister_set_bit(priv, CANFD_CFG_STAT_OFFSET, CAN_FD_SET_BUSOFF_MASK);
-+ can_bus_off(ndev);
-+ if (skb)
-+ cf->can_id |= CAN_ERR_BUSOFF;
-+
-+ } else if ((eir & CAN_FD_SET_EPASS_MASK) && ~(can_stat & CAN_FD_SET_BUSOFF_MASK)) {
-+ priv->can.state = get_of_chip_status(ndev);
-+ priv->can.can_stats.error_passive++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_CRTL;
-+ cf->data[1] |= (recnt > 127) ? CAN_ERR_CRTL_RX_PASSIVE : 0;
-+ cf->data[1] |= (tecnt > 127) ? CAN_ERR_CRTL_TX_PASSIVE : 0;
-+ cf->data[6] = tecnt;
-+ cf->data[7] = recnt;
-+ }
-+ } else if (eir & CAN_FD_SET_EWARN_MASK && ~(eir & CAN_FD_SET_EPASS_MASK)) {
-+ priv->can.state = get_of_chip_status(ndev);
-+ priv->can.can_stats.error_warning++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_CRTL;
-+ cf->data[1] |= (recnt > 95) ? CAN_ERR_CRTL_RX_WARNING : 0;
-+ cf->data[1] |= (tecnt > 95) ? CAN_ERR_CRTL_TX_WARNING : 0;
-+ cf->data[6] = tecnt;
-+ cf->data[7] = recnt;
-+ }
-+ }
-+
-+ /* Check for in protocol defined error interrupt */
-+ if (eir & CAN_FD_SET_BEIF_MASK) {
-+ if (skb)
-+ cf->can_id |= CAN_ERR_BUSERROR | CAN_ERR_PROT;
-+
-+ /* bit error interrupt */
-+ if (koer == CAN_FD_SET_BIT_ERROR_MASK) {
-+ stats->tx_errors++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_PROT;
-+ cf->data[2] = CAN_ERR_PROT_BIT;
-+ }
-+ }
-+ /* format error interrupt */
-+ if (koer == CAN_FD_SET_FORM_ERROR_MASK) {
-+ stats->rx_errors++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_PROT;
-+ cf->data[2] = CAN_ERR_PROT_FORM;
-+ }
-+ }
-+ /* stuffing error interrupt */
-+ if (koer == CAN_FD_SET_STUFF_ERROR_MASK) {
-+ stats->rx_errors++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_PROT;
-+ cf->data[3] = CAN_ERR_PROT_STUFF;
-+ }
-+ }
-+ /* ack error interrupt */
-+ if (koer == CAN_FD_SET_ACK_ERROR_MASK) {
-+ stats->tx_errors++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_PROT;
-+ cf->data[2] = CAN_ERR_PROT_LOC_ACK;
-+ }
-+ }
-+ /* crc error interrupt */
-+ if (koer == CAN_FD_SET_CRC_ERROR_MASK) {
-+ stats->rx_errors++;
-+ if (skb) {
-+ cf->can_id |= CAN_ERR_PROT;
-+ cf->data[2] = CAN_ERR_PROT_LOC_CRC_SEQ;
-+ }
-+ }
-+ priv->can.can_stats.bus_error++;
-+ }
-+ if (skb) {
-+ stats->rx_packets++;
-+ stats->rx_bytes += cf->can_dlc;
-+ netif_rx(skb);
-+ }
-+
-+ netdev_dbg(ndev, "Recnt is 0x%02x", can_ioread8(priv->reg_base + CANFD_RECNT_OFFSET));
-+ netdev_dbg(ndev, "Tecnt is 0x%02x", can_ioread8(priv->reg_base + CANFD_TECNT_OFFSET));
-+}
-+
-+static irqreturn_t canfd_interrupt(int irq, void *dev_id)
-+{
-+ struct net_device *ndev = (struct net_device *)dev_id;
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ u8 isr, eir;
-+ u8 isr_handled = 0, eir_handled = 0;
-+
-+ /* read the value of interrupt status register */
-+ isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET);
-+
-+ /* read the value of error interrupt register */
-+ eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET);
-+
-+ /* Check for Tx interrupt and Processing it */
-+ if (isr & (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK)) {
-+ canfd_tx_interrupt(ndev, isr);
-+ isr_handled |= (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK);
-+ }
-+ if (isr & (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK)) {
-+ canfd_rxfull_interrupt(ndev, isr);
-+ isr_handled |= (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK);
-+ }
-+ /* Check Rx interrupt and Processing the receive interrupt routine */
-+ if (isr & CAN_FD_SET_RIF_MASK) {
-+ canfd_reigister_off_bit(priv, CANFD_RTIE_OFFSET, CAN_FD_OFF_RIE_MASK);
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_RIF_MASK);
-+
-+ napi_schedule(&priv->napi);
-+ isr_handled |= CAN_FD_SET_RIF_MASK;
-+ }
-+ if ((isr & CAN_FD_SET_EIF_MASK) | (eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK))) {
-+ /* reset EPIF and BEIF. Reset EIF */
-+ canfd_reigister_set_bit(priv, CANFD_ERRINT_OFFSET,
-+ eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK));
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET,
-+ isr & CAN_FD_SET_EIF_MASK);
-+
-+ canfd_error_interrupt(ndev, isr, eir);
-+
-+ isr_handled |= CAN_FD_SET_EIF_MASK;
-+ eir_handled |= (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK);
-+ }
-+ if ((isr_handled == 0) && (eir_handled == 0)) {
-+ netdev_err(ndev, "Unhandled interrupt!\n");
-+ return IRQ_NONE;
-+ }
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static int canfd_chip_start(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ int err;
-+ u8 ret;
-+
-+ err = set_reset_mode(ndev);
-+ if (err) {
-+ netdev_err(ndev, "Mode Resetting Failed!\n");
-+ return err;
-+ }
-+
-+ err = canfd_device_driver_bittime_configuration(ndev);
-+ if (err) {
-+ netdev_err(ndev, "Bittime Setting Failed!\n");
-+ return err;
-+ }
-+
-+ /* Set Almost Full Warning Limit */
-+ canfd_reigister_set_bit(priv, CANFD_LIMIT_OFFSET, CAN_FD_SET_AFWL_MASK);
-+
-+ /* Programmable Error Warning Limit = (EWL+1)*8. Set EWL=11->Error Warning=96 */
-+ canfd_reigister_set_bit(priv, CANFD_LIMIT_OFFSET, CAN_FD_SET_EWL_MASK);
-+
-+ /* Interrupts enable */
-+ can_iowrite8(CAN_FD_INTR_ALL_MASK, priv->reg_base + CANFD_RTIE_OFFSET);
-+
-+ /* Error Interrupts enable(Error Passive and Bus Error) */
-+ canfd_reigister_set_bit(priv, CANFD_ERRINT_OFFSET, CAN_FD_SET_EPIE_MASK);
-+
-+ ret = can_ioread8(priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+ /* Check whether it is loopback mode or normal mode */
-+ if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
-+ ret |= CAN_FD_LBMIMOD_MASK;
-+ } else {
-+ ret &= ~CAN_FD_LBMEMOD_MASK;
-+ ret &= ~CAN_FD_LBMIMOD_MASK;
-+ }
-+
-+ can_iowrite8(ret, priv->reg_base + CANFD_CFG_STAT_OFFSET);
-+
-+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
-+
-+ return 0;
-+}
-+
-+static int canfd_do_set_mode(struct net_device *ndev, enum can_mode mode)
-+{
-+ int ret;
-+
-+ switch (mode) {
-+ case CAN_MODE_START:
-+ ret = canfd_chip_start(ndev);
-+ if (ret) {
-+ netdev_err(ndev, "Could Not Start CAN device !!\n");
-+ return ret;
-+ }
-+ netif_wake_queue(ndev);
-+ break;
-+ default:
-+ ret = -EOPNOTSUPP;
-+ break;
-+ }
-+
-+ return ret;
-+}
-+
-+static int canfd_driver_open(struct net_device *ndev)
-+{
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ int ret;
-+
-+ ret = pm_runtime_get_sync(priv->dev);
-+ if (ret < 0) {
-+ netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
-+ __func__, ret);
-+ goto err;
-+ }
-+
-+ /* Set chip into reset mode */
-+ ret = set_reset_mode(ndev);
-+ if (ret) {
-+ netdev_err(ndev, "Mode Resetting Failed!\n");
-+ return ret;
-+ }
-+
-+ /* Common open */
-+ ret = open_candev(ndev);
-+ if (ret)
-+ return ret;
-+
-+ /* Register interrupt handler */
-+ ret = request_irq(ndev->irq, canfd_interrupt, IRQF_SHARED, ndev->name, ndev);
-+ if (ret) {
-+ netdev_err(ndev, "Request_irq err: %d\n", ret);
-+ goto exit_irq;
-+ }
-+
-+ ret = canfd_chip_start(ndev);
-+ if (ret) {
-+ netdev_err(ndev, "Could Not Start CAN device !\n");
-+ goto exit_can_start;
-+ }
-+
-+ napi_enable(&priv->napi);
-+ netif_start_queue(ndev);
-+
-+ return 0;
-+
-+exit_can_start:
-+ free_irq(ndev->irq, ndev);
-+err:
-+ pm_runtime_put(priv->dev);
-+exit_irq:
-+ close_candev(ndev);
-+ return ret;
-+}
-+
-+static int canfd_control_parse_dt(struct ipms_canfd_priv *priv)
-+{
-+ struct of_phandle_args args;
-+ u32 syscon_mask, syscon_shift;
-+ u32 can_or_canfd;
-+ u32 syscon_offset, regval;
-+ int ret;
-+
-+ ret = of_parse_phandle_with_fixed_args(priv->dev->of_node,
-+ "starfive,sys-syscon", 3, 0, &args);
-+ if (ret) {
-+ dev_err(priv->dev, "Failed to parse starfive,sys-syscon\n");
-+ return -EINVAL;
-+ }
-+
-+ priv->reg_syscon = syscon_node_to_regmap(args.np);
-+ of_node_put(args.np);
-+ if (IS_ERR(priv->reg_syscon))
-+ return PTR_ERR(priv->reg_syscon);
-+
-+ syscon_offset = args.args[0];
-+ syscon_shift = args.args[1];
-+ syscon_mask = args.args[2];
-+
-+ ret = device_property_read_u32(priv->dev, "syscon,can_or_canfd", &can_or_canfd);
-+ if (ret)
-+ goto exit_parse;
-+
-+ priv->can_or_canfd = can_or_canfd;
-+
-+ /* enable can2.0/canfd function */
-+ regval = can_or_canfd << syscon_shift;
-+ ret = regmap_update_bits(priv->reg_syscon, syscon_offset, syscon_mask, regval);
-+ if (ret)
-+ return ret;
-+ return 0;
-+exit_parse:
-+ return ret;
-+}
-+
-+static const struct net_device_ops canfd_netdev_ops = {
-+ .ndo_open = canfd_driver_open,
-+ .ndo_stop = canfd_driver_close,
-+ .ndo_start_xmit = canfd_driver_start_xmit,
-+ .ndo_change_mtu = can_change_mtu,
-+};
-+
-+static int canfd_driver_probe(struct platform_device *pdev)
-+{
-+ struct net_device *ndev;
-+ struct ipms_canfd_priv *priv;
-+ void __iomem *addr;
-+ int ret;
-+ u32 frq;
-+
-+ addr = devm_platform_ioremap_resource(pdev, 0);
-+ if (IS_ERR(addr)) {
-+ ret = PTR_ERR(addr);
-+ goto exit;
-+ }
-+
-+ ndev = alloc_candev(sizeof(struct ipms_canfd_priv), 1);
-+ if (!ndev) {
-+ ret = -ENOMEM;
-+ goto exit;
-+ }
-+
-+ priv = netdev_priv(ndev);
-+ priv->dev = &pdev->dev;
-+
-+ ret = canfd_control_parse_dt(priv);
-+ if (ret)
-+ goto free_exit;
-+
-+ priv->nr_clks = devm_clk_bulk_get_all(priv->dev, &priv->clks);
-+ if (priv->nr_clks < 0) {
-+ dev_err(priv->dev, "Failed to get can clocks\n");
-+ ret = -ENODEV;
-+ goto free_exit;
-+ }
-+
-+ ret = clk_bulk_prepare_enable(priv->nr_clks, priv->clks);
-+ if (ret) {
-+ dev_err(priv->dev, "Failed to enable clocks\n");
-+ goto free_exit;
-+ }
-+
-+ priv->resets = devm_reset_control_array_get_exclusive(priv->dev);
-+ if (IS_ERR(priv->resets)) {
-+ ret = PTR_ERR(priv->resets);
-+ dev_err(priv->dev, "Failed to get can resets");
-+ goto clk_exit;
-+ }
-+
-+ ret = reset_control_deassert(priv->resets);
-+ if (ret)
-+ goto clk_exit;
-+ priv->can.bittiming_const = &canfd_bittiming_const;
-+ priv->can.data_bittiming_const = &canfd_data_bittiming_const;
-+ priv->can.do_set_mode = canfd_do_set_mode;
-+
-+ /* in user space the execution mode can be chosen */
-+ if (priv->can_or_canfd == IPMS_CAN_TYPE_CANFD)
-+ priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_FD;
-+ else
-+ priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK;
-+ priv->reg_base = addr;
-+ priv->write_reg = canfd_write_reg_le;
-+ priv->read_reg = canfd_read_reg_le;
-+
-+ pm_runtime_enable(&pdev->dev);
-+
-+ priv->can_clk = devm_clk_get(&pdev->dev, "core_clk");
-+ if (IS_ERR(priv->can_clk)) {
-+ dev_err(&pdev->dev, "Device clock not found.\n");
-+ ret = PTR_ERR(priv->can_clk);
-+ goto reset_exit;
-+ }
-+
-+ device_property_read_u32(priv->dev, "frequency", &frq);
-+ clk_set_rate(priv->can_clk, frq);
-+
-+ priv->can.clock.freq = clk_get_rate(priv->can_clk);
-+ ndev->irq = platform_get_irq(pdev, 0);
-+
-+ /* we support local echo */
-+ ndev->flags |= IFF_ECHO;
-+ ndev->netdev_ops = &canfd_netdev_ops;
-+
-+ platform_set_drvdata(pdev, ndev);
-+ SET_NETDEV_DEV(ndev, &pdev->dev);
-+
-+ netif_napi_add(ndev, &priv->napi, canfd_rx_poll);
-+ ret = register_candev(ndev);
-+ if (ret) {
-+ dev_err(&pdev->dev, "Fail to register failed (err=%d)\n", ret);
-+ goto reset_exit;
-+ }
-+
-+ dev_dbg(&pdev->dev, "Driver registered: regs=%p, irp=%d, clock=%d\n",
-+ priv->reg_base, ndev->irq, priv->can.clock.freq);
-+
-+ return 0;
-+
-+reset_exit:
-+ reset_control_assert(priv->resets);
-+clk_exit:
-+ clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
-+free_exit:
-+ free_candev(ndev);
-+exit:
-+ return ret;
-+}
-+
-+static void canfd_driver_remove(struct platform_device *pdev)
-+{
-+ struct net_device *ndev = platform_get_drvdata(pdev);
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+ reset_control_assert(priv->resets);
-+ clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
-+ pm_runtime_disable(&pdev->dev);
-+
-+ unregister_candev(ndev);
-+ netif_napi_del(&priv->napi);
-+ free_candev(ndev);
-+}
-+
-+#ifdef CONFIG_PM_SLEEP
-+static int __maybe_unused canfd_suspend(struct device *dev)
-+{
-+ struct net_device *ndev = dev_get_drvdata(dev);
-+
-+ if (netif_running(ndev)) {
-+ netif_stop_queue(ndev);
-+ netif_device_detach(ndev);
-+ canfd_driver_stop(ndev);
-+ }
-+
-+ return pm_runtime_force_suspend(dev);
-+}
-+
-+static int __maybe_unused canfd_resume(struct device *dev)
-+{
-+ struct net_device *ndev = dev_get_drvdata(dev);
-+ int ret;
-+
-+ ret = pm_runtime_force_resume(dev);
-+ if (ret) {
-+ dev_err(dev, "pm_runtime_force_resume failed on resume\n");
-+ return ret;
-+ }
-+
-+ if (netif_running(ndev)) {
-+ ret = canfd_chip_start(ndev);
-+ if (ret) {
-+ dev_err(dev, "canfd_chip_start failed on resume\n");
-+ return ret;
-+ }
-+
-+ netif_device_attach(ndev);
-+ netif_start_queue(ndev);
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+#ifdef CONFIG_PM
-+static int canfd_runtime_suspend(struct device *dev)
-+{
-+ struct net_device *ndev = dev_get_drvdata(dev);
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+
-+ reset_control_assert(priv->resets);
-+ clk_bulk_disable_unprepare(priv->nr_clks, priv->clks);
-+
-+ return 0;
-+}
-+
-+static int canfd_runtime_resume(struct device *dev)
-+{
-+ struct net_device *ndev = dev_get_drvdata(dev);
-+ struct ipms_canfd_priv *priv = netdev_priv(ndev);
-+ int ret;
-+
-+ ret = clk_bulk_prepare_enable(priv->nr_clks, priv->clks);
-+ if (ret) {
-+ dev_err(dev, "Failed to prepare_enable clk\n");
-+ return ret;
-+ }
-+
-+ ret = reset_control_deassert(priv->resets);
-+ if (ret) {
-+ dev_err(dev, "Failed to deassert reset\n");
-+ return ret;
-+ }
-+
-+ return 0;
-+}
-+#endif
-+
-+static const struct dev_pm_ops canfd_pm_ops = {
-+ SET_SYSTEM_SLEEP_PM_OPS(canfd_suspend, canfd_resume)
-+ SET_RUNTIME_PM_OPS(canfd_runtime_suspend,
-+ canfd_runtime_resume, NULL)
-+};
-+
-+static const struct of_device_id canfd_of_match[] = {
-+ { .compatible = "ipms,can" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, canfd_of_match);
-+
-+static struct platform_driver can_driver = {
-+ .probe = canfd_driver_probe,
-+ .remove = canfd_driver_remove,
-+ .driver = {
-+ .name = DRIVER_NAME,
-+ .pm = &canfd_pm_ops,
-+ .of_match_table = canfd_of_match,
-+ },
-+};
-+
-+module_platform_driver(can_driver);
-+
-+MODULE_DESCRIPTION("ipms can controller driver for StarFive jh7110 SoC");
-+MODULE_AUTHOR("William Qiu<william.qiu@starfivetech.com");
-+MODULE_LICENSE("GPL");
+++ /dev/null
-From 356774301b12dbdfe4682e12c57bddb8058014a2 Mon Sep 17 00:00:00 2001
-From: William Qiu <william.qiu@starfivetech.com>
-Date: Sat, 12 Oct 2024 17:56:00 +0800
-Subject: [PATCH 12/55] ipms: CAN: Solve CAN packet leakage problem
-
-Improve RX interrupt trigger mechanism, reduce buffer trigger condition,
-and increase polling value to solve the problem of CAN packet leakage.
-
-Signed-off-by: William Qiu <william.qiu@starfivetech.com>
----
- drivers/net/can/ipms_canfd.c | 108 +++++++++++++++++++----------------
- 1 file changed, 59 insertions(+), 49 deletions(-)
-
---- a/drivers/net/can/ipms_canfd.c
-+++ b/drivers/net/can/ipms_canfd.c
-@@ -5,28 +5,30 @@
- * Copyright (c) 2022 StarFive Technology Co., Ltd.
- */
-
-+#include <linux/can/dev.h>
-+#include <linux/can/error.h>
- #include <linux/clk.h>
--#include <linux/reset.h>
- #include <linux/errno.h>
- #include <linux/init.h>
- #include <linux/interrupt.h>
- #include <linux/io.h>
-+#include <linux/jiffies.h>
- #include <linux/kernel.h>
-+#include <linux/mfd/syscon.h>
- #include <linux/module.h>
- #include <linux/netdevice.h>
- #include <linux/of.h>
-+#include <linux/of_device.h>
- #include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/regmap.h>
-+#include <linux/reset.h>
- #include <linux/skbuff.h>
- #include <linux/string.h>
- #include <linux/types.h>
--#include <linux/can/dev.h>
--#include <linux/can/error.h>
--#include <linux/pm_runtime.h>
--#include <linux/of_device.h>
--#include <linux/mfd/syscon.h>
--#include <linux/regmap.h>
-
- #define DRIVER_NAME "ipms_canfd"
-+#define MAX_IRQ 16
-
- /* CAN registers set */
- enum canfd_device_reg {
-@@ -124,7 +126,7 @@ enum canfd_reg_bitchange {
- CAN_FD_SET_BEIF_MASK = 0x01,
- CAN_FD_OFF_EPIE_MASK = 0xdf,
- CAN_FD_OFF_BEIE_MASK = 0xfd,
-- CAN_FD_SET_AFWL_MASK = 0x40,
-+ CAN_FD_SET_AFWL_MASK = 0x20,
- CAN_FD_SET_EWL_MASK = 0x0b,
- CAN_FD_SET_KOER_MASK = 0xe0,
- CAN_FD_SET_BIT_ERROR_MASK = 0x20,
-@@ -366,12 +368,8 @@ static int can_rx(struct net_device *nde
- struct can_frame *cf;
- struct sk_buff *skb;
- u32 can_id;
-- u8 dlc, control, rx_status;
--
-- rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+ u8 dlc, control;
-
-- if (!(rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK))
-- return 0;
- control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
- can_id = priv->read_reg(priv, CANFD_RUBF_ID_OFFSET);
- dlc = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET) & CAN_FD_SET_DLC_MASK;
-@@ -403,7 +401,7 @@ static int can_rx(struct net_device *nde
- canfd_reigister_set_bit(priv, CANFD_RCTRL_OFFSET, CAN_FD_SET_RREL_MASK);
- stats->rx_bytes += can_fd_dlc2len(cf->can_dlc);
- stats->rx_packets++;
-- netif_receive_skb(skb);
-+ netif_rx(skb);
-
- return 1;
- }
-@@ -419,9 +417,9 @@ static int canfd_rx(struct net_device *n
- int i;
-
- rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
--
- if (!(rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK))
- return 0;
-+
- control = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET);
- can_id = priv->read_reg(priv, CANFD_RUBF_ID_OFFSET);
- dlc = can_ioread8(priv->reg_base + CANFD_RBUF_CTL_OFFSET) & CAN_FD_SET_DLC_MASK;
-@@ -557,6 +555,8 @@ static netdev_tx_t canfd_driver_start_xm
- if (can_dropped_invalid_skb(ndev, skb))
- return NETDEV_TX_OK;
-
-+ netif_stop_queue(ndev);
-+
- switch (priv->tx_mode) {
- case XMIT_FULL:
- return NETDEV_TX_BUSY;
-@@ -837,46 +837,56 @@ static irqreturn_t canfd_interrupt(int i
- {
- struct net_device *ndev = (struct net_device *)dev_id;
- struct ipms_canfd_priv *priv = netdev_priv(ndev);
-- u8 isr, eir;
-+ u8 isr, eir, rx_status;
- u8 isr_handled = 0, eir_handled = 0;
-+ int num = 0;
-
-- /* read the value of interrupt status register */
-- isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET);
--
-- /* read the value of error interrupt register */
-- eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET);
-+ while (((isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET)) ||
-+ (eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET))) &&
-+ num < MAX_IRQ) {
-+ num++;
-+
-+ /* Check for Tx interrupt and Processing it */
-+ if (isr & (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK)) {
-+ canfd_tx_interrupt(ndev, isr);
-+ isr_handled |= (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK);
-+ break;
-+ }
-
-- /* Check for Tx interrupt and Processing it */
-- if (isr & (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK)) {
-- canfd_tx_interrupt(ndev, isr);
-- isr_handled |= (CAN_FD_SET_TPIF_MASK | CAN_FD_SET_TSIF_MASK);
-- }
-- if (isr & (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK)) {
-- canfd_rxfull_interrupt(ndev, isr);
-- isr_handled |= (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK);
-- }
-- /* Check Rx interrupt and Processing the receive interrupt routine */
-- if (isr & CAN_FD_SET_RIF_MASK) {
-- canfd_reigister_off_bit(priv, CANFD_RTIE_OFFSET, CAN_FD_OFF_RIE_MASK);
-- canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, CAN_FD_SET_RIF_MASK);
--
-- napi_schedule(&priv->napi);
-- isr_handled |= CAN_FD_SET_RIF_MASK;
-- }
-- if ((isr & CAN_FD_SET_EIF_MASK) | (eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK))) {
-- /* reset EPIF and BEIF. Reset EIF */
-- canfd_reigister_set_bit(priv, CANFD_ERRINT_OFFSET,
-- eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK));
-- canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET,
-- isr & CAN_FD_SET_EIF_MASK);
-+ if (unlikely(isr & (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK))) {
-+ canfd_rxfull_interrupt(ndev, isr);
-+ isr_handled |= (CAN_FD_SET_RAFIF_MASK | CAN_FD_SET_RFIF_MASK);
-+ }
-
-- canfd_error_interrupt(ndev, isr, eir);
-+ /* Check Rx interrupt and Processing the receive interrupt routine */
-+ if (isr & CAN_FD_SET_RIF_MASK) {
-+ rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+ while (rx_status & CAN_FD_RSTAT_NOT_EMPTY_MASK) {
-+ can_rx(ndev);
-+ rx_status = can_ioread8(priv->reg_base + CANFD_RCTRL_OFFSET);
-+ }
-+ isr_handled |= CAN_FD_SET_RIF_MASK;
-+ }
-
-- isr_handled |= CAN_FD_SET_EIF_MASK;
-- eir_handled |= (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK);
-+ if (unlikely((isr & CAN_FD_SET_EIF_MASK) |
-+ (eir & (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK)))) {
-+ /* reset EPIF and BEIF. Reset EIF */
-+ canfd_reigister_set_bit(priv, CANFD_ERRINT_OFFSET,
-+ eir & (CAN_FD_SET_EPIF_MASK |
-+ CAN_FD_SET_BEIF_MASK));
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET,
-+ isr & CAN_FD_SET_EIF_MASK);
-+ canfd_error_interrupt(ndev, isr, eir);
-+ isr_handled |= CAN_FD_SET_EIF_MASK;
-+ eir_handled |= (CAN_FD_SET_EPIF_MASK | CAN_FD_SET_BEIF_MASK);
-+ }
-+ canfd_reigister_set_bit(priv, CANFD_RTIF_OFFSET, isr);
- }
-- if ((isr_handled == 0) && (eir_handled == 0)) {
-- netdev_err(ndev, "Unhandled interrupt!\n");
-+
-+ if (num == 0) {
-+ isr = can_ioread8(priv->reg_base + CANFD_RTIF_OFFSET);
-+ eir = can_ioread8(priv->reg_base + CANFD_ERRINT_OFFSET);
-+ netdev_err(ndev, "Unhandled interrupt!isr:%x,eir:%x\n", isr, eir);
- return IRQ_NONE;
- }
-
+++ /dev/null
-From 63ebc39891f7b292197f653f8f3aa9dfe35135ee Mon Sep 17 00:00:00 2001
-From: "Kevin.xie" <kevin.xie@starfivetech.com>
-Date: Thu, 24 Nov 2022 16:59:12 +0800
-Subject: [PATCH 13/55] drivers: nvme: Add precheck and delay for CQE pending
- status.
-
-To workaroud the NVMe I/O timeout problem in bootup S10udev case
-which caused by the CQE update lantancy.
-
-Signed-off-by: Kevin.xie <kevin.xie@starfivetech.com>
----
- drivers/nvme/host/pci.c | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/drivers/nvme/host/pci.c
-+++ b/drivers/nvme/host/pci.c
-@@ -28,6 +28,7 @@
- #include <linux/io-64-nonatomic-hi-lo.h>
- #include <linux/sed-opal.h>
- #include <linux/pci-p2pdma.h>
-+#include <linux/delay.h>
-
- #include "trace.h"
- #include "nvme.h"
-@@ -1156,6 +1157,15 @@ static inline int nvme_poll_cq(struct nv
- {
- int found = 0;
-
-+ /*
-+ * In some cases, such as udev trigger, cqe status may update
-+ * a little bit later than MSI, which cause an irq handle missing.
-+ * To workaound, here we will prefetch the status first, and wait
-+ * 1us if we get nothing.
-+ */
-+ if (!nvme_cqe_pending(nvmeq))
-+ udelay(1);
-+
- while (nvme_cqe_pending(nvmeq)) {
- found++;
- /*
+++ /dev/null
-From 16fef31de538ce55e286b630d0b33d872707420d Mon Sep 17 00:00:00 2001
-From: Mason Huo <mason.huo@starfivetech.com>
-Date: Tue, 20 Jun 2023 13:37:52 +0800
-Subject: [PATCH 14/55] riscv: Optimize memcpy with aligned version
-
-Optimizing the 128 byte align case, this will improve the
-performance of large block memcpy.
-
-Here we combine the memcpy of glibc and kernel.
-
-Signed-off-by: Mason Huo <mason.huo@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/lib/Makefile | 3 +-
- arch/riscv/lib/{memcpy.S => memcpy_aligned.S} | 37 +--
- arch/riscv/lib/string.c | 266 ++++++++++++++++++
- 3 files changed, 274 insertions(+), 32 deletions(-)
- rename arch/riscv/lib/{memcpy.S => memcpy_aligned.S} (65%)
- create mode 100644 arch/riscv/lib/string.c
-
---- a/arch/riscv/lib/Makefile
-+++ b/arch/riscv/lib/Makefile
-@@ -1,6 +1,5 @@
- # SPDX-License-Identifier: GPL-2.0-only
- lib-y += delay.o
--lib-y += memcpy.o
- lib-y += memset.o
- lib-y += memmove.o
- ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),)
-@@ -16,6 +15,8 @@ lib-$(CONFIG_MMU) += uaccess.o
- lib-$(CONFIG_64BIT) += tishift.o
- lib-$(CONFIG_RISCV_ISA_ZICBOZ) += clear_page.o
- lib-$(CONFIG_RISCV_ISA_ZBC) += crc32.o
-+lib-y += string.o
-+lib-y += memcpy_aligned.o
-
- obj-$(CONFIG_FUNCTION_ERROR_INJECTION) += error-inject.o
- lib-$(CONFIG_RISCV_ISA_V) += xor.o
---- a/arch/riscv/lib/memcpy.S
-+++ /dev/null
-@@ -1,110 +0,0 @@
--/* SPDX-License-Identifier: GPL-2.0-only */
--/*
-- * Copyright (C) 2013 Regents of the University of California
-- */
--
--#include <linux/linkage.h>
--#include <asm/asm.h>
--
--/* void *memcpy(void *, const void *, size_t) */
--SYM_FUNC_START(__memcpy)
-- move t6, a0 /* Preserve return value */
--
-- /* Defer to byte-oriented copy for small sizes */
-- sltiu a3, a2, 128
-- bnez a3, 4f
-- /* Use word-oriented copy only if low-order bits match */
-- andi a3, t6, SZREG-1
-- andi a4, a1, SZREG-1
-- bne a3, a4, 4f
--
-- beqz a3, 2f /* Skip if already aligned */
-- /*
-- * Round to nearest double word-aligned address
-- * greater than or equal to start address
-- */
-- andi a3, a1, ~(SZREG-1)
-- addi a3, a3, SZREG
-- /* Handle initial misalignment */
-- sub a4, a3, a1
--1:
-- lb a5, 0(a1)
-- addi a1, a1, 1
-- sb a5, 0(t6)
-- addi t6, t6, 1
-- bltu a1, a3, 1b
-- sub a2, a2, a4 /* Update count */
--
--2:
-- andi a4, a2, ~((16*SZREG)-1)
-- beqz a4, 4f
-- add a3, a1, a4
--3:
-- REG_L a4, 0(a1)
-- REG_L a5, SZREG(a1)
-- REG_L a6, 2*SZREG(a1)
-- REG_L a7, 3*SZREG(a1)
-- REG_L t0, 4*SZREG(a1)
-- REG_L t1, 5*SZREG(a1)
-- REG_L t2, 6*SZREG(a1)
-- REG_L t3, 7*SZREG(a1)
-- REG_L t4, 8*SZREG(a1)
-- REG_L t5, 9*SZREG(a1)
-- REG_S a4, 0(t6)
-- REG_S a5, SZREG(t6)
-- REG_S a6, 2*SZREG(t6)
-- REG_S a7, 3*SZREG(t6)
-- REG_S t0, 4*SZREG(t6)
-- REG_S t1, 5*SZREG(t6)
-- REG_S t2, 6*SZREG(t6)
-- REG_S t3, 7*SZREG(t6)
-- REG_S t4, 8*SZREG(t6)
-- REG_S t5, 9*SZREG(t6)
-- REG_L a4, 10*SZREG(a1)
-- REG_L a5, 11*SZREG(a1)
-- REG_L a6, 12*SZREG(a1)
-- REG_L a7, 13*SZREG(a1)
-- REG_L t0, 14*SZREG(a1)
-- REG_L t1, 15*SZREG(a1)
-- addi a1, a1, 16*SZREG
-- REG_S a4, 10*SZREG(t6)
-- REG_S a5, 11*SZREG(t6)
-- REG_S a6, 12*SZREG(t6)
-- REG_S a7, 13*SZREG(t6)
-- REG_S t0, 14*SZREG(t6)
-- REG_S t1, 15*SZREG(t6)
-- addi t6, t6, 16*SZREG
-- bltu a1, a3, 3b
-- andi a2, a2, (16*SZREG)-1 /* Update count */
--
--4:
-- /* Handle trailing misalignment */
-- beqz a2, 6f
-- add a3, a1, a2
--
-- /* Use word-oriented copy if co-aligned to word boundary */
-- or a5, a1, t6
-- or a5, a5, a3
-- andi a5, a5, 3
-- bnez a5, 5f
--7:
-- lw a4, 0(a1)
-- addi a1, a1, 4
-- sw a4, 0(t6)
-- addi t6, t6, 4
-- bltu a1, a3, 7b
--
-- ret
--
--5:
-- lb a4, 0(a1)
-- addi a1, a1, 1
-- sb a4, 0(t6)
-- addi t6, t6, 1
-- bltu a1, a3, 5b
--6:
-- ret
--SYM_FUNC_END(__memcpy)
--SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy)
--SYM_FUNC_ALIAS(__pi_memcpy, __memcpy)
--SYM_FUNC_ALIAS(__pi___memcpy, __memcpy)
---- /dev/null
-+++ b/arch/riscv/lib/memcpy_aligned.S
-@@ -0,0 +1,85 @@
-+/* SPDX-License-Identifier: GPL-2.0-only */
-+/*
-+ * Copyright (C) 2013 Regents of the University of California
-+ */
-+
-+#include <linux/linkage.h>
-+#include <asm/asm.h>
-+
-+/* void *__memcpy_aligned(void *, const void *, size_t) */
-+SYM_FUNC_START(__memcpy_aligned)
-+ move t6, a0 /* Preserve return value */
-+
-+2:
-+ andi a4, a2, ~((16*SZREG)-1)
-+ beqz a4, 4f
-+ add a3, a1, a4
-+3:
-+ REG_L a4, 0(a1)
-+ REG_L a5, SZREG(a1)
-+ REG_L a6, 2*SZREG(a1)
-+ REG_L a7, 3*SZREG(a1)
-+ REG_L t0, 4*SZREG(a1)
-+ REG_L t1, 5*SZREG(a1)
-+ REG_L t2, 6*SZREG(a1)
-+ REG_L t3, 7*SZREG(a1)
-+ REG_L t4, 8*SZREG(a1)
-+ REG_L t5, 9*SZREG(a1)
-+ REG_S a4, 0(t6)
-+ REG_S a5, SZREG(t6)
-+ REG_S a6, 2*SZREG(t6)
-+ REG_S a7, 3*SZREG(t6)
-+ REG_S t0, 4*SZREG(t6)
-+ REG_S t1, 5*SZREG(t6)
-+ REG_S t2, 6*SZREG(t6)
-+ REG_S t3, 7*SZREG(t6)
-+ REG_S t4, 8*SZREG(t6)
-+ REG_S t5, 9*SZREG(t6)
-+ REG_L a4, 10*SZREG(a1)
-+ REG_L a5, 11*SZREG(a1)
-+ REG_L a6, 12*SZREG(a1)
-+ REG_L a7, 13*SZREG(a1)
-+ REG_L t0, 14*SZREG(a1)
-+ REG_L t1, 15*SZREG(a1)
-+ addi a1, a1, 16*SZREG
-+ REG_S a4, 10*SZREG(t6)
-+ REG_S a5, 11*SZREG(t6)
-+ REG_S a6, 12*SZREG(t6)
-+ REG_S a7, 13*SZREG(t6)
-+ REG_S t0, 14*SZREG(t6)
-+ REG_S t1, 15*SZREG(t6)
-+ addi t6, t6, 16*SZREG
-+ bltu a1, a3, 3b
-+ andi a2, a2, (16*SZREG)-1 /* Update count */
-+
-+4:
-+ /* Handle trailing misalignment */
-+ beqz a2, 6f
-+ add a3, a1, a2
-+
-+ /* Use word-oriented copy if co-aligned to word boundary */
-+ or a5, a1, t6
-+ or a5, a5, a3
-+ andi a5, a5, 3
-+ bnez a5, 5f
-+7:
-+ lw a4, 0(a1)
-+ addi a1, a1, 4
-+ sw a4, 0(t6)
-+ addi t6, t6, 4
-+ bltu a1, a3, 7b
-+
-+ ret
-+
-+5:
-+ lb a4, 0(a1)
-+ addi a1, a1, 1
-+ sb a4, 0(t6)
-+ addi t6, t6, 1
-+ bltu a1, a3, 5b
-+6:
-+ ret
-+SYM_FUNC_END(__memcpy_aligned)
-+SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy_aligned)
-+SYM_FUNC_ALIAS(__pi_memcpy, __memcpy_aligned)
-+SYM_FUNC_ALIAS(__pi___memcpy, __memcpy_aligned)
---- /dev/null
-+++ b/arch/riscv/lib/string.c
-@@ -0,0 +1,266 @@
-+// SPDX-License-Identifier: GPL-2.0-only
-+/*
-+ * Copy memory to memory until the specified number of bytes
-+ * has been copied. Overlap is NOT handled correctly.
-+ * Copyright (C) 1991-2020 Free Software Foundation, Inc.
-+ * This file is part of the GNU C Library.
-+ * Contributed by Torbjorn Granlund (tege@sics.se).
-+ *
-+ * The GNU C Library is free software; you can redistribute it and/or
-+ * modify it under the terms of the GNU Lesser General Public
-+ * License as published by the Free Software Foundation; either
-+ * version 2.1 of the License, or (at your option) any later version.
-+ *
-+ * The GNU C Library is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ * Lesser General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU Lesser General Public
-+ * License along with the GNU C Library; if not, see
-+ * <https://www.gnu.org/licenses/>.
-+ *
-+ */
-+
-+#define __NO_FORTIFY
-+#include <linux/types.h>
-+#include <linux/module.h>
-+
-+#define MERGE(w0, sh_1, w1, sh_2) (((w0) >> (sh_1)) | ((w1) << (sh_2)))
-+#define OP_T_THRES 16
-+#define op_t unsigned long
-+#define OPSIZ (sizeof(op_t))
-+#define OPSIZ_MASK (sizeof(op_t) - 1)
-+#define FAST_COPY_THRES (128)
-+#define byte unsigned char
-+
-+static void _wordcopy_fwd_aligned(long dstp, long srcp, size_t len)
-+{
-+ op_t a0, a1;
-+
-+ switch (len % 8) {
-+ case 2:
-+ a0 = ((op_t *) srcp)[0];
-+ srcp -= 6 * OPSIZ;
-+ dstp -= 7 * OPSIZ;
-+ len += 6;
-+ goto do1;
-+ case 3:
-+ a1 = ((op_t *) srcp)[0];
-+ srcp -= 5 * OPSIZ;
-+ dstp -= 6 * OPSIZ;
-+ len += 5;
-+ goto do2;
-+ case 4:
-+ a0 = ((op_t *) srcp)[0];
-+ srcp -= 4 * OPSIZ;
-+ dstp -= 5 * OPSIZ;
-+ len += 4;
-+ goto do3;
-+ case 5:
-+ a1 = ((op_t *) srcp)[0];
-+ srcp -= 3 * OPSIZ;
-+ dstp -= 4 * OPSIZ;
-+ len += 3;
-+ goto do4;
-+ case 6:
-+ a0 = ((op_t *) srcp)[0];
-+ srcp -= 2 * OPSIZ;
-+ dstp -= 3 * OPSIZ;
-+ len += 2;
-+ goto do5;
-+ case 7:
-+ a1 = ((op_t *) srcp)[0];
-+ srcp -= 1 * OPSIZ;
-+ dstp -= 2 * OPSIZ;
-+ len += 1;
-+ goto do6;
-+
-+ case 0:
-+ if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+ return;
-+ a0 = ((op_t *) srcp)[0];
-+ srcp -= 0 * OPSIZ;
-+ dstp -= 1 * OPSIZ;
-+ goto do7;
-+ case 1:
-+ a1 = ((op_t *) srcp)[0];
-+ srcp -= -1 * OPSIZ;
-+ dstp -= 0 * OPSIZ;
-+ len -= 1;
-+ if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+ goto do0;
-+ goto do8; /* No-op. */
-+ }
-+
-+ do {
-+do8:
-+ a0 = ((op_t *) srcp)[0];
-+ ((op_t *) dstp)[0] = a1;
-+do7:
-+ a1 = ((op_t *) srcp)[1];
-+ ((op_t *) dstp)[1] = a0;
-+do6:
-+ a0 = ((op_t *) srcp)[2];
-+ ((op_t *) dstp)[2] = a1;
-+do5:
-+ a1 = ((op_t *) srcp)[3];
-+ ((op_t *) dstp)[3] = a0;
-+do4:
-+ a0 = ((op_t *) srcp)[4];
-+ ((op_t *) dstp)[4] = a1;
-+do3:
-+ a1 = ((op_t *) srcp)[5];
-+ ((op_t *) dstp)[5] = a0;
-+do2:
-+ a0 = ((op_t *) srcp)[6];
-+ ((op_t *) dstp)[6] = a1;
-+do1:
-+ a1 = ((op_t *) srcp)[7];
-+ ((op_t *) dstp)[7] = a0;
-+
-+ srcp += 8 * OPSIZ;
-+ dstp += 8 * OPSIZ;
-+ len -= 8;
-+ } while (len != 0);
-+
-+ /* This is the right position for do0. Please don't move
-+ * it into the loop.
-+ */
-+do0:
-+ ((op_t *) dstp)[0] = a1;
-+}
-+
-+static void _wordcopy_fwd_dest_aligned(long dstp, long srcp, size_t len)
-+{
-+ op_t a0, a1, a2, a3;
-+ int sh_1, sh_2;
-+
-+ /* Calculate how to shift a word read at the memory operation
-+ * aligned srcp to make it aligned for copy.
-+ */
-+
-+ sh_1 = 8 * (srcp % OPSIZ);
-+ sh_2 = 8 * OPSIZ - sh_1;
-+
-+ /* Make SRCP aligned by rounding it down to the beginning of the `op_t'
-+ * it points in the middle of.
-+ */
-+ srcp &= -OPSIZ;
-+
-+ switch (len % 4) {
-+ case 2:
-+ a1 = ((op_t *) srcp)[0];
-+ a2 = ((op_t *) srcp)[1];
-+ srcp -= 1 * OPSIZ;
-+ dstp -= 3 * OPSIZ;
-+ len += 2;
-+ goto do1;
-+ case 3:
-+ a0 = ((op_t *) srcp)[0];
-+ a1 = ((op_t *) srcp)[1];
-+ srcp -= 0 * OPSIZ;
-+ dstp -= 2 * OPSIZ;
-+ len += 1;
-+ goto do2;
-+ case 0:
-+ if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+ return;
-+ a3 = ((op_t *) srcp)[0];
-+ a0 = ((op_t *) srcp)[1];
-+ srcp -= -1 * OPSIZ;
-+ dstp -= 1 * OPSIZ;
-+ len += 0;
-+ goto do3;
-+ case 1:
-+ a2 = ((op_t *) srcp)[0];
-+ a3 = ((op_t *) srcp)[1];
-+ srcp -= -2 * OPSIZ;
-+ dstp -= 0 * OPSIZ;
-+ len -= 1;
-+ if (OP_T_THRES <= 3 * OPSIZ && len == 0)
-+ goto do0;
-+ goto do4; /* No-op. */
-+ }
-+
-+ do {
-+do4:
-+ a0 = ((op_t *) srcp)[0];
-+ ((op_t *) dstp)[0] = MERGE(a2, sh_1, a3, sh_2);
-+do3:
-+ a1 = ((op_t *) srcp)[1];
-+ ((op_t *) dstp)[1] = MERGE(a3, sh_1, a0, sh_2);
-+do2:
-+ a2 = ((op_t *) srcp)[2];
-+ ((op_t *) dstp)[2] = MERGE(a0, sh_1, a1, sh_2);
-+do1:
-+ a3 = ((op_t *) srcp)[3];
-+ ((op_t *) dstp)[3] = MERGE(a1, sh_1, a2, sh_2);
-+
-+ srcp += 4 * OPSIZ;
-+ dstp += 4 * OPSIZ;
-+ len -= 4;
-+ } while (len != 0);
-+
-+ /* This is the right position for do0. Please don't move
-+ * it into the loop.
-+ */
-+do0:
-+ ((op_t *) dstp)[0] = MERGE(a2, sh_1, a3, sh_2);
-+}
-+
-+#define BYTE_COPY_FWD(dst_bp, src_bp, nbytes) \
-+do { \
-+ size_t __nbytes = (nbytes); \
-+ while (__nbytes > 0) { \
-+ byte __x = ((byte *) src_bp)[0]; \
-+ src_bp += 1; \
-+ __nbytes -= 1; \
-+ ((byte *) dst_bp)[0] = __x; \
-+ dst_bp += 1; \
-+ } \
-+} while (0)
-+
-+#define WORD_COPY_FWD(dst_bp, src_bp, nbytes_left, nbytes) \
-+do { \
-+ if (src_bp % OPSIZ == 0) \
-+ _wordcopy_fwd_aligned(dst_bp, src_bp, (nbytes) / OPSIZ); \
-+ else \
-+ _wordcopy_fwd_dest_aligned(dst_bp, src_bp, (nbytes) / OPSIZ); \
-+ src_bp += (nbytes) & -OPSIZ; \
-+ dst_bp += (nbytes) & -OPSIZ; \
-+ (nbytes_left) = (nbytes) % OPSIZ; \
-+} while (0)
-+
-+extern void *__memcpy_aligned(void *dest, const void *src, size_t len);
-+void *__memcpy(void *dest, const void *src, size_t len)
-+{
-+ unsigned long dstp = (long) dest;
-+ unsigned long srcp = (long) src;
-+
-+ /* If there not too few bytes to copy, use word copy. */
-+ if (len >= OP_T_THRES) {
-+ if ((len >= FAST_COPY_THRES) && ((dstp & OPSIZ_MASK) == 0) &&
-+ ((srcp & OPSIZ_MASK) == 0)) {
-+ __memcpy_aligned(dest, src, len);
-+ return dest;
-+ }
-+ /* Copy just a few bytes to make DSTP aligned. */
-+ len -= (-dstp) % OPSIZ;
-+ BYTE_COPY_FWD(dstp, srcp, (-dstp) % OPSIZ);
-+
-+ /* Copy from SRCP to DSTP taking advantage of the known alignment of
-+ * DSTP. Number of bytes remaining is put in the third argument,
-+ * i.e. in LEN. This number may vary from machine to machine.
-+ */
-+ WORD_COPY_FWD(dstp, srcp, len, len);
-+ /* Fall out and copy the tail. */
-+ }
-+
-+ /* There are just a few bytes to copy. Use byte memory operations. */
-+ BYTE_COPY_FWD(dstp, srcp, len);
-+
-+ return dest;
-+}
-+
-+void *memcpy(void *dest, const void *src, size_t len) __weak __alias(__memcpy);
+++ /dev/null
-From a0eaebc3b3ae079772c1022c47d704c887c375d0 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Sun, 4 Feb 2024 15:27:09 +0800
-Subject: [PATCH 15/55] riscv/purgatory: Change memcpy to the aligned version
-
-Change memcpy to the aligned version, for purgatory.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/purgatory/Makefile | 7 +++++--
- 1 file changed, 5 insertions(+), 2 deletions(-)
-
---- a/arch/riscv/purgatory/Makefile
-+++ b/arch/riscv/purgatory/Makefile
-@@ -1,6 +1,6 @@
- # SPDX-License-Identifier: GPL-2.0
-
--purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy.o memset.o
-+purgatory-y := purgatory.o sha256.o entry.o string.o ctype.o memcpy_aligned.o memcpy.o memset.o
- ifeq ($(CONFIG_KASAN_GENERIC)$(CONFIG_KASAN_SW_TAGS),)
- purgatory-y += strcmp.o strlen.o strncmp.o
- endif
-@@ -14,9 +14,12 @@ $(obj)/string.o: $(srctree)/lib/string.c
- $(obj)/ctype.o: $(srctree)/lib/ctype.c FORCE
- $(call if_changed_rule,cc_o_c)
-
--$(obj)/memcpy.o: $(srctree)/arch/riscv/lib/memcpy.S FORCE
-+$(obj)/memcpy_aligned.o: $(srctree)/arch/riscv/lib/memcpy_aligned.S FORCE
- $(call if_changed_rule,as_o_S)
-
-+$(obj)/memcpy.o: $(srctree)/arch/riscv/lib/string.c FORCE
-+ $(call if_changed_rule,cc_o_c)
-+
- $(obj)/memset.o: $(srctree)/arch/riscv/lib/memset.S FORCE
- $(call if_changed_rule,as_o_S)
-
+++ /dev/null
-From 9b8ac2217743a522f0c4f3e360f089b434fcd04b Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Tue, 21 Jan 2025 11:42:35 +0800
-Subject: [PATCH 16/55] riscv: Fix __memcpy_aligned alias
-
-Don't set the weak global alias of memcpy_aligned to memcpy.
-This affected iperf3 test.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- arch/riscv/lib/memcpy_aligned.S | 1 -
- 1 file changed, 1 deletion(-)
-
---- a/arch/riscv/lib/memcpy_aligned.S
-+++ b/arch/riscv/lib/memcpy_aligned.S
-@@ -80,6 +80,5 @@ SYM_FUNC_START(__memcpy_aligned)
- 6:
- ret
- SYM_FUNC_END(__memcpy_aligned)
--SYM_FUNC_ALIAS_WEAK(memcpy, __memcpy_aligned)
- SYM_FUNC_ALIAS(__pi_memcpy, __memcpy_aligned)
- SYM_FUNC_ALIAS(__pi___memcpy, __memcpy_aligned)
+++ /dev/null
-From 8ea9ae21bde99c2c1832f364f973895e108a4851 Mon Sep 17 00:00:00 2001
-From: Minda Chen <minda.chen@starfivetech.com>
-Date: Thu, 18 Jul 2024 17:22:53 +0800
-Subject: [PATCH 17/55] plic: irq: Set IRQCHIP_EOI_THREADED in PREEMPT_RT case
-
-In ipms can device or other device, interrupt is trigger by level.
-in PREEMPT_RT case. irq handle is in thread, If not set
-IRQCHIP_EOI_THREADED, device irq in PLIC is cleared first, but
-device irq reg is not clear, So the interrupt will be triggered
-again, IRQCHIP_EOI_THREADED will clear device PLIC IRQ status
-after clear device irq reg.
-
-Signed-off-by: Minda Chen <minda.chen@starfivetech.com>
----
- drivers/irqchip/irq-sifive-plic.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/irqchip/irq-sifive-plic.c
-+++ b/drivers/irqchip/irq-sifive-plic.c
-@@ -209,6 +209,9 @@ static struct irq_chip plic_edge_chip =
- #endif
- .irq_set_type = plic_irq_set_type,
- .flags = IRQCHIP_SKIP_SET_WAKE |
-+#ifdef CONFIG_PREEMPT_RT
-+ IRQCHIP_EOI_THREADED |
-+#endif
- IRQCHIP_AFFINITY_PRE_STARTUP,
- };
-
-@@ -224,6 +227,9 @@ static struct irq_chip plic_chip = {
- #endif
- .irq_set_type = plic_irq_set_type,
- .flags = IRQCHIP_SKIP_SET_WAKE |
-+#ifdef CONFIG_PREEMPT_RT
-+ IRQCHIP_EOI_THREADED |
-+#endif
- IRQCHIP_AFFINITY_PRE_STARTUP,
- };
-
+++ /dev/null
-From b37b26232ebb6c0a61b530f11ccd6eefdf782c04 Mon Sep 17 00:00:00 2001
-From: "shanlong.li" <shanlong.li@starfivetech.com>
-Date: Fri, 16 Jun 2023 03:02:14 -0700
-Subject: [PATCH 18/55] driver:e24: add e24 driver
-
-add e24 driver
-
-Signed-off-by: shanlong.li <shanlong.li@starfivetech.com>
----
- drivers/Kconfig | 1 +
- drivers/Makefile | 1 +
- drivers/e24/Kconfig | 5 +
- drivers/e24/Makefile | 12 +
- drivers/e24/e24_alloc.c | 241 ++++++
- drivers/e24/e24_alloc.h | 59 ++
- drivers/e24/starfive_e24.c | 1524 +++++++++++++++++++++++++++++++++
- drivers/e24/starfive_e24.h | 159 ++++
- drivers/e24/starfive_e24_hw.c | 134 +++
- drivers/e24/starfive_e24_hw.h | 94 ++
- 10 files changed, 2230 insertions(+)
- create mode 100644 drivers/e24/Kconfig
- create mode 100644 drivers/e24/Makefile
- create mode 100644 drivers/e24/e24_alloc.c
- create mode 100644 drivers/e24/e24_alloc.h
- create mode 100644 drivers/e24/starfive_e24.c
- create mode 100644 drivers/e24/starfive_e24.h
- create mode 100644 drivers/e24/starfive_e24_hw.c
- create mode 100644 drivers/e24/starfive_e24_hw.h
-
---- a/drivers/Kconfig
-+++ b/drivers/Kconfig
-@@ -245,4 +245,5 @@ source "drivers/cdx/Kconfig"
-
- source "drivers/dpll/Kconfig"
-
-+source "drivers/e24/Kconfig"
- endmenu
---- a/drivers/Makefile
-+++ b/drivers/Makefile
-@@ -195,3 +195,4 @@ obj-$(CONFIG_CDX_BUS) += cdx/
- obj-$(CONFIG_DPLL) += dpll/
-
- obj-$(CONFIG_S390) += s390/
-+obj-$(CONFIG_E24) += e24/
---- /dev/null
-+++ b/drivers/e24/Kconfig
-@@ -0,0 +1,5 @@
-+config E24
-+ tristate "E24 support"
-+ default m
-+ help
-+ This module provides the function of E24 device.
---- /dev/null
-+++ b/drivers/e24/Makefile
-@@ -0,0 +1,12 @@
-+# SPDX-License-Identifier: GPL-2.0
-+# Copyright(c) 1999 - 2018 Intel Corporation.
-+#
-+# Makefile for the E24 driver
-+#
-+ccflags-y += -I$(srctree)/drivers/e24
-+#ccflags-y += -DDEBUG
-+ccflags-y += -Wunused-variable -Wno-error=missing-prototypes
-+
-+obj-$(CONFIG_E24) += e24.o
-+
-+e24-y := starfive_e24.o starfive_e24_hw.o e24_alloc.o
---- /dev/null
-+++ b/drivers/e24/e24_alloc.c
-@@ -0,0 +1,241 @@
-+// SPDX-License-Identifier: GPL-2.0
-+#include <linux/atomic.h>
-+#include <linux/kernel.h>
-+#include <linux/mutex.h>
-+#include <linux/printk.h>
-+#include <linux/slab.h>
-+#include "e24_alloc.h"
-+
-+struct e24_private_pool {
-+ struct e24_allocation_pool pool;
-+ struct mutex free_list_lock;
-+ phys_addr_t start;
-+ u32 size;
-+ struct e24_allocation *free_list;
-+};
-+
-+static void e24_private_free(struct e24_allocation *e24_allocation)
-+{
-+ struct e24_private_pool *pool = container_of(e24_allocation->pool,
-+ struct e24_private_pool,
-+ pool);
-+ struct e24_allocation **pcur;
-+
-+ pr_debug("%s: %pap x %d\n", __func__,
-+ &e24_allocation->start, e24_allocation->size);
-+
-+ mutex_lock(&pool->free_list_lock);
-+
-+ for (pcur = &pool->free_list; ; pcur = &(*pcur)->next) {
-+ struct e24_allocation *cur = *pcur;
-+
-+ if (cur && cur->start + cur->size == e24_allocation->start) {
-+ struct e24_allocation *next = cur->next;
-+
-+ pr_debug("merging block tail: %pap x 0x%x ->\n",
-+ &cur->start, cur->size);
-+ cur->size += e24_allocation->size;
-+ pr_debug("... -> %pap x 0x%x\n",
-+ &cur->start, cur->size);
-+ kfree(e24_allocation);
-+
-+ if (next && cur->start + cur->size == next->start) {
-+ pr_debug("merging with next block: %pap x 0x%x ->\n",
-+ &cur->start, cur->size);
-+ cur->size += next->size;
-+ cur->next = next->next;
-+ pr_debug("... -> %pap x 0x%x\n",
-+ &cur->start, cur->size);
-+ kfree(next);
-+ }
-+ break;
-+ }
-+
-+ if (!cur || e24_allocation->start < cur->start) {
-+ if (cur && e24_allocation->start + e24_allocation->size ==
-+ cur->start) {
-+ pr_debug("merging block head: %pap x 0x%x ->\n",
-+ &cur->start, cur->size);
-+ cur->size += e24_allocation->size;
-+ cur->start = e24_allocation->start;
-+ pr_debug("... -> %pap x 0x%x\n",
-+ &cur->start, cur->size);
-+ kfree(e24_allocation);
-+ } else {
-+ pr_debug("inserting new free block\n");
-+ e24_allocation->next = cur;
-+ *pcur = e24_allocation;
-+ }
-+ break;
-+ }
-+ }
-+
-+ mutex_unlock(&pool->free_list_lock);
-+}
-+
-+static long e24_private_alloc(struct e24_allocation_pool *pool,
-+ u32 size, u32 align,
-+ struct e24_allocation **alloc)
-+{
-+ struct e24_private_pool *ppool = container_of(pool,
-+ struct e24_private_pool,
-+ pool);
-+ struct e24_allocation **pcur;
-+ struct e24_allocation *cur = NULL;
-+ struct e24_allocation *new;
-+ phys_addr_t aligned_start = 0;
-+ bool found = false;
-+
-+ if (!size || (align & (align - 1)))
-+ return -EINVAL;
-+ if (!align)
-+ align = 1;
-+
-+ new = kzalloc(sizeof(struct e24_allocation), GFP_KERNEL);
-+ if (!new)
-+ return -ENOMEM;
-+
-+ align = ALIGN(align, PAGE_SIZE);
-+ size = ALIGN(size, PAGE_SIZE);
-+
-+ mutex_lock(&ppool->free_list_lock);
-+
-+ /* on exit free list is fixed */
-+ for (pcur = &ppool->free_list; *pcur; pcur = &(*pcur)->next) {
-+ cur = *pcur;
-+ aligned_start = ALIGN(cur->start, align);
-+
-+ if (aligned_start >= cur->start &&
-+ aligned_start - cur->start + size <= cur->size) {
-+ if (aligned_start == cur->start) {
-+ if (aligned_start + size == cur->start + cur->size) {
-+ pr_debug("reusing complete block: %pap x %x\n",
-+ &cur->start, cur->size);
-+ *pcur = cur->next;
-+ } else {
-+ pr_debug("cutting block head: %pap x %x ->\n",
-+ &cur->start, cur->size);
-+ cur->size -= aligned_start + size - cur->start;
-+ cur->start = aligned_start + size;
-+ pr_debug("... -> %pap x %x\n",
-+ &cur->start, cur->size);
-+ cur = NULL;
-+ }
-+ } else {
-+ if (aligned_start + size == cur->start + cur->size) {
-+ pr_debug("cutting block tail: %pap x %x ->\n",
-+ &cur->start, cur->size);
-+ cur->size = aligned_start - cur->start;
-+ pr_debug("... -> %pap x %x\n",
-+ &cur->start, cur->size);
-+ cur = NULL;
-+ } else {
-+ pr_debug("splitting block into two: %pap x %x ->\n",
-+ &cur->start, cur->size);
-+ new->start = aligned_start + size;
-+ new->size = cur->start +
-+ cur->size - new->start;
-+
-+ cur->size = aligned_start - cur->start;
-+
-+ new->next = cur->next;
-+ cur->next = new;
-+ pr_debug("... -> %pap x %x + %pap x %x\n",
-+ &cur->start, cur->size,
-+ &new->start, new->size);
-+
-+ cur = NULL;
-+ new = NULL;
-+ }
-+ }
-+ found = true;
-+ break;
-+ } else {
-+ cur = NULL;
-+ }
-+ }
-+
-+ mutex_unlock(&ppool->free_list_lock);
-+
-+ if (!found) {
-+ kfree(cur);
-+ kfree(new);
-+ return -ENOMEM;
-+ }
-+
-+ if (!cur) {
-+ cur = new;
-+ new = NULL;
-+ }
-+ if (!cur) {
-+ cur = kzalloc(sizeof(struct e24_allocation), GFP_KERNEL);
-+ if (!cur)
-+ return -ENOMEM;
-+ }
-+
-+ kfree(new);
-+ pr_debug("returning: %pap x %x\n", &aligned_start, size);
-+ cur->start = aligned_start;
-+ cur->size = size;
-+ cur->pool = pool;
-+ atomic_set(&cur->ref, 0);
-+ atomic_inc(&cur->ref);
-+ *alloc = cur;
-+
-+ return 0;
-+}
-+
-+static void e24_private_free_pool(struct e24_allocation_pool *pool)
-+{
-+ struct e24_private_pool *ppool = container_of(pool,
-+ struct e24_private_pool,
-+ pool);
-+ kfree(ppool->free_list);
-+ kfree(ppool);
-+}
-+
-+static phys_addr_t e24_private_offset(const struct e24_allocation *allocation)
-+{
-+ struct e24_private_pool *ppool = container_of(allocation->pool,
-+ struct e24_private_pool,
-+ pool);
-+ return allocation->start - ppool->start;
-+}
-+
-+static const struct e24_allocation_ops e24_private_pool_ops = {
-+ .alloc = e24_private_alloc,
-+ .free = e24_private_free,
-+ .free_pool = e24_private_free_pool,
-+ .offset = e24_private_offset,
-+};
-+
-+long e24_init_private_pool(struct e24_allocation_pool **ppool,
-+ phys_addr_t start, u32 size)
-+{
-+ struct e24_private_pool *pool = kmalloc(sizeof(*pool), GFP_KERNEL);
-+ struct e24_allocation *allocation = kmalloc(sizeof(*allocation),
-+ GFP_KERNEL);
-+
-+ if (!pool || !allocation) {
-+ kfree(pool);
-+ kfree(allocation);
-+ return -ENOMEM;
-+ }
-+
-+ *allocation = (struct e24_allocation){
-+ .pool = &pool->pool,
-+ .start = start,
-+ .size = size,
-+ };
-+ *pool = (struct e24_private_pool){
-+ .pool = {
-+ .ops = &e24_private_pool_ops,
-+ },
-+ .start = start,
-+ .size = size,
-+ .free_list = allocation,
-+ };
-+ mutex_init(&pool->free_list_lock);
-+ *ppool = &pool->pool;
-+ return 0;
-+}
---- /dev/null
-+++ b/drivers/e24/e24_alloc.h
-@@ -0,0 +1,59 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#ifndef E24_ALLOC_H
-+#define E24_ALLOC_H
-+
-+struct e24_allocation_pool;
-+struct e24_allocation;
-+
-+struct e24_allocation_ops {
-+ long (*alloc)(struct e24_allocation_pool *allocation_pool,
-+ u32 size, u32 align, struct e24_allocation **alloc);
-+ void (*free)(struct e24_allocation *allocation);
-+ void (*free_pool)(struct e24_allocation_pool *allocation_pool);
-+ phys_addr_t (*offset)(const struct e24_allocation *allocation);
-+};
-+
-+struct e24_allocation_pool {
-+ const struct e24_allocation_ops *ops;
-+};
-+
-+struct e24_allocation {
-+ struct e24_allocation_pool *pool;
-+ struct e24_allocation *next;
-+ phys_addr_t start;
-+ u32 size;
-+ atomic_t ref;
-+};
-+
-+static inline void e24_free_pool(struct e24_allocation_pool *allocation_pool)
-+{
-+ allocation_pool->ops->free_pool(allocation_pool);
-+}
-+
-+static inline void e24_free(struct e24_allocation *allocation)
-+{
-+ return allocation->pool->ops->free(allocation);
-+}
-+
-+static inline long e24_allocate(struct e24_allocation_pool *allocation_pool,
-+ u32 size, u32 align,
-+ struct e24_allocation **alloc)
-+{
-+ return allocation_pool->ops->alloc(allocation_pool,
-+ size, align, alloc);
-+}
-+
-+static inline void e24_allocation_put(struct e24_allocation *e24_allocation)
-+{
-+ if (atomic_dec_and_test(&e24_allocation->ref))
-+ e24_allocation->pool->ops->free(e24_allocation);
-+}
-+
-+static inline phys_addr_t e24_allocation_offset(const struct e24_allocation *allocation)
-+{
-+ return allocation->pool->ops->offset(allocation);
-+}
-+
-+long e24_init_private_pool(struct e24_allocation_pool **ppool, phys_addr_t start, u32 size);
-+
-+#endif
---- /dev/null
-+++ b/drivers/e24/starfive_e24.c
-@@ -0,0 +1,1522 @@
-+// SPDX-License-Identifier: GPL-2.0
-+/*
-+ * e24 driver for StarFive JH7110 SoC
-+ *
-+ * Copyright (c) 2021 StarFive Technology Co., Ltd.
-+ * Author: Shanlong Li <shanlong.li@starfivetech.com>
-+ */
-+#include <linux/version.h>
-+#include <linux/atomic.h>
-+#include <linux/acpi.h>
-+#include <linux/completion.h>
-+#include <linux/delay.h>
-+#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 16, 0)
-+#include <linux/dma-mapping.h>
-+#else
-+#include <linux/dma-direct.h>
-+#endif
-+#include <linux/firmware.h>
-+#include <linux/fs.h>
-+#include <linux/hashtable.h>
-+#include <linux/highmem.h>
-+#include <linux/idr.h>
-+#include <linux/interrupt.h>
-+#include <linux/io.h>
-+#include <linux/kernel.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/of_address.h>
-+#include <linux/of_device.h>
-+#include <linux/of_reserved_mem.h>
-+#include <linux/platform_device.h>
-+#include <linux/pm_runtime.h>
-+#include <linux/property.h>
-+#include <linux/sched.h>
-+#include <linux/slab.h>
-+#include <linux/sort.h>
-+#include <linux/mman.h>
-+#include <linux/uaccess.h>
-+#include <linux/mailbox_controller.h>
-+#include <linux/mailbox_client.h>
-+
-+#include <linux/bsearch.h>
-+
-+#include "e24_alloc.h"
-+#include "starfive_e24.h"
-+#include "starfive_e24_hw.h"
-+
-+#define EMBOX_MAX_MSG_LEN 4
-+
-+static DEFINE_IDA(e24_nodeid);
-+
-+struct e24_dsp_cmd {
-+ __u32 flags;
-+ __u32 in_data_size;
-+ __u32 out_data_size;
-+ union {
-+ __u32 in_data_addr;
-+ __u8 in_data[E24_DSP_CMD_INLINE_DATA_SIZE];
-+ };
-+ union {
-+ __u32 out_data_addr;
-+ __u8 out_data[E24_DSP_CMD_INLINE_DATA_SIZE];
-+ };
-+};
-+
-+struct e24_ioctl_user {
-+ u32 flags;
-+ u32 in_data_size;
-+ u32 out_data_size;
-+ u64 in_data_addr;
-+ u64 out_data_addr;
-+};
-+
-+struct e24_ioctl_request {
-+ struct e24_ioctl_user ioctl_data;
-+ phys_addr_t in_data_phys;
-+ phys_addr_t out_data_phys;
-+ struct e24_mapping *buffer_mapping;
-+
-+ union {
-+ struct e24_mapping in_data_mapping;
-+ u8 in_data[E24_DSP_CMD_INLINE_DATA_SIZE];
-+ };
-+ union {
-+ struct e24_mapping out_data_mapping;
-+ u8 out_data[E24_DSP_CMD_INLINE_DATA_SIZE];
-+ };
-+};
-+
-+static int firmware_command_timeout = 10;
-+
-+static inline void e24_comm_read(volatile void __iomem *addr, void *p,
-+ size_t sz)
-+{
-+ size_t sz32 = sz & ~3;
-+ u32 v;
-+
-+ while (sz32) {
-+ v = __raw_readl(addr);
-+ memcpy(p, &v, sizeof(v));
-+ p += 4;
-+ addr += 4;
-+ sz32 -= 4;
-+ }
-+ sz &= 3;
-+ if (sz) {
-+ v = __raw_readl(addr);
-+ memcpy(p, &v, sz);
-+ }
-+}
-+
-+static inline void e24_comm_write(volatile void __iomem *addr, const void *p,
-+ size_t sz)
-+{
-+ size_t sz32 = sz & ~3;
-+ u32 v;
-+
-+ while (sz32) {
-+ memcpy(&v, p, sizeof(v));
-+ __raw_writel(v, addr);
-+ p += 4;
-+ addr += 4;
-+ sz32 -= 4;
-+ }
-+ sz &= 3;
-+ if (sz) {
-+ v = 0;
-+ memcpy(&v, p, sz);
-+ __raw_writel(v, addr);
-+ }
-+}
-+
-+static bool e24_cacheable(struct e24_device *e24_dat, unsigned long pfn,
-+ unsigned long n_pages)
-+{
-+ if (e24_dat->hw_ops->cacheable) {
-+ return e24_dat->hw_ops->cacheable(e24_dat->hw_arg, pfn, n_pages);
-+ } else {
-+ unsigned long i;
-+
-+ for (i = 0; i < n_pages; ++i)
-+ if (!pfn_valid(pfn + i))
-+ return false;
-+ return true;
-+ }
-+}
-+
-+static int e24_compare_address_sort(const void *a, const void *b)
-+{
-+ const struct e24_address_map_entry *pa = a;
-+ const struct e24_address_map_entry *pb = b;
-+
-+ if (pa->src_addr < pb->src_addr &&
-+ pb->src_addr - pa->src_addr >= pa->size)
-+ return -1;
-+ if (pa->src_addr > pb->src_addr &&
-+ pa->src_addr - pb->src_addr >= pb->size)
-+ return 1;
-+
-+ return 0;
-+}
-+
-+static int e24_compare_address_search(const void *a, const void *b)
-+{
-+ const phys_addr_t *pa = a;
-+
-+ return e24_compare_address(*pa, b);
-+}
-+
-+struct e24_address_map_entry *
-+e24_get_address_mapping(const struct e24_address_map *map, phys_addr_t addr)
-+{
-+ return bsearch(&addr, map->entry, map->n, sizeof(*map->entry),
-+ e24_compare_address_search);
-+}
-+
-+u32 e24_translate_to_dsp(const struct e24_address_map *map, phys_addr_t addr)
-+{
-+#ifdef E24_MEM_MAP
-+ return addr;
-+#else
-+ struct e24_address_map_entry *entry = e24_get_address_mapping(map, addr);
-+
-+ if (!entry)
-+ return E24_NO_TRANSLATION;
-+ return entry->dst_addr + addr - entry->src_addr;
-+#endif
-+}
-+
-+static int e24_dma_direction(unsigned int flags)
-+{
-+ static const enum dma_data_direction e24_dma_direction[] = {
-+ [0] = DMA_NONE,
-+ [E24_FLAG_READ] = DMA_TO_DEVICE,
-+ [E24_FLAG_WRITE] = DMA_FROM_DEVICE,
-+ [E24_FLAG_READ_WRITE] = DMA_BIDIRECTIONAL,
-+ };
-+ return e24_dma_direction[flags & E24_FLAG_READ_WRITE];
-+}
-+
-+static void e24_dma_sync_for_cpu(struct e24_device *e24_dat,
-+ unsigned long virt,
-+ phys_addr_t phys,
-+ unsigned long size,
-+ unsigned long flags)
-+{
-+ if (e24_dat->hw_ops->dma_sync_for_cpu)
-+ e24_dat->hw_ops->dma_sync_for_cpu(e24_dat->hw_arg,
-+ (void *)virt, phys, size,
-+ flags);
-+ else
-+ dma_sync_single_for_cpu(e24_dat->dev, phys_to_dma(e24_dat->dev, phys), size,
-+ e24_dma_direction(flags));
-+}
-+
-+static void starfive_mbox_receive_message(struct mbox_client *client, void *message)
-+{
-+ struct e24_device *e24_dat = dev_get_drvdata(client->dev);
-+
-+ complete(&e24_dat->tx_channel->tx_complete);
-+}
-+
-+static struct mbox_chan *
-+starfive_mbox_request_channel(struct device *dev, const char *name)
-+{
-+ struct mbox_client *client;
-+ struct mbox_chan *channel;
-+
-+ client = devm_kzalloc(dev, sizeof(*client), GFP_KERNEL);
-+ if (!client)
-+ return ERR_PTR(-ENOMEM);
-+
-+ client->dev = dev;
-+ client->rx_callback = starfive_mbox_receive_message;
-+ client->tx_prepare = NULL;
-+ client->tx_done = NULL;
-+ client->tx_block = true;
-+ client->knows_txdone = false;
-+ client->tx_tout = 3000;
-+
-+ channel = mbox_request_channel_byname(client, name);
-+ if (IS_ERR(channel)) {
-+ dev_warn(dev, "Failed to request %s channel\n", name);
-+ return NULL;
-+ }
-+
-+ return channel;
-+}
-+
-+static void e24_vm_open(struct vm_area_struct *vma)
-+{
-+ struct e24_allocation *cur = vma->vm_private_data;
-+
-+ atomic_inc(&cur->ref);
-+}
-+
-+static void e24_vm_close(struct vm_area_struct *vma)
-+{
-+ e24_allocation_put(vma->vm_private_data);
-+}
-+
-+static const struct vm_operations_struct e24_vm_ops = {
-+ .open = e24_vm_open,
-+ .close = e24_vm_close,
-+};
-+
-+static long e24_synchronize(struct e24_device *dev)
-+{
-+
-+ struct e24_comm *queue = dev->queue;
-+ struct e24_dsp_cmd __iomem *cmd = queue->comm;
-+ u32 flags;
-+ unsigned long deadline = jiffies + 10 * HZ;
-+
-+ do {
-+ flags = __raw_readl(&cmd->flags);
-+ /* memory barrier */
-+ rmb();
-+ if (flags == 0x104)
-+ return 0;
-+
-+ schedule();
-+ } while (time_before(jiffies, deadline));
-+
-+ return -1;
-+}
-+
-+static int e24_open(struct inode *inode, struct file *filp)
-+{
-+ struct e24_device *e24_dev = container_of(filp->private_data,
-+ struct e24_device, miscdev);
-+ int rc = 0;
-+
-+ rc = pm_runtime_get_sync(e24_dev->dev);
-+ if (rc < 0)
-+ return rc;
-+
-+ spin_lock_init(&e24_dev->busy_list_lock);
-+ filp->private_data = e24_dev;
-+ mdelay(1);
-+
-+ return 0;
-+}
-+
-+int e24_release(struct inode *inode, struct file *filp)
-+{
-+ struct e24_device *e24_dev = (struct e24_device *)filp->private_data;
-+ int rc = 0;
-+
-+ rc = pm_runtime_put_sync(e24_dev->dev);
-+ if (rc < 0)
-+ return rc;
-+
-+ return 0;
-+}
-+
-+static ssize_t mbox_e24_message_write(struct file *filp,
-+ const char __user *userbuf,
-+ size_t count, loff_t *ppos)
-+{
-+ struct e24_device *edev = filp->private_data;
-+ void *data;
-+ int ret;
-+
-+ if (!edev->tx_channel) {
-+ dev_err(edev->dev, "Channel cannot do Tx\n");
-+ return -EINVAL;
-+ }
-+
-+ if (count > EMBOX_MAX_MSG_LEN) {
-+ dev_err(edev->dev,
-+ "Message length %zd greater than max allowed %d\n",
-+ count, EMBOX_MAX_MSG_LEN);
-+ return -EINVAL;
-+ }
-+
-+ edev->message = kzalloc(EMBOX_MAX_MSG_LEN, GFP_KERNEL);
-+ if (!edev->message)
-+ return -ENOMEM;
-+
-+ ret = copy_from_user(edev->message, userbuf, count);
-+ if (ret) {
-+ ret = -EFAULT;
-+ goto out;
-+ }
-+
-+ print_hex_dump_bytes("Client: Sending: Message: ", DUMP_PREFIX_ADDRESS,
-+ edev->message, EMBOX_MAX_MSG_LEN);
-+ data = edev->message;
-+ pr_debug("%s:%d, %d\n", __func__, __LINE__, *((int *)data));
-+ ret = mbox_send_message(edev->tx_channel, data);
-+
-+ if (ret < 0 || !edev->tx_channel->active_req)
-+ dev_err(edev->dev, "Failed to send message via mailbox:%d\n", ret);
-+
-+out:
-+ kfree(edev->message);
-+ edev->tx_channel->active_req = NULL;
-+
-+ return ret < 0 ? ret : count;
-+}
-+
-+static long _e24_copy_user_phys(struct e24_device *edev,
-+ unsigned long vaddr, unsigned long size,
-+ phys_addr_t paddr, unsigned long flags,
-+ bool to_phys)
-+{
-+ void __iomem *p = ioremap(paddr, size);
-+ unsigned long rc;
-+
-+ if (!p) {
-+ dev_err(edev->dev,
-+ "couldn't ioremap %pap x 0x%08x\n",
-+ &paddr, (u32)size);
-+ return -EINVAL;
-+ }
-+ if (to_phys)
-+ rc = raw_copy_from_user(__io_virt(p),
-+ (void __user *)vaddr, size);
-+ else
-+ rc = copy_to_user((void __user *)vaddr,
-+ __io_virt(p), size);
-+ iounmap(p);
-+ if (rc)
-+ return -EFAULT;
-+ return 0;
-+}
-+
-+static long e24_copy_user_to_phys(struct e24_device *edev,
-+ unsigned long vaddr, unsigned long size,
-+ phys_addr_t paddr, unsigned long flags)
-+{
-+ return _e24_copy_user_phys(edev, vaddr, size, paddr, flags, true);
-+}
-+
-+static long e24_copy_user_from_phys(struct e24_device *edev,
-+ unsigned long vaddr, unsigned long size,
-+ phys_addr_t paddr, unsigned long flags)
-+{
-+ return _e24_copy_user_phys(edev, vaddr, size, paddr, flags, false);
-+}
-+
-+static long e24_copy_virt_to_phys(struct e24_device *edev,
-+ unsigned long flags,
-+ unsigned long vaddr, unsigned long size,
-+ phys_addr_t *paddr,
-+ struct e24_alien_mapping *mapping)
-+{
-+ phys_addr_t phys;
-+ unsigned long align = clamp(vaddr & -vaddr, 16ul, PAGE_SIZE);
-+ unsigned long offset = vaddr & (align - 1);
-+ struct e24_allocation *allocation;
-+ long rc;
-+
-+ rc = e24_allocate(edev->pool,
-+ size + align, align, &allocation);
-+ if (rc < 0)
-+ return rc;
-+
-+ phys = (allocation->start & -align) | offset;
-+ if (phys < allocation->start)
-+ phys += align;
-+
-+ if (flags & E24_FLAG_READ) {
-+ if (e24_copy_user_to_phys(edev, vaddr,
-+ size, phys, flags)) {
-+ e24_allocation_put(allocation);
-+ return -EFAULT;
-+ }
-+ }
-+
-+ *paddr = phys;
-+ *mapping = (struct e24_alien_mapping){
-+ .vaddr = vaddr,
-+ .size = size,
-+ .paddr = *paddr,
-+ .allocation = allocation,
-+ .type = ALIEN_COPY,
-+ };
-+ pr_debug("%s: copying to pa: %pap\n", __func__, paddr);
-+
-+ return 0;
-+}
-+
-+static long e24_writeback_alien_mapping(struct e24_device *edev,
-+ struct e24_alien_mapping *alien_mapping,
-+ unsigned long flags)
-+{
-+ struct page *page;
-+ size_t nr_pages;
-+ size_t i;
-+ long ret = 0;
-+
-+ switch (alien_mapping->type) {
-+ case ALIEN_GUP:
-+ e24_dma_sync_for_cpu(edev,
-+ alien_mapping->vaddr,
-+ alien_mapping->paddr,
-+ alien_mapping->size,
-+ flags);
-+ pr_debug("%s: dirtying alien GUP @va = %p, pa = %pap\n",
-+ __func__, (void __user *)alien_mapping->vaddr,
-+ &alien_mapping->paddr);
-+ page = pfn_to_page(__phys_to_pfn(alien_mapping->paddr));
-+ nr_pages = PFN_UP(alien_mapping->vaddr + alien_mapping->size) -
-+ PFN_DOWN(alien_mapping->vaddr);
-+ for (i = 0; i < nr_pages; ++i)
-+ SetPageDirty(page + i);
-+ break;
-+
-+ case ALIEN_COPY:
-+ pr_debug("%s: synchronizing alien copy @pa = %pap back to %p\n",
-+ __func__, &alien_mapping->paddr,
-+ (void __user *)alien_mapping->vaddr);
-+ if (e24_copy_user_from_phys(edev,
-+ alien_mapping->vaddr,
-+ alien_mapping->size,
-+ alien_mapping->paddr,
-+ flags))
-+ ret = -EINVAL;
-+ break;
-+
-+ default:
-+ break;
-+ }
-+ return ret;
-+}
-+
-+static bool vma_needs_cache_ops(struct vm_area_struct *vma)
-+{
-+ pgprot_t prot = vma->vm_page_prot;
-+
-+ return pgprot_val(prot) != pgprot_val(pgprot_noncached(prot)) &&
-+ pgprot_val(prot) != pgprot_val(pgprot_writecombine(prot));
-+}
-+
-+static void e24_alien_mapping_destroy(struct e24_alien_mapping *alien_mapping)
-+{
-+ switch (alien_mapping->type) {
-+ case ALIEN_COPY:
-+ e24_allocation_put(alien_mapping->allocation);
-+ break;
-+ default:
-+ break;
-+ }
-+}
-+
-+static long __e24_unshare_block(struct file *filp, struct e24_mapping *mapping,
-+ unsigned long flags)
-+{
-+ long ret = 0;
-+ struct e24_device *edev = filp->private_data;
-+
-+ switch (mapping->type & ~E24_MAPPING_KERNEL) {
-+ case E24_MAPPING_NATIVE:
-+ if (flags & E24_FLAG_WRITE) {
-+ e24_dma_sync_for_cpu(edev,
-+ mapping->native.vaddr,
-+ mapping->native.m_allocation->start,
-+ mapping->native.m_allocation->size,
-+ flags);
-+ }
-+ e24_allocation_put(mapping->native.m_allocation);
-+ break;
-+
-+ case E24_MAPPING_ALIEN:
-+ if (flags & E24_FLAG_WRITE) {
-+ ret = e24_writeback_alien_mapping(edev,
-+ &mapping->alien_mapping,
-+ flags);
-+ }
-+ e24_alien_mapping_destroy(&mapping->alien_mapping);
-+ break;
-+
-+ case E24_MAPPING_KERNEL:
-+ break;
-+
-+ default:
-+ break;
-+ }
-+
-+ mapping->type = E24_MAPPING_NONE;
-+
-+ return ret;
-+}
-+
-+static long __e24_share_block(struct file *filp,
-+ unsigned long virt, unsigned long size,
-+ unsigned long flags, phys_addr_t *paddr,
-+ struct e24_mapping *mapping)
-+{
-+ phys_addr_t phys = ~0ul;
-+ struct e24_device *edev = filp->private_data;
-+ struct mm_struct *mm = current->mm;
-+ struct vm_area_struct *vma = find_vma(mm, virt);
-+ bool do_cache = true;
-+ long rc = -EINVAL;
-+
-+ if (!vma) {
-+ pr_debug("%s: no vma for vaddr/size = 0x%08lx/0x%08lx\n",
-+ __func__, virt, size);
-+ return -EINVAL;
-+ }
-+
-+ if (virt + size < virt || vma->vm_start > virt)
-+ return -EINVAL;
-+
-+ if (vma && (vma->vm_file == filp)) {
-+ struct e24_device *vm_file = vma->vm_file->private_data;
-+ struct e24_allocation *e24_user_allocation = vma->vm_private_data;
-+
-+ phys = vm_file->shared_mem + (vma->vm_pgoff << PAGE_SHIFT) +
-+ virt - vma->vm_start;
-+ pr_debug("%s: E24 allocation at 0x%08lx, paddr: %pap\n",
-+ __func__, virt, &phys);
-+
-+ rc = 0;
-+ mapping->type = E24_MAPPING_NATIVE;
-+ mapping->native.m_allocation = e24_user_allocation;
-+ mapping->native.vaddr = virt;
-+ atomic_inc(&e24_user_allocation->ref);
-+ do_cache = vma_needs_cache_ops(vma);
-+ }
-+ if (rc < 0) {
-+ struct e24_alien_mapping *alien_mapping =
-+ &mapping->alien_mapping;
-+
-+ /* Otherwise this is alien allocation. */
-+ pr_debug("%s: non-E24 allocation at 0x%08lx\n",
-+ __func__, virt);
-+
-+ rc = e24_copy_virt_to_phys(edev, flags,
-+ virt, size, &phys,
-+ alien_mapping);
-+
-+ if (rc < 0) {
-+ pr_debug("%s: couldn't map virt to phys\n",
-+ __func__);
-+ return -EINVAL;
-+ }
-+
-+ phys = alien_mapping->paddr +
-+ virt - alien_mapping->vaddr;
-+
-+ mapping->type = E24_MAPPING_ALIEN;
-+ }
-+
-+ *paddr = phys;
-+ pr_debug("%s: mapping = %p, mapping->type = %d\n",
-+ __func__, mapping, mapping->type);
-+
-+ return 0;
-+}
-+
-+
-+static void e24_unmap_request_nowb(struct file *filp, struct e24_ioctl_request *rq)
-+{
-+ if (rq->ioctl_data.in_data_size > E24_DSP_CMD_INLINE_DATA_SIZE)
-+ __e24_unshare_block(filp, &rq->in_data_mapping, 0);
-+ if (rq->ioctl_data.out_data_size > E24_DSP_CMD_INLINE_DATA_SIZE)
-+ __e24_unshare_block(filp, &rq->out_data_mapping, 0);
-+}
-+
-+static long e24_unmap_request(struct file *filp, struct e24_ioctl_request *rq)
-+{
-+ long ret = 0;
-+
-+ if (rq->ioctl_data.in_data_size > E24_DSP_CMD_INLINE_DATA_SIZE)
-+ __e24_unshare_block(filp, &rq->in_data_mapping, E24_FLAG_READ);
-+
-+ if (rq->ioctl_data.out_data_size > E24_DSP_CMD_INLINE_DATA_SIZE) {
-+ ret = __e24_unshare_block(filp, &rq->out_data_mapping,
-+ E24_FLAG_WRITE);
-+ if (ret < 0)
-+ pr_debug("%s: out_data could not be unshared\n", __func__);
-+
-+ } else {
-+ if (copy_to_user((void __user *)(unsigned long)rq->ioctl_data.out_data_addr,
-+ rq->out_data,
-+ rq->ioctl_data.out_data_size)) {
-+ pr_debug("%s: out_data could not be copied\n", __func__);
-+ ret = -EFAULT;
-+ }
-+ }
-+
-+ return ret;
-+}
-+
-+static bool e24_cmd_complete(struct e24_comm *share_com)
-+{
-+ struct e24_dsp_cmd __iomem *cmd = share_com->comm;
-+ u32 flags = __raw_readl(&cmd->flags);
-+
-+ rmb();
-+ return (flags & (E24_CMD_FLAG_REQUEST_VALID |
-+ E24_CMD_FLAG_RESPONSE_VALID)) ==
-+ (E24_CMD_FLAG_REQUEST_VALID |
-+ E24_CMD_FLAG_RESPONSE_VALID);
-+}
-+
-+static long e24_complete_poll(struct e24_device *edev, struct e24_comm *comm,
-+ bool (*cmd_complete)(struct e24_comm *p), struct e24_ioctl_request *rq)
-+{
-+ unsigned long deadline = jiffies + firmware_command_timeout * HZ;
-+
-+ do {
-+ if (cmd_complete(comm)) {
-+ pr_debug("%s: poll complete.\n", __func__);
-+ return 0;
-+ }
-+ schedule();
-+ } while (time_before(jiffies, deadline));
-+
-+ pr_debug("%s: poll complete cmd timeout.\n", __func__);
-+
-+ return -EBUSY;
-+}
-+
-+static long e24_map_request(struct file *filp, struct e24_ioctl_request *rq, struct mm_struct *mm)
-+{
-+ long ret = 0;
-+
-+ mmap_read_lock(mm);
-+ if (rq->ioctl_data.in_data_size > E24_DSP_CMD_INLINE_DATA_SIZE) {
-+ ret = __e24_share_block(filp, rq->ioctl_data.in_data_addr,
-+ rq->ioctl_data.in_data_size,
-+ E24_FLAG_READ, &rq->in_data_phys,
-+ &rq->in_data_mapping);
-+ if (ret < 0) {
-+ pr_debug("%s: in_data could not be shared\n", __func__);
-+ goto share_err;
-+ }
-+ } else {
-+ if (copy_from_user(rq->in_data,
-+ (void __user *)(unsigned long)rq->ioctl_data.in_data_addr,
-+ rq->ioctl_data.in_data_size)) {
-+ pr_debug("%s: in_data could not be copied\n",
-+ __func__);
-+ ret = -EFAULT;
-+ goto share_err;
-+ }
-+ }
-+
-+ if (rq->ioctl_data.out_data_size > E24_DSP_CMD_INLINE_DATA_SIZE) {
-+ ret = __e24_share_block(filp, rq->ioctl_data.out_data_addr,
-+ rq->ioctl_data.out_data_size,
-+ E24_FLAG_WRITE, &rq->out_data_phys,
-+ &rq->out_data_mapping);
-+ if (ret < 0) {
-+ pr_debug("%s: out_data could not be shared\n",
-+ __func__);
-+ goto share_err;
-+ }
-+ }
-+share_err:
-+ mmap_read_unlock(mm);
-+ if (ret < 0)
-+ e24_unmap_request_nowb(filp, rq);
-+ return ret;
-+
-+}
-+
-+static void e24_fill_hw_request(struct e24_dsp_cmd __iomem *cmd,
-+ struct e24_ioctl_request *rq,
-+ const struct e24_address_map *map)
-+{
-+ __raw_writel(rq->ioctl_data.in_data_size, &cmd->in_data_size);
-+ __raw_writel(rq->ioctl_data.out_data_size, &cmd->out_data_size);
-+
-+ if (rq->ioctl_data.in_data_size > E24_DSP_CMD_INLINE_DATA_SIZE)
-+ __raw_writel(e24_translate_to_dsp(map, rq->in_data_phys),
-+ &cmd->in_data_addr);
-+ else
-+ e24_comm_write(&cmd->in_data, rq->in_data,
-+ rq->ioctl_data.in_data_size);
-+
-+ if (rq->ioctl_data.out_data_size > E24_DSP_CMD_INLINE_DATA_SIZE)
-+ __raw_writel(e24_translate_to_dsp(map, rq->out_data_phys),
-+ &cmd->out_data_addr);
-+
-+ wmb();
-+ /* update flags */
-+ __raw_writel(rq->ioctl_data.flags, &cmd->flags);
-+}
-+
-+static long e24_complete_hw_request(struct e24_dsp_cmd __iomem *cmd,
-+ struct e24_ioctl_request *rq)
-+{
-+ u32 flags = __raw_readl(&cmd->flags);
-+
-+ if (rq->ioctl_data.out_data_size <= E24_DSP_CMD_INLINE_DATA_SIZE)
-+ e24_comm_read(&cmd->out_data, rq->out_data,
-+ rq->ioctl_data.out_data_size);
-+
-+ __raw_writel(0, &cmd->flags);
-+
-+ return (flags & E24_QUEUE_VALID_FLAGS) ? -ENXIO : 0;
-+}
-+
-+static long e24_ioctl_submit_task(struct file *filp,
-+ struct e24_ioctl_user __user *msg)
-+{
-+ struct e24_device *edev = filp->private_data;
-+ struct e24_comm *queue = edev->queue;
-+ struct e24_ioctl_request rq_data, *vrq = &rq_data;
-+ void *data = &edev->mbox_data;
-+ int ret = -ENOMEM;
-+ int irq_mode = edev->irq_mode;
-+
-+ if (copy_from_user(&vrq->ioctl_data, msg, sizeof(*msg)))
-+ return -EFAULT;
-+
-+ if (vrq->ioctl_data.flags & ~E24_QUEUE_VALID_FLAGS) {
-+ dev_dbg(edev->dev, "%s: invalid flags 0x%08x\n",
-+ __func__, vrq->ioctl_data.flags);
-+ return -EINVAL;
-+ }
-+
-+ ret = e24_map_request(filp, vrq, current->mm);
-+ if (ret < 0)
-+ return ret;
-+
-+ mutex_lock(&queue->lock);
-+ e24_fill_hw_request(queue->comm, vrq, &edev->address_map);
-+
-+ if (irq_mode) {
-+ ret = mbox_send_message(edev->tx_channel, data);
-+ mbox_chan_txdone(edev->tx_channel, ret);
-+ } else {
-+ ret = e24_complete_poll(edev, queue, e24_cmd_complete, vrq);
-+ }
-+
-+ ret = e24_complete_hw_request(queue->comm, vrq);
-+ mutex_unlock(&queue->lock);
-+
-+ if (ret == 0)
-+ ret = e24_unmap_request(filp, vrq);
-+
-+ return ret;
-+}
-+
-+static long e24_ioctl_get_channel(struct file *filp,
-+ void __user *msg)
-+{
-+ struct e24_device *edev = filp->private_data;
-+
-+ if (edev->tx_channel == NULL)
-+ edev->tx_channel = starfive_mbox_request_channel(edev->dev, "tx");
-+ if (edev->rx_channel == NULL)
-+ edev->rx_channel = starfive_mbox_request_channel(edev->dev, "rx");
-+
-+ return 0;
-+}
-+
-+static long e24_ioctl_free_channel(struct file *filp,
-+ void __user *msg)
-+{
-+ struct e24_device *edev = filp->private_data;
-+
-+ if (edev->rx_channel)
-+ mbox_free_channel(edev->rx_channel);
-+ if (edev->tx_channel)
-+ mbox_free_channel(edev->tx_channel);
-+
-+ edev->rx_channel = NULL;
-+ edev->tx_channel = NULL;
-+ return 0;
-+}
-+
-+static void e24_allocation_queue(struct e24_device *edev,
-+ struct e24_allocation *e24_pool_allocation)
-+{
-+ spin_lock(&edev->busy_list_lock);
-+
-+ e24_pool_allocation->next = edev->busy_list;
-+ edev->busy_list = e24_pool_allocation;
-+
-+ spin_unlock(&edev->busy_list_lock);
-+}
-+
-+static struct e24_allocation *e24_allocation_dequeue(struct e24_device *edev,
-+ phys_addr_t paddr, u32 size)
-+{
-+ struct e24_allocation **pcur;
-+ struct e24_allocation *cur;
-+
-+ spin_lock(&edev->busy_list_lock);
-+
-+ for (pcur = &edev->busy_list; (cur = *pcur); pcur = &((*pcur)->next)) {
-+ pr_debug("%s: %pap / %pap x %d\n", __func__, &paddr, &cur->start, cur->size);
-+ if (paddr >= cur->start && paddr + size - cur->start <= cur->size) {
-+ *pcur = cur->next;
-+ break;
-+ }
-+ }
-+
-+ spin_unlock(&edev->busy_list_lock);
-+ return cur;
-+}
-+
-+static int e24_mmap(struct file *filp, struct vm_area_struct *vma)
-+{
-+ int err;
-+ struct e24_device *edev = filp->private_data;
-+ unsigned long pfn = vma->vm_pgoff + PFN_DOWN(edev->shared_mem);
-+ struct e24_allocation *e24_user_allocation;
-+
-+ e24_user_allocation = e24_allocation_dequeue(filp->private_data,
-+ pfn << PAGE_SHIFT,
-+ vma->vm_end - vma->vm_start);
-+ if (e24_user_allocation) {
-+ pgprot_t prot = vma->vm_page_prot;
-+
-+ if (!e24_cacheable(edev, pfn,
-+ PFN_DOWN(vma->vm_end - vma->vm_start))) {
-+ prot = pgprot_writecombine(prot);
-+ vma->vm_page_prot = prot;
-+ }
-+
-+ err = remap_pfn_range(vma, vma->vm_start, pfn,
-+ vma->vm_end - vma->vm_start,
-+ prot);
-+
-+ vma->vm_private_data = e24_user_allocation;
-+ vma->vm_ops = &e24_vm_ops;
-+ } else {
-+ err = -EINVAL;
-+ }
-+
-+ return err;
-+}
-+
-+static long e24_ioctl_free(struct file *filp,
-+ struct e24_ioctl_alloc __user *p)
-+{
-+ struct mm_struct *mm = current->mm;
-+ struct e24_ioctl_alloc user_ioctl_alloc;
-+ struct vm_area_struct *vma;
-+ unsigned long start;
-+
-+ if (copy_from_user(&user_ioctl_alloc, p, sizeof(*p)))
-+ return -EFAULT;
-+
-+ start = user_ioctl_alloc.addr;
-+ pr_debug("%s: virt_addr = 0x%08lx\n", __func__, start);
-+
-+ mmap_read_lock(mm);
-+ vma = find_vma(mm, start);
-+
-+ if (vma && vma->vm_file == filp &&
-+ vma->vm_start <= start && start < vma->vm_end) {
-+ size_t size;
-+
-+ start = vma->vm_start;
-+ size = vma->vm_end - vma->vm_start;
-+ mmap_read_unlock(mm);
-+ pr_debug("%s: 0x%lx x %zu\n", __func__, start, size);
-+ return vm_munmap(start, size);
-+ }
-+ pr_debug("%s: no vma/bad vma for vaddr = 0x%08lx\n", __func__, start);
-+ mmap_read_unlock(mm);
-+
-+ return -EINVAL;
-+}
-+
-+static long e24_ioctl_alloc(struct file *filp,
-+ struct e24_ioctl_alloc __user *p)
-+{
-+ struct e24_device *edev = filp->private_data;
-+ struct e24_allocation *e24_pool_allocation;
-+ unsigned long vaddr;
-+ struct e24_ioctl_alloc user_ioctl_alloc;
-+ long err;
-+
-+ if (copy_from_user(&user_ioctl_alloc, p, sizeof(*p)))
-+ return -EFAULT;
-+
-+ pr_debug("%s: size = %d, align = %x\n", __func__,
-+ user_ioctl_alloc.size, user_ioctl_alloc.align);
-+
-+ err = e24_allocate(edev->pool,
-+ user_ioctl_alloc.size,
-+ user_ioctl_alloc.align,
-+ &e24_pool_allocation);
-+ if (err)
-+ return err;
-+
-+ e24_allocation_queue(edev, e24_pool_allocation);
-+
-+ vaddr = vm_mmap(filp, 0, e24_pool_allocation->size,
-+ PROT_READ | PROT_WRITE, MAP_SHARED,
-+ e24_allocation_offset(e24_pool_allocation));
-+
-+ user_ioctl_alloc.addr = vaddr;
-+
-+ if (copy_to_user(p, &user_ioctl_alloc, sizeof(*p))) {
-+ vm_munmap(vaddr, user_ioctl_alloc.size);
-+ return -EFAULT;
-+ }
-+ return 0;
-+}
-+
-+static long e24_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-+{
-+ long retval;
-+
-+ switch (cmd) {
-+ case E24_IOCTL_SEND:
-+ retval = e24_ioctl_submit_task(filp, (struct e24_ioctl_user *)arg);
-+ break;
-+ case E24_IOCTL_GET_CHANNEL:
-+ retval = e24_ioctl_get_channel(filp, NULL);
-+ break;
-+ case E24_IOCTL_FREE_CHANNEL:
-+ retval = e24_ioctl_free_channel(filp, NULL);
-+ break;
-+ case E24_IOCTL_ALLOC:
-+ retval = e24_ioctl_alloc(filp, (struct e24_ioctl_alloc __user *)arg);
-+ break;
-+ case E24_IOCTL_FREE:
-+ retval = e24_ioctl_free(filp, (struct e24_ioctl_alloc __user *)arg);
-+ break;
-+ default:
-+ retval = -EINVAL;
-+ break;
-+ }
-+ return retval;
-+}
-+
-+static const struct file_operations e24_fops = {
-+ .owner = THIS_MODULE,
-+ .unlocked_ioctl = e24_ioctl,
-+#ifdef CONFIG_COMPAT
-+ .compat_ioctl = e24_ioctl,
-+#endif
-+ .open = e24_open,
-+ .release = e24_release,
-+ .write = mbox_e24_message_write,
-+ .mmap = e24_mmap,
-+};
-+
-+void mailbox_task(struct platform_device *pdev)
-+{
-+ struct e24_device *e24_dev = platform_get_drvdata(pdev);
-+
-+ e24_dev->tx_channel = starfive_mbox_request_channel(e24_dev->dev, "tx");
-+ e24_dev->rx_channel = starfive_mbox_request_channel(e24_dev->dev, "rx");
-+ pr_debug("%s:%d.%#llx\n", __func__, __LINE__, (u64)e24_dev->rx_channel);
-+}
-+
-+static long e24_init_mem_pool(struct platform_device *pdev, struct e24_device *devs)
-+{
-+ struct resource *mem;
-+
-+ mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ecmd");
-+ if (!mem)
-+ return -ENODEV;
-+
-+ devs->comm_phys = mem->start;
-+ devs->comm = devm_ioremap(&pdev->dev, mem->start, mem->end - mem->start);
-+ mem = platform_get_resource_byname(pdev, IORESOURCE_MEM, "espace");
-+ if (!mem)
-+ return -ENODEV;
-+
-+ devs->shared_mem = mem->start;
-+ devs->shared_size = resource_size(mem);
-+ pr_debug("%s:%d.%llx,%llx\n", __func__, __LINE__, devs->comm_phys, devs->shared_mem);
-+ return e24_init_private_pool(&devs->pool, devs->shared_mem, devs->shared_size);
-+}
-+
-+static int e24_init_address_map(struct device *dev,
-+ struct e24_address_map *map)
-+{
-+#if IS_ENABLED(CONFIG_OF)
-+ struct device_node *pnode = dev->of_node;
-+ struct device_node *node;
-+ int rlen, off;
-+ const __be32 *ranges = of_get_property(pnode, "ranges", &rlen);
-+ int na, pna, ns;
-+ int i;
-+
-+ if (!ranges) {
-+ dev_dbg(dev, "%s: no 'ranges' property in the device tree, no translation at that level\n",
-+ __func__);
-+ goto empty;
-+ }
-+
-+ node = of_get_next_child(pnode, NULL);
-+ if (!node) {
-+ dev_warn(dev, "%s: no child node found in the device tree, no translation at that level\n",
-+ __func__);
-+ goto empty;
-+ }
-+
-+ na = of_n_addr_cells(node);
-+ ns = of_n_size_cells(node);
-+ pna = of_n_addr_cells(pnode);
-+
-+ rlen /= 4;
-+ map->n = rlen / (na + pna + ns);
-+ map->entry = kmalloc_array(map->n, sizeof(*map->entry), GFP_KERNEL);
-+ if (!map->entry)
-+ return -ENOMEM;
-+
-+ dev_dbg(dev,
-+ "%s: na = %d, pna = %d, ns = %d, rlen = %d cells, n = %d\n",
-+ __func__, na, pna, ns, rlen, map->n);
-+
-+ for (off = 0, i = 0; off < rlen; off += na + pna + ns, ++i) {
-+ map->entry[i].src_addr = of_translate_address(node,
-+ ranges + off);
-+ map->entry[i].dst_addr = of_read_number(ranges + off, na);
-+ map->entry[i].size = of_read_number(ranges + off + na + pna, ns);
-+ dev_dbg(dev,
-+ " src_addr = 0x%llx, dst_addr = 0x%lx, size = 0x%lx\n",
-+ (unsigned long long)map->entry[i].src_addr,
-+ (unsigned long)map->entry[i].dst_addr,
-+ (unsigned long)map->entry[i].size);
-+ }
-+ sort(map->entry, map->n, sizeof(*map->entry), e24_compare_address_sort, NULL);
-+
-+ of_node_put(node);
-+ return 0;
-+
-+empty:
-+#endif
-+ map->n = 1;
-+ map->entry = kmalloc(sizeof(*map->entry), GFP_KERNEL);
-+ map->entry->src_addr = 0;
-+ map->entry->dst_addr = 0;
-+ map->entry->size = ~0u;
-+ return -ENOMEM;
-+}
-+
-+typedef long e24_init_function(struct platform_device *pdev);
-+
-+static inline void e24_init(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->init)
-+ e24_hw->hw_ops->init(e24_hw->hw_arg);
-+}
-+
-+static inline void e24_release_e24(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->reset)
-+ e24_hw->hw_ops->release(e24_hw->hw_arg);
-+}
-+
-+static inline void e24_halt_e24(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->halt)
-+ e24_hw->hw_ops->halt(e24_hw->hw_arg);
-+}
-+
-+static inline int e24_enable_e24(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->enable)
-+ return e24_hw->hw_ops->enable(e24_hw->hw_arg);
-+ else
-+ return -EINVAL;
-+}
-+
-+static inline void e24_reset_e24(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->reset)
-+ e24_hw->hw_ops->reset(e24_hw->hw_arg);
-+}
-+
-+static inline void e24_disable_e24(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->disable)
-+ e24_hw->hw_ops->disable(e24_hw->hw_arg);
-+}
-+
-+static inline void e24_sendirq_e24(struct e24_device *e24_hw)
-+{
-+ if (e24_hw->hw_ops->send_irq)
-+ e24_hw->hw_ops->send_irq(e24_hw->hw_arg);
-+}
-+
-+irqreturn_t e24_irq_handler(int irq, struct e24_device *e24_hw)
-+{
-+ dev_dbg(e24_hw->dev, "%s\n", __func__);
-+ complete(&e24_hw->completion);
-+
-+ return IRQ_HANDLED;
-+}
-+EXPORT_SYMBOL(e24_irq_handler);
-+
-+static phys_addr_t e24_translate_to_cpu(struct e24_device *mail, Elf32_Phdr *phdr)
-+{
-+ phys_addr_t res;
-+ __be32 addr = cpu_to_be32((u32)phdr->p_paddr);
-+ struct device_node *node =
-+ of_get_next_child(mail->dev->of_node, NULL);
-+
-+ if (!node)
-+ node = mail->dev->of_node;
-+
-+ res = of_translate_address(node, &addr);
-+
-+ if (node != mail->dev->of_node)
-+ of_node_put(node);
-+ return res;
-+}
-+
-+static int e24_load_segment_to_sysmem(struct e24_device *e24, Elf32_Phdr *phdr)
-+{
-+ phys_addr_t pa = e24_translate_to_cpu(e24, phdr);
-+ struct page *page = pfn_to_page(__phys_to_pfn(pa));
-+ size_t page_offs = pa & ~PAGE_MASK;
-+ size_t offs;
-+
-+ for (offs = 0; offs < phdr->p_memsz; ++page) {
-+ void *p = kmap(page);
-+ size_t sz;
-+
-+ if (!p)
-+ return -ENOMEM;
-+
-+ page_offs &= ~PAGE_MASK;
-+ sz = PAGE_SIZE - page_offs;
-+
-+ if (offs < phdr->p_filesz) {
-+ size_t copy_sz = sz;
-+
-+ if (phdr->p_filesz - offs < copy_sz)
-+ copy_sz = phdr->p_filesz - offs;
-+
-+ copy_sz = ALIGN(copy_sz, 4);
-+ memcpy(p + page_offs,
-+ (void *)e24->firmware->data +
-+ phdr->p_offset + offs,
-+ copy_sz);
-+ page_offs += copy_sz;
-+ offs += copy_sz;
-+ sz -= copy_sz;
-+ }
-+
-+ if (offs < phdr->p_memsz && sz) {
-+ if (phdr->p_memsz - offs < sz)
-+ sz = phdr->p_memsz - offs;
-+
-+ sz = ALIGN(sz, 4);
-+ memset(p + page_offs, 0, sz);
-+ page_offs += sz;
-+ offs += sz;
-+ }
-+ kunmap(page);
-+ }
-+ dma_sync_single_for_device(e24->dev, pa, phdr->p_memsz, DMA_TO_DEVICE);
-+ return 0;
-+}
-+
-+static int e24_load_segment_to_iomem(struct e24_device *e24, Elf32_Phdr *phdr)
-+{
-+ phys_addr_t pa = e24_translate_to_cpu(e24, phdr);
-+ void __iomem *p = ioremap(pa, phdr->p_memsz);
-+
-+ if (!p) {
-+ dev_err(e24->dev, "couldn't ioremap %pap x 0x%08x\n",
-+ &pa, (u32)phdr->p_memsz);
-+ return -EINVAL;
-+ }
-+ if (e24->hw_ops->memcpy_tohw)
-+ e24->hw_ops->memcpy_tohw(p, (void *)e24->firmware->data +
-+ phdr->p_offset, phdr->p_filesz);
-+ else
-+ memcpy_toio(p, (void *)e24->firmware->data + phdr->p_offset,
-+ ALIGN(phdr->p_filesz, 4));
-+
-+ if (e24->hw_ops->memset_hw)
-+ e24->hw_ops->memset_hw(p + phdr->p_filesz, 0,
-+ phdr->p_memsz - phdr->p_filesz);
-+ else
-+ memset_io(p + ALIGN(phdr->p_filesz, 4), 0,
-+ ALIGN(phdr->p_memsz - ALIGN(phdr->p_filesz, 4), 4));
-+
-+ iounmap(p);
-+ return 0;
-+}
-+
-+static int e24_load_firmware(struct e24_device *e24_dev)
-+{
-+ Elf32_Ehdr *ehdr = (Elf32_Ehdr *)e24_dev->firmware->data;
-+ u32 *dai = (u32 *)e24_dev->firmware->data;
-+ int i;
-+
-+ pr_debug("elf size:%ld,%x,%x\n", e24_dev->firmware->size, dai[0], dai[1]);
-+ if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
-+ dev_err(e24_dev->dev, "bad firmware ELF magic\n");
-+ return -EINVAL;
-+ }
-+
-+ if (ehdr->e_type != ET_EXEC) {
-+ dev_err(e24_dev->dev, "bad firmware ELF type\n");
-+ return -EINVAL;
-+ }
-+
-+ if (ehdr->e_machine != EM_RISCV) {
-+ dev_err(e24_dev->dev, "bad firmware ELF machine\n");
-+ return -EINVAL;
-+ }
-+
-+ if (ehdr->e_phoff >= e24_dev->firmware->size ||
-+ ehdr->e_phoff +
-+ ehdr->e_phentsize * ehdr->e_phnum > e24_dev->firmware->size) {
-+ dev_err(e24_dev->dev, "bad firmware ELF PHDR information\n");
-+ return -EINVAL;
-+ }
-+
-+ for (i = ehdr->e_phnum; i >= 0 ; i--) {
-+ Elf32_Phdr *phdr = (void *)e24_dev->firmware->data +
-+ ehdr->e_phoff + i * ehdr->e_phentsize;
-+ phys_addr_t pa;
-+ int rc;
-+
-+ /* Only load non-empty loadable segments, R/W/X */
-+ if (!(phdr->p_type == PT_LOAD &&
-+ (phdr->p_flags & (PF_X | PF_R | PF_W)) &&
-+ phdr->p_memsz > 0))
-+ continue;
-+
-+ if (phdr->p_offset >= e24_dev->firmware->size ||
-+ phdr->p_offset + phdr->p_filesz > e24_dev->firmware->size) {
-+ dev_err(e24_dev->dev, "bad firmware ELF program header entry %d\n", i);
-+ return -EINVAL;
-+ }
-+
-+ pa = e24_translate_to_cpu(e24_dev, phdr);
-+ if (pa == (phys_addr_t)OF_BAD_ADDR) {
-+ dev_err(e24_dev->dev,
-+ "device address 0x%08x could not be mapped to host physical address",
-+ (u32)phdr->p_paddr);
-+ return -EINVAL;
-+ }
-+ dev_dbg(e24_dev->dev, "loading segment %d (device 0x%08x) to physical %pap\n",
-+ i, (u32)phdr->p_paddr, &pa);
-+
-+ if (pfn_valid(__phys_to_pfn(pa)))
-+ rc = e24_load_segment_to_sysmem(e24_dev, phdr);
-+ else
-+ rc = e24_load_segment_to_iomem(e24_dev, phdr);
-+
-+ if (rc < 0)
-+ return rc;
-+ }
-+ return 0;
-+}
-+
-+static int e24_boot_firmware(struct device *dev)
-+{
-+ int ret;
-+ struct e24_device *e24_dev = dev_get_drvdata(dev);
-+
-+ if (e24_dev->firmware_name) {
-+ ret = request_firmware(&e24_dev->firmware, e24_dev->firmware_name, e24_dev->dev);
-+
-+ if (ret < 0)
-+ return ret;
-+
-+ ret = e24_load_firmware(e24_dev);
-+ if (ret < 0) {
-+ release_firmware(e24_dev->firmware);
-+ return ret;
-+ }
-+
-+ }
-+
-+ release_firmware(e24_dev->firmware);
-+ ret = e24_enable_e24(e24_dev);
-+ if (ret < 0)
-+ return ret;
-+
-+ e24_reset_e24(e24_dev);
-+ e24_release_e24(e24_dev);
-+ e24_synchronize(e24_dev);
-+
-+ return ret;
-+}
-+
-+int e24_runtime_suspend(struct device *dev)
-+{
-+ struct e24_device *e24_dev = dev_get_drvdata(dev);
-+
-+ e24_halt_e24(e24_dev);
-+ e24_disable_e24(e24_dev);
-+
-+ return 0;
-+}
-+
-+long e24_init_v0(struct platform_device *pdev)
-+{
-+ long ret = -EINVAL;
-+ int nodeid, i;
-+ struct e24_hw_arg *hw_arg;
-+ struct e24_device *e24_dev;
-+ char nodename[sizeof("eboot") + 2 * sizeof(int)];
-+
-+ e24_dev = devm_kzalloc(&pdev->dev, sizeof(*e24_dev), GFP_KERNEL);
-+ if (e24_dev == NULL) {
-+ ret = -ENOMEM;
-+ return ret;
-+ }
-+
-+ hw_arg = devm_kzalloc(&pdev->dev, sizeof(*hw_arg), GFP_KERNEL);
-+ if (hw_arg == NULL)
-+ return ret;
-+
-+ platform_set_drvdata(pdev, e24_dev);
-+ e24_dev->dev = &pdev->dev;
-+ e24_dev->hw_arg = hw_arg;
-+ e24_dev->hw_ops = e24_get_hw_ops();
-+ e24_dev->nodeid = -1;
-+ hw_arg->e24 = e24_dev;
-+
-+ ret = e24_init_mem_pool(pdev, e24_dev);
-+ if (ret < 0)
-+ goto err;
-+
-+ ret = e24_init_address_map(e24_dev->dev, &e24_dev->address_map);
-+ if (ret < 0)
-+ goto err_free_pool;
-+
-+ e24_dev->n_queues = 1;
-+ e24_dev->queue = devm_kmalloc(&pdev->dev,
-+ e24_dev->n_queues * sizeof(*e24_dev->queue),
-+ GFP_KERNEL);
-+ if (e24_dev->queue == NULL)
-+ goto err_free_map;
-+
-+ for (i = 0; i < e24_dev->n_queues; i++) {
-+ mutex_init(&e24_dev->queue[i].lock);
-+ e24_dev->queue[i].comm = e24_dev->comm + E24_CMD_STRIDE * i;
-+ }
-+
-+ ret = of_property_read_u32(pdev->dev.of_node, "irq-mode",
-+ &hw_arg->irq_mode);
-+ e24_dev->irq_mode = hw_arg->irq_mode;
-+ if (hw_arg->irq_mode == 0)
-+ dev_info(&pdev->dev, "using polling mode on the device side\n");
-+
-+ e24_dev->mbox_data = e24_translate_to_dsp(&e24_dev->address_map, e24_dev->comm_phys);
-+ ret = device_property_read_string(e24_dev->dev, "firmware-name",
-+ &e24_dev->firmware_name);
-+ if (ret == -EINVAL || ret == -ENODATA) {
-+ dev_dbg(e24_dev->dev,
-+ "no firmware-name property, not loading firmware");
-+ } else if (ret < 0) {
-+ dev_err(e24_dev->dev, "invalid firmware name (%ld)", ret);
-+ goto err_free_map;
-+ }
-+
-+ e24_init(e24_dev);
-+ pm_runtime_set_active(e24_dev->dev);
-+ pm_runtime_enable(e24_dev->dev);
-+ if (!pm_runtime_enabled(e24_dev->dev)) {
-+ ret = e24_boot_firmware(e24_dev->dev);
-+ if (ret)
-+ goto err_pm_disable;
-+ }
-+ nodeid = ida_simple_get(&e24_nodeid, 0, 0, GFP_KERNEL);
-+ if (nodeid < 0) {
-+ ret = nodeid;
-+ goto err_pm_disable;
-+ }
-+
-+ e24_dev->nodeid = nodeid;
-+ sprintf(nodename, "eboot%u", nodeid);
-+
-+ e24_dev->miscdev = (struct miscdevice){
-+ .minor = MISC_DYNAMIC_MINOR,
-+ .name = devm_kstrdup(&pdev->dev, nodename, GFP_KERNEL),
-+ .nodename = devm_kstrdup(&pdev->dev, nodename, GFP_KERNEL),
-+ .fops = &e24_fops,
-+ };
-+
-+ ret = misc_register(&e24_dev->miscdev);
-+ if (ret < 0)
-+ goto err_free_id;
-+
-+ return PTR_ERR(e24_dev);
-+err_free_id:
-+ ida_simple_remove(&e24_nodeid, nodeid);
-+
-+err_pm_disable:
-+ pm_runtime_disable(e24_dev->dev);
-+err_free_map:
-+ kfree(e24_dev->address_map.entry);
-+err_free_pool:
-+ e24_free_pool(e24_dev->pool);
-+err:
-+ dev_err(&pdev->dev, "%s: ret = %ld\n", __func__, ret);
-+ return ret;
-+}
-+
-+static const struct of_device_id e24_of_match[] = {
-+ {
-+ .compatible = "starfive,e24",
-+ .data = e24_init_v0,
-+ },
-+ {
-+ },
-+};
-+MODULE_DEVICE_TABLE(of, e24_of_match);
-+
-+int e24_deinit(struct platform_device *pdev)
-+{
-+ struct e24_device *e24_dev = platform_get_drvdata(pdev);
-+
-+ pm_runtime_disable(&pdev->dev);
-+ if (!pm_runtime_status_suspended(e24_dev->dev))
-+ e24_runtime_suspend(e24_dev->dev);
-+
-+ misc_deregister(&e24_dev->miscdev);
-+ e24_free_pool(e24_dev->pool);
-+ kfree(e24_dev->address_map.entry);
-+ ida_simple_remove(&e24_nodeid, e24_dev->nodeid);
-+
-+ if (e24_dev->rx_channel)
-+ mbox_free_channel(e24_dev->rx_channel);
-+ if (e24_dev->tx_channel)
-+ mbox_free_channel(e24_dev->tx_channel);
-+ return 0;
-+}
-+
-+static int e24_probe(struct platform_device *pdev)
-+{
-+ long ret = -EINVAL;
-+ const e24_init_function *init;
-+
-+ init = of_device_get_match_data(&pdev->dev);
-+ ret = init(pdev);
-+
-+ return IS_ERR_VALUE(ret) ? ret : 0;
-+}
-+
-+static void e24_remove(struct platform_device *pdev)
-+{
-+ e24_deinit(pdev);
-+}
-+
-+static const struct dev_pm_ops e24_runtime_pm_ops = {
-+ SET_RUNTIME_PM_OPS(e24_runtime_suspend,
-+ e24_boot_firmware, NULL)
-+};
-+
-+static struct platform_driver e24_driver = {
-+ .probe = e24_probe,
-+ .remove = e24_remove,
-+ .driver = {
-+ .name = "e24_boot",
-+ .of_match_table = of_match_ptr(e24_of_match),
-+ .pm = &e24_runtime_pm_ops,
-+ },
-+};
-+
-+module_platform_driver(e24_driver);
-+
-+MODULE_DESCRIPTION("StarFive e24 driver");
-+MODULE_AUTHOR("Shanlong Li <shanlong.li@starfivetech.com>");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/e24/starfive_e24.h
-@@ -0,0 +1,159 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#ifndef __STARFIVE_E24_H__
-+#define __STARFIVE_E24_H__
-+
-+#include <linux/types.h>
-+#include <linux/completion.h>
-+#include <linux/miscdevice.h>
-+#include <linux/mutex.h>
-+#include <linux/irqreturn.h>
-+#include <linux/platform_device.h>
-+
-+#define E24_IOCTL_MAGIC 'e'
-+#define E24_IOCTL_SEND _IO(E24_IOCTL_MAGIC, 1)
-+#define E24_IOCTL_RECV _IO(E24_IOCTL_MAGIC, 2)
-+#define E24_IOCTL_GET_CHANNEL _IO(E24_IOCTL_MAGIC, 3)
-+#define E24_IOCTL_FREE_CHANNEL _IO(E24_IOCTL_MAGIC, 4)
-+#define E24_IOCTL_ALLOC _IO(E24_IOCTL_MAGIC, 5)
-+#define E24_IOCTL_FREE _IO(E24_IOCTL_MAGIC, 6)
-+
-+#define E24_DSP_CMD_INLINE_DATA_SIZE 16
-+#define E24_NO_TRANSLATION ((u32)~0ul)
-+#define E24_CMD_STRIDE 256
-+
-+#define E24_MEM_MAP
-+enum e24_irq_mode {
-+ MAIL_IRQ_NONE,
-+ MAIL_IRQ_LEVEL,
-+ MAIL_IRQ_MAX
-+};
-+
-+enum {
-+ E24_FLAG_READ = 0x1,
-+ E24_FLAG_WRITE = 0x2,
-+ E24_FLAG_READ_WRITE = 0x3,
-+};
-+
-+enum {
-+ E24_QUEUE_FLAG_VALID = 0x4,
-+ E24_QUEUE_FLAG_PRIO = 0xff00,
-+ E24_QUEUE_FLAG_PRIO_SHIFT = 8,
-+
-+ E24_QUEUE_VALID_FLAGS =
-+ E24_QUEUE_FLAG_VALID |
-+ E24_QUEUE_FLAG_PRIO,
-+};
-+
-+enum {
-+ E24_CMD_FLAG_REQUEST_VALID = 0x00000001,
-+ E24_CMD_FLAG_RESPONSE_VALID = 0x00000002,
-+ E24_CMD_FLAG_REQUEST_NSID = 0x00000004,
-+ E24_CMD_FLAG_RESPONSE_DELIVERY_FAIL = 0x00000008,
-+};
-+
-+struct e24_address_map_entry {
-+ phys_addr_t src_addr;
-+ u32 dst_addr;
-+ u32 size;
-+};
-+
-+struct e24_address_map {
-+ unsigned int n;
-+ struct e24_address_map_entry *entry;
-+};
-+
-+struct e24_alien_mapping {
-+ unsigned long vaddr;
-+ unsigned long size;
-+ phys_addr_t paddr;
-+ void *allocation;
-+ enum {
-+ ALIEN_GUP,
-+ ALIEN_PFN_MAP,
-+ ALIEN_COPY,
-+ } type;
-+};
-+
-+struct e24_mapping {
-+ enum {
-+ E24_MAPPING_NONE,
-+ E24_MAPPING_NATIVE,
-+ E24_MAPPING_ALIEN,
-+ E24_MAPPING_KERNEL = 0x4,
-+ } type;
-+ union {
-+ struct {
-+ struct e24_allocation *m_allocation;
-+ unsigned long vaddr;
-+ } native;
-+ struct e24_alien_mapping alien_mapping;
-+ };
-+};
-+
-+struct e24_ioctl_alloc {
-+ u32 size;
-+ u32 align;
-+ u64 addr;
-+};
-+
-+struct e24_comm {
-+ struct mutex lock;
-+ void __iomem *comm;
-+ struct completion completion;
-+ u32 priority;
-+};
-+
-+struct e24_device {
-+ struct device *dev;
-+ const char *firmware_name;
-+ const struct firmware *firmware;
-+ struct miscdevice miscdev;
-+ const struct e24_hw_ops *hw_ops;
-+ void *hw_arg;
-+ int irq_mode;
-+
-+ u32 n_queues;
-+ struct completion completion;
-+ struct e24_address_map address_map;
-+ struct e24_comm *queue;
-+ void __iomem *comm;
-+ phys_addr_t comm_phys;
-+ phys_addr_t shared_mem;
-+ phys_addr_t shared_size;
-+
-+ u32 mbox_data;
-+ int nodeid;
-+ spinlock_t busy_list_lock;
-+
-+ struct mbox_chan *tx_channel;
-+ struct mbox_chan *rx_channel;
-+ void *rx_buffer;
-+ void *message;
-+ struct e24_allocation_pool *pool;
-+ struct e24_allocation *busy_list;
-+};
-+
-+struct e24_hw_arg {
-+ struct e24_device *e24;
-+ phys_addr_t regs_phys;
-+ struct clk *clk_rtc;
-+ struct clk *clk_core;
-+ struct clk *clk_dbg;
-+ struct reset_control *rst_core;
-+ struct regmap *reg_syscon;
-+ enum e24_irq_mode irq_mode;
-+};
-+
-+static inline int e24_compare_address(phys_addr_t addr,
-+ const struct e24_address_map_entry *entry)
-+{
-+ if (addr < entry->src_addr)
-+ return -1;
-+ if (addr - entry->src_addr < entry->size)
-+ return 0;
-+ return 1;
-+}
-+
-+irqreturn_t e24_irq_handler(int irq, struct e24_device *e24_hw);
-+
-+#endif
---- /dev/null
-+++ b/drivers/e24/starfive_e24_hw.c
-@@ -0,0 +1,134 @@
-+// SPDX-License-Identifier: GPL-2.0
-+#include <linux/delay.h>
-+#include <linux/interrupt.h>
-+#include <linux/idr.h>
-+#include <linux/io.h>
-+#include <linux/slab.h>
-+#include <linux/of.h>
-+#include <linux/clk.h>
-+#include <linux/reset.h>
-+#include <linux/module.h>
-+#include <linux/mfd/syscon.h>
-+#include <linux/regmap.h>
-+#include "starfive_e24.h"
-+#include "starfive_e24_hw.h"
-+
-+#define RET_E24_VECTOR_ADDR 0x6CE00000
-+
-+static void halt(void *hw_arg)
-+{
-+ struct e24_hw_arg *mail_arg = hw_arg;
-+
-+ reset_control_assert(mail_arg->rst_core);
-+ pr_debug("e24 halt.\n");
-+}
-+
-+static void release(void *hw_arg)
-+{
-+ struct e24_hw_arg *mail_arg = hw_arg;
-+
-+ reset_control_deassert(mail_arg->rst_core);
-+ pr_debug("e24 begin run.\n");
-+}
-+
-+static void reset(void *hw_arg)
-+{
-+ struct e24_hw_arg *mail_arg = hw_arg;
-+
-+ regmap_update_bits(mail_arg->reg_syscon, 0x24, 0xFFFFFFFF, RET_E24_VECTOR_ADDR);
-+ pr_debug("e24 reset vector.\n");
-+}
-+
-+static void disable(void *hw_arg)
-+{
-+ struct e24_hw_arg *mail_arg = hw_arg;
-+
-+ clk_disable_unprepare(mail_arg->clk_core);
-+ clk_disable_unprepare(mail_arg->clk_dbg);
-+ clk_disable_unprepare(mail_arg->clk_rtc);
-+
-+ pr_debug("e24 disable ...\n");
-+
-+}
-+
-+static int enable(void *hw_arg)
-+{
-+ struct e24_hw_arg *mail_arg = hw_arg;
-+ int ret = 0;
-+
-+ ret = clk_prepare_enable(mail_arg->clk_core);
-+ if (ret)
-+ return -EAGAIN;
-+
-+ ret = clk_prepare_enable(mail_arg->clk_dbg);
-+ if (ret) {
-+ clk_disable_unprepare(mail_arg->clk_core);
-+ return -EAGAIN;
-+ }
-+
-+ ret = clk_prepare_enable(mail_arg->clk_rtc);
-+ if (ret) {
-+ clk_disable_unprepare(mail_arg->clk_core);
-+ clk_disable_unprepare(mail_arg->clk_dbg);
-+ return -EAGAIN;
-+ }
-+
-+ pr_debug("e24_enable clk ...\n");
-+ return 0;
-+}
-+
-+
-+static int init(void *hw_arg)
-+{
-+ struct e24_hw_arg *mail_arg = hw_arg;
-+
-+ mail_arg->reg_syscon = syscon_regmap_lookup_by_phandle(
-+ mail_arg->e24->dev->of_node,
-+ "starfive,stg-syscon");
-+ if (IS_ERR(mail_arg->reg_syscon)) {
-+ dev_err(mail_arg->e24->dev, "No starfive,stg-syscon\n");
-+ return PTR_ERR(mail_arg->reg_syscon);
-+ }
-+
-+ mail_arg->clk_core = devm_clk_get_optional(mail_arg->e24->dev, "clk_core");
-+ if (IS_ERR(mail_arg->clk_core)) {
-+ dev_err(mail_arg->e24->dev, "failed to get e24 clk core\n");
-+ return -ENOMEM;
-+ }
-+
-+ mail_arg->clk_dbg = devm_clk_get_optional(mail_arg->e24->dev, "clk_dbg");
-+ if (IS_ERR(mail_arg->clk_dbg)) {
-+ dev_err(mail_arg->e24->dev, "failed to get e24 clk dbg\n");
-+ return -ENOMEM;
-+ }
-+
-+ mail_arg->clk_rtc = devm_clk_get_optional(mail_arg->e24->dev, "clk_rtc");
-+ if (IS_ERR(mail_arg->clk_rtc)) {
-+ dev_err(mail_arg->e24->dev, "failed to get e24 clk rtc\n");
-+ return -ENOMEM;
-+ }
-+
-+ mail_arg->rst_core = devm_reset_control_get_exclusive(mail_arg->e24->dev, "e24_core");
-+ if (IS_ERR(mail_arg->rst_core)) {
-+ dev_err(mail_arg->e24->dev, "failed to get e24 reset\n");
-+ return -ENOMEM;
-+ }
-+
-+ enable(hw_arg);
-+
-+ return 0;
-+}
-+
-+static struct e24_hw_ops e24_hw_ops = {
-+ .init = init,
-+ .enable = enable,
-+ .reset = reset,
-+ .halt = halt,
-+ .release = release,
-+ .disable = disable,
-+};
-+
-+struct e24_hw_ops *e24_get_hw_ops(void)
-+{
-+ return &e24_hw_ops;
-+}
---- /dev/null
-+++ b/drivers/e24/starfive_e24_hw.h
-@@ -0,0 +1,94 @@
-+/* SPDX-License-Identifier: GPL-2.0 */
-+#ifndef __STARFIVE_E24_HW_H__
-+#define __STARFIVE_E24_HW_H__
-+/*
-+ * Hardware-specific operation entry points.
-+ */
-+struct e24_hw_ops {
-+ /*
-+ * Gets the clock for E24.
-+ */
-+ int (*init)(void *hw_arg);
-+ /*
-+ * Enable power/clock, but keep the core stalled.
-+ */
-+ int (*enable)(void *hw_arg);
-+ /*
-+ * Diable power/clock.
-+ */
-+ void (*disable)(void *hw_arg);
-+ /*
-+ * Reset the core.
-+ */
-+ void (*reset)(void *hw_arg);
-+ /*
-+ * Unstall the core.
-+ */
-+ void (*release)(void *hw_arg);
-+ /*
-+ * Stall the core.
-+ */
-+ void (*halt)(void *hw_arg);
-+
-+ /* Get HW-specific data to pass to the DSP on synchronization
-+ *
-+ * param hw_arg: opaque parameter passed to DSP at initialization
-+ * param sz: return size of sync data here
-+ * return a buffer allocated with kmalloc that the caller will free
-+ */
-+ void *(*get_hw_sync_data)(void *hw_arg, size_t *sz);
-+
-+ /*
-+ * Send IRQ to the core.
-+ */
-+ void (*send_irq)(void *hw_arg);
-+
-+ /*
-+ * Check whether region of physical memory may be handled by
-+ * dma_sync_* operations
-+ *
-+ * \param hw_arg: opaque parameter passed to DSP at initialization
-+ * time
-+ */
-+ bool (*cacheable)(void *hw_arg, unsigned long pfn, unsigned long n_pages);
-+ /*
-+ * Synchronize region of memory for DSP access.
-+ *
-+ * \param hw_arg: opaque parameter passed to DSP at initialization
-+ * time
-+ */
-+ void (*dma_sync_for_device)(void *hw_arg,
-+ void *vaddr, phys_addr_t paddr,
-+ unsigned long sz, unsigned int flags);
-+ /*
-+ * Synchronize region of memory for host access.
-+ *
-+ * \param hw_arg: opaque parameter passed to DSP at initialization
-+ * time
-+ */
-+ void (*dma_sync_for_cpu)(void *hw_arg,
-+ void *vaddr, phys_addr_t paddr,
-+ unsigned long sz, unsigned int flags);
-+
-+ /*
-+ * memcpy data/code to device-specific memory.
-+ */
-+ void (*memcpy_tohw)(void __iomem *dst, const void *src, size_t sz);
-+ /*
-+ * memset device-specific memory.
-+ */
-+ void (*memset_hw)(void __iomem *dst, int c, size_t sz);
-+
-+ /*
-+ * Check DSP status.
-+ *
-+ * \param hw_arg: opaque parameter passed to DSP at initialization
-+ * time
-+ * \return whether the core has crashed and needs to be restarted
-+ */
-+ bool (*panic_check)(void *hw_arg);
-+};
-+
-+long e24_init_hw(struct platform_device *pdev, void *hw_arg);
-+struct e24_hw_ops *e24_get_hw_ops(void);
-+#endif
+++ /dev/null
-From 0eaf04ef4963db173428da176f52320754b0574c Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Thu, 10 Oct 2024 11:05:20 +0800
-Subject: [PATCH 19/55] net: stmmac: Extend waiting time of dma reset
-
-Fix dma reset failure happening when disabling network.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_lib.c
-@@ -23,7 +23,7 @@ int dwmac4_dma_reset(void __iomem *ioadd
-
- return readl_poll_timeout(ioaddr + DMA_BUS_MODE, value,
- !(value & DMA_BUS_MODE_SFT_RESET),
-- 10000, 1000000);
-+ 10000, 3000000);
- }
-
- void dwmac4_set_rx_tail_ptr(struct stmmac_priv *priv, void __iomem *ioaddr,
+++ /dev/null
-From 714c99f993097e5c16822e73ba0a7945b86a20ea Mon Sep 17 00:00:00 2001
-From: "xingyu.wu" <xingyu.wu@starfivetech.com>
-Date: Tue, 28 Jun 2022 22:48:15 +0800
-Subject: [PATCH 20/55] spi-pl022:starfive:Add platform bus register to adapt
- overlay
-
-Add platform bus register to adapt dtbo overlay.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 143 ++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 137 insertions(+), 6 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -34,6 +34,7 @@
- #include <linux/of.h>
- #include <linux/pinctrl/consumer.h>
- #include <linux/reset.h>
-+#include <linux/platform_device.h>
-
- /*
- * This macro is used to define some register default values.
-@@ -1841,7 +1842,10 @@ pl022_platform_data_dt_get(struct device
- return NULL;
- }
-
-- pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL);
-+ if (strncmp(dev->bus->name, "platform", strlen("platform")))
-+ pd = devm_kzalloc(dev, sizeof(struct pl022_ssp_controller), GFP_KERNEL);
-+ else
-+ pd = kzalloc(sizeof(struct pl022_ssp_controller), GFP_KERNEL);
- if (!pd)
- return NULL;
-
-@@ -1861,6 +1865,14 @@ static int pl022_probe(struct amba_devic
- struct spi_controller *host;
- struct pl022 *pl022 = NULL; /*Data for this driver */
- int status = 0;
-+ int platform_flag = 0;
-+
-+ if (strncmp(dev->bus->name, "platform", strlen("platform")))
-+ platform_flag = 0;
-+ else
-+ platform_flag = 1;
-+ dev_dbg(&adev->dev, "bus name:%s platform flag:%d",
-+ dev->bus->name, platform_flag);
-
- dev_info(&adev->dev,
- "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
-@@ -1916,7 +1928,11 @@ static int pl022_probe(struct amba_devic
- goto err_no_ioregion;
-
- pl022->phybase = adev->res.start;
-- pl022->virtbase = devm_ioremap(dev, adev->res.start,
-+ if (platform_flag)
-+ pl022->virtbase = ioremap(adev->res.start,
-+ resource_size(&adev->res));
-+ else
-+ pl022->virtbase = devm_ioremap(dev, adev->res.start,
- resource_size(&adev->res));
- if (pl022->virtbase == NULL) {
- status = -ENOMEM;
-@@ -1925,14 +1941,28 @@ static int pl022_probe(struct amba_devic
- dev_info(&adev->dev, "mapped registers from %pa to %p\n",
- &adev->res.start, pl022->virtbase);
-
-- pl022->clk = devm_clk_get_enabled(&adev->dev, NULL);
-+ if (platform_flag)
-+ pl022->clk = clk_get(&adev->dev, NULL);
-+ else
-+ pl022->clk = devm_clk_get_enabled(&adev->dev, NULL);
- if (IS_ERR(pl022->clk)) {
- status = PTR_ERR(pl022->clk);
- dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
- goto err_no_clk;
- }
-
-- pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-+ if (platform_flag) {
-+ status = clk_prepare_enable(pl022->clk);
-+ if (status) {
-+ dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
-+ goto err_no_clk_en;
-+ }
-+ }
-+
-+ if (platform_flag)
-+ pl022->rst = reset_control_get_exclusive(&adev->dev, NULL);
-+ else
-+ pl022->rst = devm_reset_control_get(&adev->dev, NULL);
- if (IS_ERR(pl022->rst)) {
- status = PTR_ERR(pl022->rst);
- dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
-@@ -1950,7 +1980,11 @@ static int pl022_probe(struct amba_devic
- SSP_CR1(pl022->virtbase));
- load_ssp_default_config(pl022);
-
-- status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
-+ if (platform_flag)
-+ status = request_irq(adev->irq[0], pl022_interrupt_handler,
-+ 0, "pl022", pl022);
-+ else
-+ status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
- 0, "pl022", pl022);
- if (status < 0) {
- dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
-@@ -1975,7 +2009,10 @@ static int pl022_probe(struct amba_devic
-
- /* Register with the SPI framework */
- amba_set_drvdata(adev, pl022);
-- status = devm_spi_register_controller(&adev->dev, host);
-+ if (platform_flag)
-+ status = spi_register_controller(host);
-+ else
-+ status = devm_spi_register_controller(&adev->dev, host);
- if (status != 0) {
- dev_err_probe(&adev->dev, status,
- "problem registering spi host\n");
-@@ -2000,13 +2037,24 @@ static int pl022_probe(struct amba_devic
- if (platform_info->enable_dma)
- pl022_dma_remove(pl022);
- err_no_irq:
-+ if (platform_flag)
-+ free_irq(adev->irq[0], pl022);
-+ reset_control_assert(pl022->rst);
- err_no_rst_de:
-+ if (platform_flag)
-+ reset_control_put(pl022->rst);
- err_no_rst:
-+ if (platform_flag)
-+ clk_put(pl022->clk);
- err_no_clk:
-+ if (platform_flag)
-+ iounmap(pl022->virtbase);
- err_no_ioremap:
- amba_release_regions(adev);
- err_no_ioregion:
- spi_controller_put(host);
-+ if (platform_flag)
-+ kfree(platform_info);
- return status;
- }
-
-@@ -2205,6 +2253,89 @@ static void __exit pl022_exit(void)
- }
- module_exit(pl022_exit);
-
-+/*
-+ * Register PL022 in platform bus to accommodate overlay use.
-+ * Because overlay only trigger response from the platform bus
-+ * not amba bus.
-+ */
-+static int starfive_of_pl022_probe(struct platform_device *pdev)
-+{
-+ int ret;
-+ const struct amba_id id = {
-+ .id = 0x00041022,
-+ .mask = 0x000fffff,
-+ .data = &vendor_arm
-+ };
-+ struct amba_device *pcdev;
-+ struct device *dev = &pdev->dev;
-+
-+ pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
-+ if (!pcdev)
-+ return -ENOMEM;
-+
-+ pcdev->dev = pdev->dev;
-+ pcdev->periphid = id.id;
-+ pcdev->res = *(pdev->resource);
-+
-+ pcdev->irq[0] = platform_get_irq(pdev, 0);
-+ if (pcdev->irq[0] < 0) {
-+ dev_err(dev, "failed to get irq\n");
-+ ret = -EINVAL;
-+ }
-+
-+ ret = pl022_probe(pcdev, &id);
-+
-+ return ret;
-+}
-+
-+static void starfive_of_pl022_remove(struct platform_device *pdev)
-+{
-+ u32 size;
-+ int irq;
-+ struct pl022 *pl022 = dev_get_drvdata(&pdev->dev);
-+
-+ if (!pl022)
-+ return;
-+
-+ pm_runtime_get_noresume(&pdev->dev);
-+
-+ load_ssp_default_config(pl022);
-+ if (pl022->host_info->enable_dma)
-+ pl022_dma_remove(pl022);
-+
-+ irq = platform_get_irq(pdev, 0);
-+ free_irq(irq, pl022);
-+ reset_control_assert(pl022->rst);
-+ reset_control_put(pl022->rst);
-+ clk_disable_unprepare(pl022->clk);
-+ clk_put(pl022->clk);
-+ iounmap(pl022->virtbase);
-+ kfree(pl022->host_info);
-+
-+ size = resource_size(pdev->resource);
-+ release_mem_region(pdev->resource->start, size);
-+}
-+
-+static const struct of_device_id starfive_of_pl022_match[] = {
-+ { .compatible = "starfive,jh7110-spi-pl022" },
-+ { },
-+};
-+MODULE_DEVICE_TABLE(of, starfive_of_pl022_match);
-+
-+static struct platform_driver starfive_of_pl022_driver = {
-+ .driver = {
-+ .name = "starfive-spi-pl022",
-+ .of_match_table = starfive_of_pl022_match,
-+ .pm = &pl022_dev_pm_ops,
-+ },
-+ .probe = starfive_of_pl022_probe,
-+ .remove = starfive_of_pl022_remove,
-+};
-+
-+module_platform_driver(starfive_of_pl022_driver);
-+/* platform register end */
-+
-+MODULE_AUTHOR("xingyu.wu <xingyu.wu@starfivetech.com>");
- MODULE_AUTHOR("Linus Walleij <linus.walleij@stericsson.com>");
- MODULE_DESCRIPTION("PL022 SSP Controller Driver");
- MODULE_LICENSE("GPL");
+++ /dev/null
-From 8063cc5e813c3a5f86a4f17e3681cda3dbebcb1a Mon Sep 17 00:00:00 2001
-From: "xingyu.wu" <xingyu.wu@starfivetech.com>
-Date: Tue, 19 Jul 2022 14:49:20 +0800
-Subject: [PATCH 21/55] spi:pl022-starfive:Avoid power device error when
- CONFIG_PM enable
-
-It would be error when CONFIG_PM enable and use overlay by of-platform to register.
-
-Add some power manager operation in platform probe function.
-
-Signed-off-by: Xingyu Wu <xingyu.wu@starfivetech.com>
-Signed-off-by: Ziv Xu <ziv.xu@starfivetech.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 36 ++++++++++++++++++++++++++++++++++--
- 1 file changed, 34 insertions(+), 2 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -35,6 +35,8 @@
- #include <linux/pinctrl/consumer.h>
- #include <linux/reset.h>
- #include <linux/platform_device.h>
-+#include <linux/clk/clk-conf.h>
-+#include <linux/pm_domain.h>
-
- /*
- * This macro is used to define some register default values.
-@@ -2019,7 +2021,8 @@ static int pl022_probe(struct amba_devic
- goto err_spi_register;
- }
- dev_dbg(dev, "probe succeeded\n");
--
-+ if (!platform_flag)
-+ platform_info->autosuspend_delay = 100;
- /* let runtime pm put suspend */
- if (platform_info->autosuspend_delay > 0) {
- dev_info(&adev->dev,
-@@ -2029,7 +2032,10 @@ static int pl022_probe(struct amba_devic
- platform_info->autosuspend_delay);
- pm_runtime_use_autosuspend(dev);
- }
-- pm_runtime_put(dev);
-+ if (platform_flag)
-+ clk_disable_unprepare(pl022->clk);
-+ else
-+ pm_runtime_put(dev);
-
- return 0;
-
-@@ -2283,8 +2289,33 @@ static int starfive_of_pl022_probe(struc
- ret = -EINVAL;
- }
-
-+ ret = of_clk_set_defaults(dev->of_node, false);
-+ if (ret < 0)
-+ goto err_probe;
-+
-+ ret = dev_pm_domain_attach(dev, true);
-+ if (ret)
-+ goto err_probe;
-+
- ret = pl022_probe(pcdev, &id);
-
-+ struct pl022 *pl022 = amba_get_drvdata(pcdev);
-+
-+ pl022->host->dev.parent = &pdev->dev;
-+ platform_set_drvdata(pdev, pl022);
-+
-+ pm_runtime_enable(&pdev->dev);
-+ pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
-+ pm_runtime_use_autosuspend(&pdev->dev);
-+
-+ if (ret) {
-+ pm_runtime_disable(dev);
-+ pm_runtime_set_suspended(dev);
-+ pm_runtime_put_noidle(dev);
-+ dev_pm_domain_detach(dev, true);
-+ }
-+
-+err_probe:
- return ret;
- }
-
-@@ -2314,6 +2345,7 @@ static void starfive_of_pl022_remove(str
-
- size = resource_size(pdev->resource);
- release_mem_region(pdev->resource->start, size);
-+ pm_runtime_disable(&pdev->dev);
- }
-
- static const struct of_device_id starfive_of_pl022_match[] = {
+++ /dev/null
-From 7a98fafdc544b85694db5d99cdf933a4640058f9 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfive.com>
-Date: Wed, 23 Nov 2022 14:53:58 +0800
-Subject: [PATCH 22/55] spi-pl022-starfive:fix the problem of spi overlay
- reload
-
-fix the problem of spi overlay reload
-
-Signed-off-by: ziv.xu <ziv.xu@starfive.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 266 ++++++++++++++++++++++++++--------------
- 1 file changed, 177 insertions(+), 89 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -1859,6 +1859,163 @@ pl022_platform_data_dt_get(struct device
- return pd;
- }
-
-+static int pl022_platform_probe(struct platform_device *pdev, const struct amba_id *id)
-+{
-+ struct device *dev = &pdev->dev;
-+ struct spi_controller *host;
-+ struct pl022_ssp_controller *platform_info;
-+ struct amba_device *adev;
-+ struct pl022 *pl022 = NULL;
-+ struct resource *res;
-+ int status = 0;
-+ int irq;
-+
-+ dev_info(dev,
-+ "ARM PL022 driver for StarFive SoC platform, device ID: 0x%08x\n",
-+ id->id);
-+
-+ adev = devm_kzalloc(dev, sizeof(*adev), GFP_KERNEL);
-+ adev->dev = pdev->dev;
-+ platform_info = pl022_platform_data_dt_get(dev);
-+ if (!platform_info) {
-+ dev_err(dev, "probe: no platform data defined\n");
-+ return -ENODEV;
-+ }
-+ /* Allocate host with space for data */
-+ host = spi_alloc_host(dev, sizeof(struct pl022));
-+ if (host == NULL) {
-+ dev_err(dev, "probe - cannot alloc SPI host\n");
-+ return -ENOMEM;
-+ }
-+
-+ pl022 = spi_controller_get_devdata(host);
-+ pl022->host = host;
-+ pl022->host_info = platform_info;
-+ pl022->adev = adev;
-+ pl022->vendor = id->data;
-+ pl022->host->dev.parent = &pdev->dev;
-+ /*
-+ * Bus Number Which has been Assigned to this SSP controller
-+ * on this board
-+ */
-+ host->bus_num = platform_info->bus_id;
-+ host->cleanup = pl022_cleanup;
-+ host->setup = pl022_setup;
-+ /* If open CONFIG_PM, auto_runtime_pm should be false when of-platform.*/
-+ host->auto_runtime_pm = true;
-+ host->transfer_one = pl022_transfer_one;
-+ host->set_cs = pl022_cs_control;
-+ host->handle_err = pl022_handle_err;
-+ host->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
-+ host->rt = platform_info->rt;
-+ host->dev.of_node = dev->of_node;
-+ host->use_gpio_descriptors = true;
-+
-+ /*
-+ * Supports mode 0-3, loopback, and active low CS. Transfers are
-+ * always MS bit first on the original pl022.
-+ */
-+ host->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LOOP;
-+ if (pl022->vendor->extended_cr)
-+ host->mode_bits |= SPI_LSB_FIRST;
-+
-+ dev_dbg(dev, "BUSNO: %d\n", host->bus_num);
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ pl022->phybase = res->start;
-+ pl022->virtbase = devm_ioremap_resource(dev, res);
-+ if (pl022->virtbase == NULL) {
-+ status = -ENOMEM;
-+ goto err_no_ioremap;
-+ }
-+ dev_info(dev, "mapped registers from %llx to %llx\n",
-+ pdev->resource->start, pdev->resource->end);
-+
-+ pl022->clk = devm_clk_get_enabled(dev, NULL);
-+ if (IS_ERR(pl022->clk)) {
-+ status = PTR_ERR(pl022->clk);
-+ dev_err(dev, "could not retrieve SSP/SPI bus clock\n");
-+ goto err_no_clk;
-+ }
-+
-+ pl022->rst = devm_reset_control_get_exclusive(dev, NULL);
-+ if (IS_ERR(pl022->rst)) {
-+ status = PTR_ERR(pl022->rst);
-+ dev_err(dev, "could not retrieve SSP/SPI bus reset\n");
-+ goto err_no_rst;
-+ }
-+
-+ status = reset_control_deassert(pl022->rst);
-+ if (status) {
-+ dev_err(dev, "could not deassert SSP/SPI bus reset\n");
-+ goto err_no_rst_de;
-+ }
-+
-+ /* Disable SSP */
-+ writew((readw(SSP_CR1(pl022->virtbase)) & (~SSP_CR1_MASK_SSE)),
-+ SSP_CR1(pl022->virtbase));
-+ load_ssp_default_config(pl022);
-+
-+ /* Obtain IRQ line. */
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq < 0) {
-+ status = -ENXIO;
-+ goto err_no_irq;
-+ }
-+ status = devm_request_irq(dev, irq, pl022_interrupt_handler,
-+ 0, "pl022", pl022);
-+ if (status < 0) {
-+ dev_err(dev, "probe - cannot get IRQ (%d)\n", status);
-+ goto err_no_irq;
-+ }
-+
-+ /* Get DMA channels, try autoconfiguration first */
-+ status = pl022_dma_autoprobe(pl022);
-+ if (status == -EPROBE_DEFER) {
-+ dev_dbg(dev, "deferring probe to get DMA channel\n");
-+ goto err_no_irq;
-+ }
-+
-+ /* dma is not used unless configured in the device tree */
-+ platform_info->enable_dma = 0;
-+
-+ /* If that failed, use channels from platform_info */
-+ if (status == 0)
-+ platform_info->enable_dma = 1;
-+ else if (platform_info->enable_dma) {
-+ status = pl022_dma_probe(pl022);
-+ if (status != 0)
-+ platform_info->enable_dma = 0;
-+ }
-+
-+ /* Register with the SPI framework */
-+ dev_set_drvdata(dev, pl022);
-+
-+ status = devm_spi_register_controller(dev, host);
-+ if (status != 0) {
-+ dev_err(dev,
-+ "probe - problem registering spi host\n");
-+ goto err_spi_register;
-+ }
-+ dev_dbg(dev, "probe succeeded\n");
-+
-+ clk_disable_unprepare(pl022->clk);
-+
-+ return 0;
-+ err_spi_register:
-+ if (platform_info->enable_dma)
-+ pl022_dma_remove(pl022);
-+ err_no_irq:
-+ reset_control_assert(pl022->rst);
-+ err_no_rst_de:
-+ err_no_rst:
-+ err_no_clk:
-+ err_no_ioremap:
-+ release_mem_region(pdev->resource->start, resource_size(pdev->resource));
-+ spi_controller_put(host);
-+ return status;
-+}
-+
- static int pl022_probe(struct amba_device *adev, const struct amba_id *id)
- {
- struct device *dev = &adev->dev;
-@@ -1867,14 +2024,6 @@ static int pl022_probe(struct amba_devic
- struct spi_controller *host;
- struct pl022 *pl022 = NULL; /*Data for this driver */
- int status = 0;
-- int platform_flag = 0;
--
-- if (strncmp(dev->bus->name, "platform", strlen("platform")))
-- platform_flag = 0;
-- else
-- platform_flag = 1;
-- dev_dbg(&adev->dev, "bus name:%s platform flag:%d",
-- dev->bus->name, platform_flag);
-
- dev_info(&adev->dev,
- "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
-@@ -1930,11 +2079,7 @@ static int pl022_probe(struct amba_devic
- goto err_no_ioregion;
-
- pl022->phybase = adev->res.start;
-- if (platform_flag)
-- pl022->virtbase = ioremap(adev->res.start,
-- resource_size(&adev->res));
-- else
-- pl022->virtbase = devm_ioremap(dev, adev->res.start,
-+ pl022->virtbase = devm_ioremap(dev, adev->res.start,
- resource_size(&adev->res));
- if (pl022->virtbase == NULL) {
- status = -ENOMEM;
-@@ -1943,28 +2088,14 @@ static int pl022_probe(struct amba_devic
- dev_info(&adev->dev, "mapped registers from %pa to %p\n",
- &adev->res.start, pl022->virtbase);
-
-- if (platform_flag)
-- pl022->clk = clk_get(&adev->dev, NULL);
-- else
-- pl022->clk = devm_clk_get_enabled(&adev->dev, NULL);
-+ pl022->clk = devm_clk_get_enabled(&adev->dev, NULL);
- if (IS_ERR(pl022->clk)) {
- status = PTR_ERR(pl022->clk);
- dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
- goto err_no_clk;
- }
-
-- if (platform_flag) {
-- status = clk_prepare_enable(pl022->clk);
-- if (status) {
-- dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
-- goto err_no_clk_en;
-- }
-- }
--
-- if (platform_flag)
-- pl022->rst = reset_control_get_exclusive(&adev->dev, NULL);
-- else
-- pl022->rst = devm_reset_control_get(&adev->dev, NULL);
-+ pl022->rst = devm_reset_control_get(&adev->dev, NULL);
- if (IS_ERR(pl022->rst)) {
- status = PTR_ERR(pl022->rst);
- dev_err(&adev->dev, "could not retrieve SSP/SPI bus reset\n");
-@@ -1982,11 +2113,7 @@ static int pl022_probe(struct amba_devic
- SSP_CR1(pl022->virtbase));
- load_ssp_default_config(pl022);
-
-- if (platform_flag)
-- status = request_irq(adev->irq[0], pl022_interrupt_handler,
-- 0, "pl022", pl022);
-- else
-- status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
-+ status = devm_request_irq(dev, adev->irq[0], pl022_interrupt_handler,
- 0, "pl022", pl022);
- if (status < 0) {
- dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
-@@ -2011,18 +2138,16 @@ static int pl022_probe(struct amba_devic
-
- /* Register with the SPI framework */
- amba_set_drvdata(adev, pl022);
-- if (platform_flag)
-- status = spi_register_controller(host);
-- else
-- status = devm_spi_register_controller(&adev->dev, host);
-+
-+ status = devm_spi_register_controller(&adev->dev, host);
- if (status != 0) {
- dev_err_probe(&adev->dev, status,
- "problem registering spi host\n");
- goto err_spi_register;
- }
- dev_dbg(dev, "probe succeeded\n");
-- if (!platform_flag)
-- platform_info->autosuspend_delay = 100;
-+
-+ platform_info->autosuspend_delay = 100;
- /* let runtime pm put suspend */
- if (platform_info->autosuspend_delay > 0) {
- dev_info(&adev->dev,
-@@ -2032,10 +2157,8 @@ static int pl022_probe(struct amba_devic
- platform_info->autosuspend_delay);
- pm_runtime_use_autosuspend(dev);
- }
-- if (platform_flag)
-- clk_disable_unprepare(pl022->clk);
-- else
-- pm_runtime_put(dev);
-+
-+ pm_runtime_put(dev);
-
- return 0;
-
-@@ -2043,24 +2166,15 @@ static int pl022_probe(struct amba_devic
- if (platform_info->enable_dma)
- pl022_dma_remove(pl022);
- err_no_irq:
-- if (platform_flag)
-- free_irq(adev->irq[0], pl022);
- reset_control_assert(pl022->rst);
- err_no_rst_de:
-- if (platform_flag)
-- reset_control_put(pl022->rst);
- err_no_rst:
-- if (platform_flag)
-- clk_put(pl022->clk);
- err_no_clk:
-- if (platform_flag)
-- iounmap(pl022->virtbase);
- err_no_ioremap:
- amba_release_regions(adev);
- err_no_ioregion:
- spi_controller_put(host);
-- if (platform_flag)
-- kfree(platform_info);
-+
- return status;
- }
-
-@@ -2272,23 +2386,8 @@ static int starfive_of_pl022_probe(struc
- .mask = 0x000fffff,
- .data = &vendor_arm
- };
-- struct amba_device *pcdev;
- struct device *dev = &pdev->dev;
-
-- pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
-- if (!pcdev)
-- return -ENOMEM;
--
-- pcdev->dev = pdev->dev;
-- pcdev->periphid = id.id;
-- pcdev->res = *(pdev->resource);
--
-- pcdev->irq[0] = platform_get_irq(pdev, 0);
-- if (pcdev->irq[0] < 0) {
-- dev_err(dev, "failed to get irq\n");
-- ret = -EINVAL;
-- }
--
- ret = of_clk_set_defaults(dev->of_node, false);
- if (ret < 0)
- goto err_probe;
-@@ -2297,16 +2396,11 @@ static int starfive_of_pl022_probe(struc
- if (ret)
- goto err_probe;
-
-- ret = pl022_probe(pcdev, &id);
--
-- struct pl022 *pl022 = amba_get_drvdata(pcdev);
--
-- pl022->host->dev.parent = &pdev->dev;
-- platform_set_drvdata(pdev, pl022);
-+ ret = pl022_platform_probe(pdev, &id);
-
-- pm_runtime_enable(&pdev->dev);
-- pm_runtime_set_autosuspend_delay(&pdev->dev, 100);
-- pm_runtime_use_autosuspend(&pdev->dev);
-+ pm_runtime_enable(dev);
-+ pm_runtime_set_autosuspend_delay(dev, 100);
-+ pm_runtime_use_autosuspend(dev);
-
- if (ret) {
- pm_runtime_disable(dev);
-@@ -2321,31 +2415,25 @@ err_probe:
-
- static void starfive_of_pl022_remove(struct platform_device *pdev)
- {
-- u32 size;
-- int irq;
- struct pl022 *pl022 = dev_get_drvdata(&pdev->dev);
-
- if (!pl022)
- return;
-
-+ pm_runtime_get_sync(&pdev->dev);
- pm_runtime_get_noresume(&pdev->dev);
-
- load_ssp_default_config(pl022);
- if (pl022->host_info->enable_dma)
- pl022_dma_remove(pl022);
-
-- irq = platform_get_irq(pdev, 0);
-- free_irq(irq, pl022);
-- reset_control_assert(pl022->rst);
-- reset_control_put(pl022->rst);
- clk_disable_unprepare(pl022->clk);
-- clk_put(pl022->clk);
-- iounmap(pl022->virtbase);
-- kfree(pl022->host_info);
-
-- size = resource_size(pdev->resource);
-- release_mem_region(pdev->resource->start, size);
-+ pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
-+ pm_runtime_set_suspended(&pdev->dev);
-+ pm_runtime_put_noidle(&pdev->dev);
-+ dev_pm_domain_detach(&pdev->dev, true);
- }
-
- static const struct of_device_id starfive_of_pl022_match[] = {
+++ /dev/null
-From 4ed44e07a80ef61932b1b5012fc7f8a5a7767e41 Mon Sep 17 00:00:00 2001
-From: "ziv.xu" <ziv.xu@starfive.com>
-Date: Wed, 18 Jan 2023 15:50:47 +0800
-Subject: [PATCH 23/55] spi-pl022-starfive:Enable spi to be compiled into
- modules
-
-Enable spi to be compiled into modules
-
-Signed-off-by: ziv.xu <ziv.xu@starfive.com>
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -2365,7 +2365,11 @@ static int __init pl022_init(void)
- {
- return amba_driver_register(&pl022_driver);
- }
-+#if !IS_MODULE(CONFIG_SPI_PL022)
- subsys_initcall(pl022_init);
-+#else
-+module_init(pl022_init);
-+#endif
-
- static void __exit pl022_exit(void)
- {
-@@ -2452,7 +2456,9 @@ static struct platform_driver starfive_o
- .remove = starfive_of_pl022_remove,
- };
-
-+#if !IS_MODULE(CONFIG_SPI_PL022)
- module_platform_driver(starfive_of_pl022_driver);
-+#endif
- /* platform register end */
-
- MODULE_AUTHOR("xingyu.wu <xingyu.wu@starfivetech.com>");
+++ /dev/null
-From 1944de0e9d9c23f071ec1a75177ea7adbb87ba26 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Thu, 6 Jun 2024 11:01:58 +0800
-Subject: [PATCH 24/55] spi: pl022: Prompt warning when frequency does not
- support
-
-Prompt warning when the frequency does not support.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -1556,6 +1556,10 @@ static int calculate_effective_freq(stru
- WARN(!best_freq, "pl022: Matching cpsdvsr and scr not found for %d Hz rate \n",
- freq);
-
-+ if (best_freq != freq)
-+ dev_warn(&pl022->adev->dev,
-+ "Requested frequency: %d Hz is unsupported,select by default %d Hz\n",
-+ freq, best_freq);
- clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
- clk_freq->scr = (u8) (best_scr & 0xFF);
- dev_dbg(&pl022->adev->dev,
+++ /dev/null
-From 1b818a33e3cd20250b72306946789d09d2c7b2c8 Mon Sep 17 00:00:00 2001
-From: Hal Feng <hal.feng@starfivetech.com>
-Date: Sun, 26 Jan 2025 16:56:05 +0800
-Subject: [PATCH 25/55] spi: pl022: Fix spi overlay falut
-
-set_cs() should not be set for spi controller when using overlay.
-clk_disable_unprepare() is not needed after using
-devm_clk_get_enabled() to get and enable clocks.
-
-Signed-off-by: Hal Feng <hal.feng@starfivetech.com>
----
- drivers/spi/spi-pl022.c | 3 ---
- 1 file changed, 3 deletions(-)
-
---- a/drivers/spi/spi-pl022.c
-+++ b/drivers/spi/spi-pl022.c
-@@ -1908,7 +1908,6 @@ static int pl022_platform_probe(struct p
- /* If open CONFIG_PM, auto_runtime_pm should be false when of-platform.*/
- host->auto_runtime_pm = true;
- host->transfer_one = pl022_transfer_one;
-- host->set_cs = pl022_cs_control;
- host->handle_err = pl022_handle_err;
- host->unprepare_transfer_hardware = pl022_unprepare_transfer_hardware;
- host->rt = platform_info->rt;
-@@ -2435,8 +2434,6 @@ static void starfive_of_pl022_remove(str
- if (pl022->host_info->enable_dma)
- pl022_dma_remove(pl022);
-
-- clk_disable_unprepare(pl022->clk);
--
- pm_runtime_put_noidle(&pdev->dev);
- pm_runtime_disable(&pdev->dev);
- pm_runtime_set_suspended(&pdev->dev);
+++ /dev/null
-From 7e21305a33876bb56294389d5ecd6f497800e2fb Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
- <joao.mario@tecnico.ulisboa.pt>
-Date: Tue, 16 Nov 2021 15:48:11 +0000
-Subject: [PATCH 26/55] RISC-V: Added generic pmu-events mapfile
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The pmu-events now supports custom events for RISC-V, plus the cycle,
-time and instret events were defined.
-
-Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
----
- .../pmu-events/arch/riscv/riscv-generic.json | 20 +++++++++++++++++++
- 1 file changed, 20 insertions(+)
- create mode 100644 tools/perf/pmu-events/arch/riscv/riscv-generic.json
-
---- /dev/null
-+++ b/tools/perf/pmu-events/arch/riscv/riscv-generic.json
-@@ -0,0 +1,20 @@
-+[
-+ {
-+ "PublicDescription": "CPU Cycles",
-+ "EventCode": "0x00",
-+ "EventName": "riscv_cycles",
-+ "BriefDescription": "CPU cycles RISC-V generic counter"
-+ },
-+ {
-+ "PublicDescription": "CPU Time",
-+ "EventCode": "0x01",
-+ "EventName": "riscv_time",
-+ "BriefDescription": "CPU time RISC-V generic counter"
-+ },
-+ {
-+ "PublicDescription": "CPU Instructions",
-+ "EventCode": "0x02",
-+ "EventName": "riscv_instret",
-+ "BriefDescription": "CPU retired instructions RISC-V generic counter"
-+ }
-+]
-\ No newline at end of file
+++ /dev/null
-From f0b0e5392bd7bce16c86d4ed3fc66394db16eb7d Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
- <joao.mario@tecnico.ulisboa.pt>
-Date: Tue, 16 Nov 2021 15:48:09 +0000
-Subject: [PATCH 27/55] RISC-V: Create unique identification for SoC PMU
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-The SBI PMU platform driver did not provide any identification for
-perf events matching. This patch introduces a new sysfs file inside the
-platform device (soc:pmu/id) for pmu identification.
-
-The identification is a 64-bit value generated as:
-[63-32]: mvendorid;
-[31]: marchid[MSB];
-[30-16]: marchid[15-0];
-[15-0]: mimpid[15MSBs];
-
-The CSRs are detailed in the RISC-V privileged spec [1].
-The marchid is split in MSB + 15LSBs, due to the MSB being used for
-open-source architecture identification.
-
-[1] https://github.com/riscv/riscv-isa-manual
-
-Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
----
- drivers/perf/riscv_pmu_sbi.c | 47 ++++++++++++++++++++++++++++++++++++
- 1 file changed, 47 insertions(+)
-
---- a/drivers/perf/riscv_pmu_sbi.c
-+++ b/drivers/perf/riscv_pmu_sbi.c
-@@ -1326,6 +1326,46 @@ static struct ctl_table sbi_pmu_sysctl_t
- },
- };
-
-+static uint64_t pmu_sbi_get_pmu_id(void)
-+{
-+ union sbi_pmu_id {
-+ uint64_t value;
-+ struct {
-+ uint16_t imp:16;
-+ uint16_t arch:16;
-+ uint32_t vendor:32;
-+ };
-+ } pmuid;
-+
-+ pmuid.value = 0;
-+ pmuid.vendor = (uint32_t) sbi_get_mvendorid();
-+ pmuid.arch = (sbi_get_marchid() >> (63 - 15) & (1 << 15)) | (sbi_get_marchid() & 0x7FFF);
-+ pmuid.imp = (sbi_get_mimpid() >> 16);
-+
-+ return pmuid.value;
-+}
-+
-+static ssize_t pmu_sbi_id_show(struct device *dev,
-+ struct device_attribute *attr, char *buf)
-+{
-+ int len;
-+
-+ len = sprintf(buf, "0x%llx\n", pmu_sbi_get_pmu_id());
-+ if (len <= 0)
-+ dev_err(dev, "mydrv: Invalid sprintf len: %dn", len);
-+
-+ return len;
-+}
-+
-+static DEVICE_ATTR(id, S_IRUGO | S_IWUSR, pmu_sbi_id_show, 0);
-+
-+static struct attribute *pmu_sbi_attrs[] = {
-+ &dev_attr_id.attr,
-+ NULL
-+};
-+
-+ATTRIBUTE_GROUPS(pmu_sbi);
-+
- static int pmu_sbi_device_probe(struct platform_device *pdev)
- {
- struct riscv_pmu *pmu = NULL;
-@@ -1375,6 +1415,13 @@ static int pmu_sbi_device_probe(struct p
- pmu->event_unmapped = pmu_sbi_event_unmapped;
- pmu->csr_index = pmu_sbi_csr_index;
-
-+ ret = sysfs_create_group(&pdev->dev.kobj, &pmu_sbi_group);
-+ if (ret) {
-+ dev_err(&pdev->dev, "sysfs creation failed\n");
-+ return ret;
-+ }
-+ pdev->dev.groups = pmu_sbi_groups;
-+
- ret = riscv_pm_pmu_register(pmu);
- if (ret)
- goto out_unregister;
+++ /dev/null
-From 81ab7f42a1153d6d93b3d429ae0c779e97b0d3d6 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Jo=C3=A3o=20M=C3=A1rio=20Domingos?=
- <joao.mario@tecnico.ulisboa.pt>
-Date: Tue, 16 Nov 2021 15:48:10 +0000
-Subject: [PATCH 28/55] RISC-V: Support CPUID for risc-v in perf
-MIME-Version: 1.0
-Content-Type: text/plain; charset=UTF-8
-Content-Transfer-Encoding: 8bit
-
-This patch creates the header.c file for the risc-v architecture and introduces support for
-PMU identification through sysfs.
-It is now possible to configure pmu-events in risc-v.
-
-Depends on patch [1], that introduces the id sysfs file.
-
-Signed-off-by: João Mário Domingos <joao.mario@tecnico.ulisboa.pt>
-Signed-off-by: minda.chen <minda.chen@starfivetech.com>
----
- drivers/perf/riscv_pmu.c | 18 ++++++++++++++++++
- 1 file changed, 18 insertions(+)
-
---- a/drivers/perf/riscv_pmu.c
-+++ b/drivers/perf/riscv_pmu.c
-@@ -18,6 +18,23 @@
-
- #include <asm/sbi.h>
-
-+PMU_FORMAT_ATTR(event, "config:0-63");
-+
-+static struct attribute *riscv_arch_formats_attr[] = {
-+ &format_attr_event.attr,
-+ NULL,
-+};
-+
-+static struct attribute_group riscv_pmu_format_group = {
-+ .name = "format",
-+ .attrs = riscv_arch_formats_attr,
-+};
-+
-+static const struct attribute_group *riscv_pmu_attr_groups[] = {
-+ &riscv_pmu_format_group,
-+ NULL,
-+};
-+
- static bool riscv_perf_user_access(struct perf_event *event)
- {
- return ((event->attr.type == PERF_TYPE_HARDWARE) ||
-@@ -407,6 +424,7 @@ struct riscv_pmu *riscv_pmu_alloc(void)
- cpuc->snapshot_addr = NULL;
- }
- pmu->pmu = (struct pmu) {
-+ .attr_groups = riscv_pmu_attr_groups,
- .event_init = riscv_pmu_event_init,
- .event_mapped = riscv_pmu_event_mapped,
- .event_unmapped = riscv_pmu_event_unmapped,
+++ /dev/null
-From 1664fcade482724f09a4e0cf25018b6ccebaed84 Mon Sep 17 00:00:00 2001
-From: Walker Chen <walker.chen@starfivetech.com>
-Date: Mon, 12 Jun 2023 21:21:45 +0800
-Subject: [PATCH 29/55] dmaengine: dw-axi-dmac: Drop unused print message
-
-Removed printing information which is not related to StarFive
-platform.
-
-Signed-off-by: Walker Chen <walker.chen@starfivetech.com>
----
- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -569,7 +569,7 @@ static void dw_axi_dma_set_hw_channel(st
- unsigned long reg_value, val;
-
- if (!chip->apb_regs) {
-- dev_err(chip->dev, "apb_regs not initialized\n");
-+ dev_dbg(chip->dev, "apb_regs not initialized\n");
- return;
- }
-
+++ /dev/null
-From 8339ccc47af05298612b7f01b8609f9081e9b081 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 31 May 2025 13:59:30 +0000
-Subject: [PATCH 30/55] riscv: dts: starfive: vf2: add reserved-memory for E24
-
-E24 is an rv32 RISC-V core in the JH7110 package. As the driver is now
-available for it, add reserved memory as required.
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- .../dts/starfive/jh7110-starfive-visionfive-2.dtsi | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -11,6 +11,16 @@
- aliases {
- ethernet1 = &gmac1;
- };
-+
-+ reserved-memory {
-+ #address-cells = <2>;
-+ #size-cells = <2>;
-+ ranges;
-+
-+ e24_mem: e24@c0000000 {
-+ reg = <0x0 0x6ce00000 0x0 0x1600000>;
-+ };
-+ };
- };
-
- &gmac1 {
+++ /dev/null
-From 907f68f5000522e3c78e9a5dca194f52f2ac54d3 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sun, 31 Oct 2021 17:15:58 +0100
-Subject: [PATCH 1000/1021] riscv: dts: starfive: Add JH7100 high speed UARTs
-
-Add missing device tree nodes for UART0 and UART1 on the StarFive JH7100
-SoC. UART0 is used for Bluetooth on the BeagleV Starlight and StarFive
-VisionFive V1 boards.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 26 ++++++++++++++++++++++++
- 1 file changed, 26 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -258,6 +258,32 @@
- reg = <0x0 0x11850000 0x0 0x10000>;
- };
-
-+ uart0: serial@11870000 {
-+ compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart";
-+ reg = <0x0 0x11870000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_UART0_CORE>,
-+ <&clkgen JH7100_CLK_UART0_APB>;
-+ clock-names = "baudclk", "apb_pclk";
-+ resets = <&rstgen JH7100_RSTN_UART0_APB>;
-+ interrupts = <92>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ status = "disabled";
-+ };
-+
-+ uart1: serial@11880000 {
-+ compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart";
-+ reg = <0x0 0x11880000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_UART1_CORE>,
-+ <&clkgen JH7100_CLK_UART1_APB>;
-+ clock-names = "baudclk", "apb_pclk";
-+ resets = <&rstgen JH7100_RSTN_UART1_APB>;
-+ interrupts = <93>;
-+ reg-io-width = <4>;
-+ reg-shift = <2>;
-+ status = "disabled";
-+ };
-+
- i2c0: i2c@118b0000 {
- compatible = "snps,designware-i2c";
- reg = <0x0 0x118b0000 0x0 0x10000>;
+++ /dev/null
-From 920915a0d5495b1185391cceb92f9d5b26a875e4 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Mon, 13 Sep 2021 01:18:01 +0200
-Subject: [PATCH 1001/1021] riscv: dts: starfive: Enable Bluetooth on JH7100
- boards
-
-Add pinctrl and UART nodes for the Broadcom Wifi/Bluetooth module on the
-BeagleV Starlight and StarFive VisionFive V1 boards.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- .../boot/dts/starfive/jh7100-common.dtsi | 49 +++++++++++++++++++
- 1 file changed, 49 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -289,6 +289,41 @@
- };
- };
-
-+ uart0_pins: uart0-0 {
-+ rx-pins {
-+ pinmux = <GPIOMUX(40, GPO_LOW, GPO_DISABLE,
-+ GPI_UART0_PAD_SIN)>;
-+ bias-pull-up;
-+ drive-strength = <14>;
-+ input-enable;
-+ input-schmitt-enable;
-+ };
-+ tx-pins {
-+ pinmux = <GPIOMUX(41, GPO_UART0_PAD_SOUT,
-+ GPO_ENABLE, GPI_NONE)>;
-+ bias-disable;
-+ drive-strength = <35>;
-+ input-disable;
-+ input-schmitt-disable;
-+ };
-+ cts-pins {
-+ pinmux = <GPIOMUX(39, GPO_LOW, GPO_DISABLE,
-+ GPI_UART0_PAD_CTSN)>;
-+ bias-pull-down;
-+ drive-strength = <14>;
-+ input-enable;
-+ input-schmitt-enable;
-+ };
-+ rts-pins {
-+ pinmux = <GPIOMUX(42, GPO_UART0_PAD_RTSN,
-+ GPO_ENABLE, GPI_NONE)>;
-+ bias-disable;
-+ drive-strength = <35>;
-+ input-disable;
-+ input-schmitt-disable;
-+ };
-+ };
-+
- uart3_pins: uart3-0 {
- rx-pins {
- pinmux = <GPIOMUX(13, GPO_LOW, GPO_DISABLE,
-@@ -393,6 +428,20 @@
- };
- };
-
-+&uart0 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&uart0_pins>;
-+ uart-has-rtscts;
-+ status = "okay";
-+
-+ bluetooth {
-+ compatible = "brcm,bcm4330-bt";
-+ max-speed = <4000000>;
-+ device-wakeup-gpios = <&gpio 38 GPIO_ACTIVE_HIGH>;
-+ reset-gpios = <&gpio 35 GPIO_ACTIVE_LOW>;
-+ };
-+};
-+
- &uart3 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart3_pins>;
+++ /dev/null
-From 48358693ffb4bc661996d14adcd3942a318cdb79 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Thu, 14 Oct 2021 20:56:54 +0200
-Subject: [PATCH 1002/1021] serial: 8250_dw: Add starfive,jh7100-hsuart
- compatible
-
-This adds a compatible for the high speed UARTs on the StarFive JH7100
-RISC-V SoC. Just like the regular uarts we also need to keep the input
-clocks at their default rate and rely only on the divisor in the UART.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/tty/serial/8250/8250_dw.c | 1 +
- 1 file changed, 1 insertion(+)
-
---- a/drivers/tty/serial/8250/8250_dw.c
-+++ b/drivers/tty/serial/8250/8250_dw.c
-@@ -777,6 +777,7 @@ static const struct of_device_id dw8250_
- { .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
- { .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
- { .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
-+ { .compatible = "starfive,jh7100-hsuart", .data = &dw8250_skip_set_rate_data },
- { .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
- { /* Sentinel */ }
- };
+++ /dev/null
-From bb3c832bd58bd2bca5f7f99bd19a0fe6ad3cf1a4 Mon Sep 17 00:00:00 2001
-From: Samin Guo <samin.guo@starfivetech.com>
-Date: Fri, 8 Jan 2021 03:11:04 +0800
-Subject: [PATCH 1003/1021] drivers/tty/serial/8250: update driver for JH7100
-
----
- drivers/tty/serial/8250/8250_port.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
---- a/drivers/tty/serial/8250/8250_port.c
-+++ b/drivers/tty/serial/8250/8250_port.c
-@@ -68,8 +68,16 @@ static const struct serial8250_config ua
- },
- [PORT_16550] = {
- .name = "16550",
-+#ifdef CONFIG_SOC_STARFIVE
-+ .fifo_size = 16,
-+ .tx_loadsz = 16,
-+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00,
-+ .rxtrig_bytes = {1, 4, 8, 14},
-+ .flags = UART_CAP_FIFO,
-+#else
- .fifo_size = 1,
- .tx_loadsz = 1,
-+#endif
- },
- [PORT_16550A] = {
- .name = "16550A",
+++ /dev/null
-From 995a9b41dd4e29d02ec549170f917b301d8a6d36 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sun, 3 Jul 2022 21:01:11 +0200
-Subject: [PATCH 1004/1021] power: reset: tps65086: Allow building as a module
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/power/reset/Kconfig | 2 +-
- drivers/power/reset/tps65086-restart.c | 1 +
- 2 files changed, 2 insertions(+), 1 deletion(-)
-
---- a/drivers/power/reset/Kconfig
-+++ b/drivers/power/reset/Kconfig
-@@ -217,7 +217,7 @@ config POWER_RESET_ST
- Reset support for STMicroelectronics boards.
-
- config POWER_RESET_TPS65086
-- bool "TPS65086 restart driver"
-+ tristate "TPS65086 restart driver"
- depends on MFD_TPS65086
- help
- This driver adds support for resetting the TPS65086 PMIC on restart.
---- a/drivers/power/reset/tps65086-restart.c
-+++ b/drivers/power/reset/tps65086-restart.c
-@@ -57,3 +57,4 @@ module_platform_driver(tps65086_restart_
-
- MODULE_AUTHOR("Emil Renner Berthing <kernel@esmil.dk>");
- MODULE_DESCRIPTION("TPS65086 restart driver");
-+MODULE_LICENSE("GPL v2");
+++ /dev/null
-From bedd1e49a138fc532712ae3e889af17a0dbc9417 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 17:13:22 +0100
-Subject: [PATCH 1005/1021] riscv: dts: starfive: Add StarFive JH7100 audio
- clock node
-
-Add device tree node for the audio clocks on the StarFive JH7100 RISC-V
-SoC.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 10 ++++++++++
- 1 file changed, 10 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -239,6 +239,16 @@
- };
- };
-
-+ audclk: clock-controller@10480000 {
-+ compatible = "starfive,jh7100-audclk";
-+ reg = <0x0 0x10480000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_AUDIO_SRC>,
-+ <&clkgen JH7100_CLK_AUDIO_12288>,
-+ <&clkgen JH7100_CLK_DOM7AHB_BUS>;
-+ clock-names = "audio_src", "audio_12288", "dom7ahb_bus";
-+ #clock-cells = <1>;
-+ };
-+
- clkgen: clock-controller@11800000 {
- compatible = "starfive,jh7100-clkgen";
- reg = <0x0 0x11800000 0x0 0x10000>;
+++ /dev/null
-From 052732a9fb44ab63e522a9b2949d64e2d2f2d4fc Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 19:29:25 +0100
-Subject: [PATCH 1006/1021] dt-bindings: reset: Add StarFive JH7100 audio reset
- definitions
-
-Add all resets for the StarFive JH7100 audio reset controller.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- .../dt-bindings/reset/starfive-jh7100-audio.h | 31 +++++++++++++++++++
- 1 file changed, 31 insertions(+)
- create mode 100644 include/dt-bindings/reset/starfive-jh7100-audio.h
-
---- /dev/null
-+++ b/include/dt-bindings/reset/starfive-jh7100-audio.h
-@@ -0,0 +1,31 @@
-+/* SPDX-License-Identifier: GPL-2.0 OR MIT */
-+/*
-+ * Copyright (C) 2021 Emil Renner Berthing
-+ */
-+
-+#ifndef __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__
-+#define __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__
-+
-+#define JH7100_AUDRSTN_APB_BUS 0
-+#define JH7100_AUDRSTN_I2SADC_APB 1
-+#define JH7100_AUDRSTN_I2SADC_SRST 2
-+#define JH7100_AUDRSTN_PDM_APB 3
-+#define JH7100_AUDRSTN_I2SVAD_APB 4
-+#define JH7100_AUDRSTN_I2SVAD_SRST 5
-+#define JH7100_AUDRSTN_SPDIF_APB 6
-+#define JH7100_AUDRSTN_PWMDAC_APB 7
-+#define JH7100_AUDRSTN_I2SDAC_APB 8
-+#define JH7100_AUDRSTN_I2SDAC_SRST 9
-+#define JH7100_AUDRSTN_I2S1_APB 10
-+#define JH7100_AUDRSTN_I2S1_SRST 11
-+#define JH7100_AUDRSTN_I2SDAC16K_APB 12
-+#define JH7100_AUDRSTN_I2SDAC16K_SRST 13
-+#define JH7100_AUDRSTN_DMA1P_AHB 14
-+#define JH7100_AUDRSTN_USB_APB 15
-+#define JH7100_AUDRST_USB_AXI 16
-+#define JH7100_AUDRST_USB_PWRUP_RST_N 17
-+#define JH7100_AUDRST_USB_PONRST 18
-+
-+#define JH7100_AUDRSTN_END 19
-+
-+#endif /* __DT_BINDINGS_RESET_STARFIVE_JH7100_AUDIO_H__ */
+++ /dev/null
-From 2828a23364ab4a55af817b7ab370e6fc225f025d Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 19:30:49 +0100
-Subject: [PATCH 1007/1021] reset: starfive: Add JH7100 audio reset driver
-
-The audio resets are almost identical to the system resets, there are
-just fewer of them. So factor out and export a generic probe function,
-so most of the reset controller implementation can be shared.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- MAINTAINERS | 2 +-
- drivers/reset/starfive/Kconfig | 7 ++
- drivers/reset/starfive/Makefile | 2 +
- .../starfive/reset-starfive-jh7100-audio.c | 66 +++++++++++++++++++
- .../reset/starfive/reset-starfive-jh7100.h | 16 +++++
- 5 files changed, 92 insertions(+), 1 deletion(-)
- create mode 100644 drivers/reset/starfive/reset-starfive-jh7100-audio.c
- create mode 100644 drivers/reset/starfive/reset-starfive-jh7100.h
-
---- a/MAINTAINERS
-+++ b/MAINTAINERS
-@@ -22078,7 +22078,7 @@ STARFIVE JH71X0 RESET CONTROLLER DRIVERS
- M: Emil Renner Berthing <kernel@esmil.dk>
- M: Hal Feng <hal.feng@starfivetech.com>
- S: Maintained
--F: Documentation/devicetree/bindings/reset/starfive,jh7100-reset.yaml
-+F: Documentation/devicetree/bindings/reset/starfive,jh7100-*.yaml
- F: drivers/reset/starfive/reset-starfive-jh71*
- F: include/dt-bindings/reset/starfive?jh71*.h
-
---- a/drivers/reset/starfive/Kconfig
-+++ b/drivers/reset/starfive/Kconfig
-@@ -11,6 +11,13 @@ config RESET_STARFIVE_JH7100
- help
- This enables the reset controller driver for the StarFive JH7100 SoC.
-
-+config RESET_STARFIVE_JH7100_AUDIO
-+ tristate "StarFive JH7100 Audio Reset Driver"
-+ depends on RESET_STARFIVE_JH7100
-+ default m if SOC_STARFIVE
-+ help
-+ This enables the audio reset driver for the StarFive JH7100 SoC.
-+
- config RESET_STARFIVE_JH7110
- bool "StarFive JH7110 Reset Driver"
- depends on CLK_STARFIVE_JH7110_SYS
---- a/drivers/reset/starfive/Makefile
-+++ b/drivers/reset/starfive/Makefile
-@@ -2,4 +2,6 @@
- obj-$(CONFIG_RESET_STARFIVE_JH71X0) += reset-starfive-jh71x0.o
-
- obj-$(CONFIG_RESET_STARFIVE_JH7100) += reset-starfive-jh7100.o
-+obj-$(CONFIG_RESET_STARFIVE_JH7100_AUDIO) += reset-starfive-jh7100-audio.o
-+
- obj-$(CONFIG_RESET_STARFIVE_JH7110) += reset-starfive-jh7110.o
---- /dev/null
-+++ b/drivers/reset/starfive/reset-starfive-jh7100-audio.c
-@@ -0,0 +1,66 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Audio reset driver for the StarFive JH7100 SoC
-+ *
-+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
-+ */
-+
-+#include <linux/mod_devicetable.h>
-+#include <linux/module.h>
-+#include <linux/platform_device.h>
-+
-+#include "reset-starfive-jh71x0.h"
-+
-+#include <dt-bindings/reset/starfive-jh7100-audio.h>
-+
-+/* register offsets */
-+#define JH7100_AUDRST_ASSERT0 0x00
-+#define JH7100_AUDRST_STATUS0 0x04
-+
-+/*
-+ * Writing a 1 to the n'th bit of the ASSERT register asserts
-+ * line n, and writing a 0 deasserts the same line.
-+ * Most reset lines have their status inverted so a 0 bit in the STATUS
-+ * register means the line is asserted and a 1 means it's deasserted. A few
-+ * lines don't though, so store the expected value of the status registers when
-+ * all lines are asserted.
-+ */
-+static const u32 jh7100_audrst_asserted[1] = {
-+ BIT(JH7100_AUDRST_USB_AXI) |
-+ BIT(JH7100_AUDRST_USB_PWRUP_RST_N) |
-+ BIT(JH7100_AUDRST_USB_PONRST)
-+};
-+
-+static int jh7100_audrst_probe(struct platform_device *pdev)
-+{
-+ void __iomem *base = devm_platform_ioremap_resource(pdev, 0);
-+
-+ if (IS_ERR(base))
-+ return PTR_ERR(base);
-+
-+ return reset_starfive_jh71x0_register(&pdev->dev, pdev->dev.of_node,
-+ base + JH7100_AUDRST_ASSERT0,
-+ base + JH7100_AUDRST_STATUS0,
-+ jh7100_audrst_asserted,
-+ JH7100_AUDRSTN_END,
-+ THIS_MODULE);
-+}
-+
-+static const struct of_device_id jh7100_audrst_dt_ids[] = {
-+ { .compatible = "starfive,jh7100-audrst" },
-+ { /* sentinel */ }
-+};
-+MODULE_DEVICE_TABLE(of, jh7100_audrst_dt_ids);
-+
-+static struct platform_driver jh7100_audrst_driver = {
-+ .probe = jh7100_audrst_probe,
-+ .driver = {
-+ .name = "jh7100-reset-audio",
-+ .of_match_table = jh7100_audrst_dt_ids,
-+ },
-+};
-+module_platform_driver(jh7100_audrst_driver);
-+
-+MODULE_AUTHOR("Emil Renner Berthing");
-+MODULE_DESCRIPTION("StarFive JH7100 audio reset driver");
-+MODULE_LICENSE("GPL");
---- /dev/null
-+++ b/drivers/reset/starfive/reset-starfive-jh7100.h
-@@ -0,0 +1,16 @@
-+// SPDX-License-Identifier: GPL-2.0-or-later
-+/*
-+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
-+ */
-+
-+#ifndef _RESET_STARFIVE_JH7100_H_
-+#define _RESET_STARFIVE_JH7100_H_
-+
-+#include <linux/platform_device.h>
-+
-+int reset_starfive_jh7100_generic_probe(struct platform_device *pdev,
-+ const u32 *asserted,
-+ unsigned int status_offset,
-+ unsigned int nr_resets);
-+
-+#endif
+++ /dev/null
-From a806acd4f507764123838c9620d4e581585f2099 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 20 Nov 2021 21:33:08 +0100
-Subject: [PATCH 1008/1021] riscv: dts: starfive: Add StarFive JH7100 audio
- reset node
-
-Add device tree node for the audio resets on the StarFive JH7100 RISC-V
-SoC.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 6 ++++++
- 1 file changed, 6 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -249,6 +249,12 @@
- #clock-cells = <1>;
- };
-
-+ audrst: reset-controller@10490000 {
-+ compatible = "starfive,jh7100-audrst";
-+ reg = <0x0 0x10490000 0x0 0x10000>;
-+ #reset-cells = <1>;
-+ };
-+
- clkgen: clock-controller@11800000 {
- compatible = "starfive,jh7100-clkgen";
- reg = <0x0 0x11800000 0x0 0x10000>;
+++ /dev/null
-From 174c73330839bad688b9fb2e9b6b9a2e5d74021f Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Thu, 14 Oct 2021 20:35:43 +0200
-Subject: [PATCH 1009/1021] clk: starfive: jh7100: Keep more clocks alive
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/clk/starfive/clk-starfive-jh7100.c | 19 ++++++++++---------
- 1 file changed, 10 insertions(+), 9 deletions(-)
-
---- a/drivers/clk/starfive/clk-starfive-jh7100.c
-+++ b/drivers/clk/starfive/clk-starfive-jh7100.c
-@@ -94,9 +94,9 @@ static const struct jh71x0_clk_data jh71
- JH71X0_GATE(JH7100_CLK_DMA2PNOC_AXI, "dma2pnoc_axi", 0, JH7100_CLK_CPU_AXI),
- JH71X0_GATE(JH7100_CLK_SGDMA2P_AHB, "sgdma2p_ahb", 0, JH7100_CLK_AHB_BUS),
- JH71X0__DIV(JH7100_CLK_DLA_BUS, "dla_bus", 4, JH7100_CLK_DLA_ROOT),
-- JH71X0_GATE(JH7100_CLK_DLA_AXI, "dla_axi", 0, JH7100_CLK_DLA_BUS),
-- JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", 0, JH7100_CLK_DLA_BUS),
-- JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", 0, JH7100_CLK_APB1_BUS),
-+ JH71X0_GATE(JH7100_CLK_DLA_AXI, "dla_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DLA_BUS),
-+ JH71X0_GATE(JH7100_CLK_DLANOC_AXI, "dlanoc_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DLA_BUS),
-+ JH71X0_GATE(JH7100_CLK_DLA_APB, "dla_apb", CLK_IGNORE_UNUSED, JH7100_CLK_APB1_BUS),
- JH71X0_GDIV(JH7100_CLK_VP6_CORE, "vp6_core", 0, 4, JH7100_CLK_DSP_ROOT_DIV),
- JH71X0__DIV(JH7100_CLK_VP6BUS_SRC, "vp6bus_src", 4, JH7100_CLK_DSP_ROOT),
- JH71X0_GDIV(JH7100_CLK_VP6_AXI, "vp6_axi", 0, 4, JH7100_CLK_VP6BUS_SRC),
-@@ -163,8 +163,9 @@ static const struct jh71x0_clk_data jh71
- JH71X0_GATE(JH7100_CLK_USB_AXI, "usb_axi", 0, JH7100_CLK_USB_BUS),
- JH71X0_GATE(JH7100_CLK_USBNOC_AXI, "usbnoc_axi", 0, JH7100_CLK_USB_BUS),
- JH71X0__DIV(JH7100_CLK_USBPHY_ROOTDIV, "usbphy_rootdiv", 4, JH7100_CLK_GMACUSB_ROOT),
-- JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", 0, 8, JH7100_CLK_USBPHY_ROOTDIV),
-- JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", 0, 32,
-+ JH71X0_GDIV(JH7100_CLK_USBPHY_125M, "usbphy_125m", CLK_IGNORE_UNUSED, 8,
-+ JH7100_CLK_USBPHY_ROOTDIV),
-+ JH71X0_GDIV(JH7100_CLK_USBPHY_PLLDIV25M, "usbphy_plldiv25m", CLK_IGNORE_UNUSED, 32,
- JH7100_CLK_USBPHY_ROOTDIV),
- JH71X0__MUX(JH7100_CLK_USBPHY_25M, "usbphy_25m", 0, 2,
- JH7100_CLK_OSC_SYS,
-@@ -183,11 +184,11 @@ static const struct jh71x0_clk_data jh71
- JH71X0__DIV(JH7100_CLK_VIN_BUS, "vin_bus", 8, JH7100_CLK_VIN_SRC),
- JH71X0_GATE(JH7100_CLK_VIN_AXI, "vin_axi", 0, JH7100_CLK_VIN_BUS),
- JH71X0_GATE(JH7100_CLK_VINNOC_AXI, "vinnoc_axi", 0, JH7100_CLK_VIN_BUS),
-- JH71X0_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", 0, 4, JH7100_CLK_VOUT_ROOT),
-+ JH71X0_GDIV(JH7100_CLK_VOUT_SRC, "vout_src", CLK_IGNORE_UNUSED, 4, JH7100_CLK_VOUT_ROOT),
- JH71X0__DIV(JH7100_CLK_DISPBUS_SRC, "dispbus_src", 4, JH7100_CLK_VOUTBUS_ROOT),
- JH71X0__DIV(JH7100_CLK_DISP_BUS, "disp_bus", 4, JH7100_CLK_DISPBUS_SRC),
-- JH71X0_GATE(JH7100_CLK_DISP_AXI, "disp_axi", 0, JH7100_CLK_DISP_BUS),
-- JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", 0, JH7100_CLK_DISP_BUS),
-+ JH71X0_GATE(JH7100_CLK_DISP_AXI, "disp_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DISP_BUS),
-+ JH71X0_GATE(JH7100_CLK_DISPNOC_AXI, "dispnoc_axi", CLK_IGNORE_UNUSED, JH7100_CLK_DISP_BUS),
- JH71X0_GATE(JH7100_CLK_SDIO0_AHB, "sdio0_ahb", 0, JH7100_CLK_AHB_BUS),
- JH71X0_GDIV(JH7100_CLK_SDIO0_CCLKINT, "sdio0_cclkint", 0, 24, JH7100_CLK_PERH0_SRC),
- JH71X0__INV(JH7100_CLK_SDIO0_CCLKINT_INV, "sdio0_cclkint_inv", JH7100_CLK_SDIO0_CCLKINT),
-@@ -223,7 +224,7 @@ static const struct jh71x0_clk_data jh71
- JH71X0_GATE(JH7100_CLK_AES, "aes_clk", 0, JH7100_CLK_SEC_AHB),
- JH71X0_GATE(JH7100_CLK_SHA, "sha_clk", 0, JH7100_CLK_SEC_AHB),
- JH71X0_GATE(JH7100_CLK_PKA, "pka_clk", 0, JH7100_CLK_SEC_AHB),
-- JH71X0_GATE(JH7100_CLK_TRNG_APB, "trng_apb", 0, JH7100_CLK_APB1_BUS),
-+ JH71X0_GATE(JH7100_CLK_TRNG_APB, "trng_apb", CLK_IGNORE_UNUSED, JH7100_CLK_APB1_BUS),
- JH71X0_GATE(JH7100_CLK_OTP_APB, "otp_apb", 0, JH7100_CLK_APB1_BUS),
- JH71X0_GATE(JH7100_CLK_UART0_APB, "uart0_apb", 0, JH7100_CLK_APB1_BUS),
- JH71X0_GDIV(JH7100_CLK_UART0_CORE, "uart0_core", 0, 63, JH7100_CLK_PERH1_SRC),
+++ /dev/null
-From f3e66db46e8c849e154042c35bfa22fedc03c3df Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sat, 17 Jul 2021 21:50:38 +0200
-Subject: [PATCH 1010/1021] pinctrl: starfive: Reset pinmux settings
-
-Current u-boot doesn't seem to take into account that some GPIOs are
-configured as inputs/outputs of certain peripherals on power-up. This
-means it ends up configuring some GPIOs as inputs to more than one
-peripheral which the documentation explicitly says is illegal. Similarly
-it also ends up configuring more than one GPIO as output of the same
-peripheral. While not explicitly mentioned by the documentation this
-also seems like a bad idea.
-
-The easiest way to remedy this mess is to just disconnect all GPIOs from
-peripherals and have our pinmux configuration set everything up
-properly. This, however, means that we'd disconnect the serial console
-from its pins for a while, so add a device tree property to keep
-certain GPIOs from being reset.
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- .../pinctrl/starfive,jh7100-pinctrl.yaml | 4 ++
- .../starfive/pinctrl-starfive-jh7100.c | 66 +++++++++++++++++++
- 2 files changed, 70 insertions(+)
-
---- a/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
-+++ b/Documentation/devicetree/bindings/pinctrl/starfive,jh7100-pinctrl.yaml
-@@ -88,6 +88,10 @@ properties:
- $ref: /schemas/types.yaml#/definitions/uint32
- enum: [0, 1, 2, 3, 4, 5, 6]
-
-+ starfive,keep-gpiomux:
-+ description: Keep pinmux for these GPIOs from being reset at boot.
-+ $ref: /schemas/types.yaml#/definitions/uint32-array
-+
- required:
- - compatible
- - reg
---- a/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
-+++ b/drivers/pinctrl/starfive/pinctrl-starfive-jh7100.c
-@@ -203,6 +203,10 @@ static u16 starfive_drive_strength_from_
- return (clamp(i, 14U, 63U) - 14) / 7;
- }
-
-+static bool keepmux;
-+module_param(keepmux, bool, 0644);
-+MODULE_PARM_DESC(keepmux, "Keep pinmux settings from previous boot stage");
-+
- struct starfive_pinctrl {
- struct gpio_chip gc;
- struct pinctrl_gpio_range gpios;
-@@ -1210,6 +1214,65 @@ static void starfive_disable_clock(void
- clk_disable_unprepare(data);
- }
-
-+#define GPI_END (GPI_USB_OVER_CURRENT + 1)
-+static void starfive_pinmux_reset(struct starfive_pinctrl *sfp)
-+{
-+ static const DECLARE_BITMAP(defaults, GPI_END) = {
-+ BIT_MASK(GPI_I2C0_PAD_SCK_IN) |
-+ BIT_MASK(GPI_I2C0_PAD_SDA_IN) |
-+ BIT_MASK(GPI_I2C1_PAD_SCK_IN) |
-+ BIT_MASK(GPI_I2C1_PAD_SDA_IN) |
-+ BIT_MASK(GPI_I2C2_PAD_SCK_IN) |
-+ BIT_MASK(GPI_I2C2_PAD_SDA_IN) |
-+ BIT_MASK(GPI_I2C3_PAD_SCK_IN) |
-+ BIT_MASK(GPI_I2C3_PAD_SDA_IN) |
-+ BIT_MASK(GPI_SDIO0_PAD_CARD_DETECT_N) |
-+
-+ BIT_MASK(GPI_SDIO1_PAD_CARD_DETECT_N) |
-+ BIT_MASK(GPI_SPI0_PAD_SS_IN_N) |
-+ BIT_MASK(GPI_SPI1_PAD_SS_IN_N) |
-+ BIT_MASK(GPI_SPI2_PAD_SS_IN_N) |
-+ BIT_MASK(GPI_SPI2AHB_PAD_SS_N) |
-+ BIT_MASK(GPI_SPI3_PAD_SS_IN_N),
-+
-+ BIT_MASK(GPI_UART0_PAD_SIN) |
-+ BIT_MASK(GPI_UART1_PAD_SIN) |
-+ BIT_MASK(GPI_UART2_PAD_SIN) |
-+ BIT_MASK(GPI_UART3_PAD_SIN) |
-+ BIT_MASK(GPI_USB_OVER_CURRENT)
-+ };
-+ DECLARE_BITMAP(keep, NR_GPIOS) = {};
-+ struct device_node *np = sfp->gc.parent->of_node;
-+ int len = of_property_count_u32_elems(np, "starfive,keep-gpiomux");
-+ int i;
-+
-+ for (i = 0; i < len; i++) {
-+ u32 gpio;
-+
-+ of_property_read_u32_index(np, "starfive,keep-gpiomux", i, &gpio);
-+ if (gpio < NR_GPIOS)
-+ set_bit(gpio, keep);
-+ }
-+
-+ for (i = 0; i < NR_GPIOS; i++) {
-+ if (test_bit(i, keep))
-+ continue;
-+
-+ writel_relaxed(GPO_DISABLE, sfp->base + GPON_DOEN_CFG + 8 * i);
-+ writel_relaxed(GPO_LOW, sfp->base + GPON_DOUT_CFG + 8 * i);
-+ }
-+
-+ for (i = 0; i < GPI_END; i++) {
-+ void __iomem *reg = sfp->base + GPI_CFG_OFFSET + 4 * i;
-+ u32 din = readl_relaxed(reg);
-+
-+ if (din >= 2 && din < (NR_GPIOS + 2) && test_bit(din - 2, keep))
-+ continue;
-+
-+ writel_relaxed(test_bit(i, defaults), reg);
-+ }
-+}
-+
- static int starfive_probe(struct platform_device *pdev)
- {
- struct device *dev = &pdev->dev;
-@@ -1271,6 +1334,9 @@ static int starfive_probe(struct platfor
- writel(value, sfp->padctl + IO_PADSHARE_SEL);
- }
-
-+ if (!keepmux)
-+ starfive_pinmux_reset(sfp);
-+
- value = readl(sfp->padctl + IO_PADSHARE_SEL);
- switch (value) {
- case 0:
+++ /dev/null
-From 690e2d40fe645e86dcd0ac265038426676473e19 Mon Sep 17 00:00:00 2001
-From: Matteo Croce <technoboy85@gmail.com>
-Date: Fri, 21 May 2021 03:26:38 +0200
-Subject: [PATCH 1011/1021] net: stmmac: use GFP_DMA32
-
-Signed-off-by: Matteo Croce <mcroce@microsoft.com>
----
- drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
---- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
-@@ -1460,7 +1460,7 @@ static int stmmac_init_rx_buffers(struct
- {
- struct stmmac_rx_queue *rx_q = &dma_conf->rx_queue[queue];
- struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i];
-- gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
-+ gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32);
-
- if (priv->dma_cap.host_dma_width <= 32)
- gfp |= GFP_DMA32;
-@@ -4756,7 +4756,7 @@ static inline void stmmac_rx_refill(stru
- struct stmmac_rx_queue *rx_q = &priv->dma_conf.rx_queue[queue];
- int dirty = stmmac_rx_dirty(priv, queue);
- unsigned int entry = rx_q->dirty_rx;
-- gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN);
-+ gfp_t gfp = (GFP_ATOMIC | __GFP_NOWARN | GFP_DMA32);
-
- if (priv->dma_cap.host_dma_width <= 32)
- gfp |= GFP_DMA32;
+++ /dev/null
-From e941dae591d8cd24f6758ecded9cc9741082e76d Mon Sep 17 00:00:00 2001
-From: Geert Uytterhoeven <geert@linux-m68k.org>
-Date: Thu, 27 May 2021 20:13:43 +0200
-Subject: [PATCH 1012/1021] dt-bindings: dma: dw-axi-dmac: Increase DMA channel
- limit to 16
-
-The first DMAC instance in the StarFive JH7100 SoC supports 16 DMA
-channels.
-
-FIXME Given there are more changes to the driver than just increasing
- DMAC_MAX_CHANNELS, we probably need a new compatible value, too.
-
-Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
----
- Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml | 6 +++---
- 1 file changed, 3 insertions(+), 3 deletions(-)
-
---- a/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
-+++ b/Documentation/devicetree/bindings/dma/snps,dw-axi-dmac.yaml
-@@ -57,7 +57,7 @@ properties:
-
- dma-channels:
- minimum: 1
-- maximum: 8
-+ maximum: 16
-
- resets:
- minItems: 1
-@@ -81,14 +81,14 @@ properties:
- Channel priority specifier associated with the DMA channels.
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 1
-- maxItems: 8
-+ maxItems: 16
-
- snps,block-size:
- description: |
- Channel block size specifier associated with the DMA channels.
- $ref: /schemas/types.yaml#/definitions/uint32-array
- minItems: 1
-- maxItems: 8
-+ maxItems: 16
-
- snps,axi-max-burst-len:
- description: |
+++ /dev/null
-From 38bf6380d873ebf247dde54a1b93dcfbf3ea19f6 Mon Sep 17 00:00:00 2001
-From: Samin Guo <samin.guo@starfivetech.com>
-Date: Wed, 17 Nov 2021 14:50:45 +0800
-Subject: [PATCH 1013/1021] dmaengine: dw-axi-dmac: Handle xfer start while
- non-idle
-
-Signed-off-by: Samin Guo <samin.guo@starfivetech.com>
-Signed-off-by: Curry Zhang <curry.zhang@starfivetech.com>
----
- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 +++++++++++-
- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 1 +
- 2 files changed, 12 insertions(+), 1 deletion(-)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -428,11 +428,13 @@ static void axi_chan_block_xfer_start(st
- u32 irq_mask;
- u8 lms = 0; /* Select AXI0 master for LLI fetching */
-
-+ chan->is_err = false;
- if (unlikely(axi_chan_is_hw_enable(chan))) {
- dev_err(chan2dev(chan), "%s is non-idle!\n",
- axi_chan_name(chan));
-
-- return;
-+ axi_chan_disable(chan);
-+ chan->is_err = true;
- }
-
- axi_dma_enable(chan->chip);
-@@ -1074,6 +1076,14 @@ static noinline void axi_chan_handle_err
- axi_chan_name(chan));
- goto out;
- }
-+ if (chan->is_err) {
-+ struct axi_dma_desc *desc = vd_to_axi_desc(vd);
-+
-+ axi_chan_block_xfer_start(chan, desc);
-+ chan->is_err = false;
-+ goto out;
-+ }
-+
- /* Remove the completed descriptor from issued list */
- list_del(&vd->node);
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-@@ -50,6 +50,7 @@ struct axi_dma_chan {
- struct dma_slave_config config;
- enum dma_transfer_direction direction;
- bool cyclic;
-+ bool is_err;
- /* these other elements are all protected by vc.lock */
- bool is_paused;
- };
+++ /dev/null
-From 43048e7698e0a2c0870112168ed138de4aa937cc Mon Sep 17 00:00:00 2001
-From: Samin Guo <samin.guo@starfivetech.com>
-Date: Wed, 17 Nov 2021 14:50:45 +0800
-Subject: [PATCH 1014/1021] dmaengine: dw-axi-dmac: Add StarFive JH7100 support
-
-Signed-off-by: Samin Guo <samin.guo@starfivetech.com>
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 12 ++++++++++++
- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 4 ++++
- 2 files changed, 16 insertions(+)
-
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
-@@ -723,8 +723,13 @@ static int dw_axi_dma_set_hw_desc(struct
-
- hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1);
-
-+#ifdef CONFIG_SOC_STARFIVE
-+ ctllo |= DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_DST_MSIZE_POS |
-+ DWAXIDMAC_BURST_TRANS_LEN_16 << CH_CTL_L_SRC_MSIZE_POS;
-+#else
- ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS |
- DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS;
-+#endif
- hw_desc->lli->ctl_lo = cpu_to_le32(ctllo);
-
- set_desc_src_master(hw_desc);
-@@ -1589,7 +1594,11 @@ static int dw_probe(struct platform_devi
- * Therefore, set constraint to 1024 * 4.
- */
- dw->dma.dev->dma_parms = &dw->dma_parms;
-+#ifdef CONFIG_SOC_STARFIVE
-+ dma_set_max_seg_size(&pdev->dev, DMAC_MAX_BLK_SIZE);
-+#else
- dma_set_max_seg_size(&pdev->dev, MAX_BLOCK_SIZE);
-+#endif
- platform_set_drvdata(pdev, chip);
-
- pm_runtime_enable(chip->dev);
-@@ -1674,6 +1683,9 @@ static const struct of_device_id dw_dma_
- .compatible = "intel,kmb-axi-dma",
- .data = (void *)AXI_DMA_FLAG_HAS_APB_REGS,
- }, {
-+ .compatible = "starfive,jh7100-axi-dma",
-+ .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2),
-+ }, {
- .compatible = "starfive,jh7110-axi-dma",
- .data = (void *)(AXI_DMA_FLAG_HAS_RESETS | AXI_DMA_FLAG_USE_CFG2),
- }, {
---- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h
-@@ -288,7 +288,11 @@ enum {
- #define CH_CTL_L_SRC_MAST BIT(0)
-
- /* CH_CFG_H */
-+#ifdef CONFIG_SOC_STARFIVE
-+#define CH_CFG_H_PRIORITY_POS 15
-+#else
- #define CH_CFG_H_PRIORITY_POS 17
-+#endif
- #define CH_CFG_H_DST_PER_POS 12
- #define CH_CFG_H_SRC_PER_POS 7
- #define CH_CFG_H_HS_SEL_DST_POS 4
+++ /dev/null
-From 4a5a14f6cce89d12efa90dd8e2a82e36df2ee179 Mon Sep 17 00:00:00 2001
-From: Huan Feng <huan.feng@starfivetech.com>
-Date: Fri, 8 Jan 2021 03:35:42 +0800
-Subject: [PATCH 1015/1021] hwrng: Add StarFive JH7100 Random Number Generator
- driver
-
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- drivers/char/hw_random/Kconfig | 13 ++
- drivers/char/hw_random/Makefile | 1 +
- drivers/char/hw_random/starfive-vic-rng.c | 256 ++++++++++++++++++++++
- drivers/char/hw_random/starfive-vic-rng.h | 167 ++++++++++++++
- 4 files changed, 437 insertions(+)
- create mode 100644 drivers/char/hw_random/starfive-vic-rng.c
- create mode 100644 drivers/char/hw_random/starfive-vic-rng.h
-
---- a/drivers/char/hw_random/Kconfig
-+++ b/drivers/char/hw_random/Kconfig
-@@ -323,6 +323,19 @@ config HW_RANDOM_POWERNV
-
- If unsure, say Y.
-
-+config HW_RANDOM_STARFIVE_VIC
-+ tristate "Starfive VIC Random Number Generator support"
-+ depends on HW_RANDOM && (SOC_STARFIVE || COMPILE_TEST)
-+ default SOC_STARFIVE
-+ help
-+ This driver provides kernel-side support for the Random Number
-+ Generator hardware found on Starfive VIC SoC.
-+
-+ To compile this driver as a module, choose M here: the
-+ module will be called starfive-vic-rng.
-+
-+ If unsure, say Y.
-+
- config HW_RANDOM_HISI
- tristate "Hisilicon Random Number Generator support"
- depends on ARCH_HISI || COMPILE_TEST
---- a/drivers/char/hw_random/Makefile
-+++ b/drivers/char/hw_random/Makefile
-@@ -28,6 +28,7 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon
- obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
- obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
- obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
-+obj-$(CONFIG_HW_RANDOM_STARFIVE_VIC) += starfive-vic-rng.o
- obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
- obj-$(CONFIG_HW_RANDOM_HISTB) += histb-rng.o
- obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
---- /dev/null
-+++ b/drivers/char/hw_random/starfive-vic-rng.c
-@@ -0,0 +1,256 @@
-+/*
-+ ******************************************************************************
-+ * @file starfive-vic-rng.c
-+ * @author StarFive Technology
-+ * @version V1.0
-+ * @date 08/13/2020
-+ * @brief
-+ ******************************************************************************
-+ * @copy
-+ *
-+ * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
-+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
-+ * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
-+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
-+ * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
-+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
-+ *
-+ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
-+ */
-+#include <linux/err.h>
-+#include <linux/kernel.h>
-+#include <linux/hw_random.h>
-+#include <linux/io.h>
-+#include <linux/module.h>
-+#include <linux/of.h>
-+#include <linux/platform_device.h>
-+#include <linux/interrupt.h>
-+#include <linux/random.h>
-+
-+#include "starfive-vic-rng.h"
-+
-+#define to_vic_rng(p) container_of(p, struct vic_rng, rng)
-+
-+struct vic_rng {
-+ struct device *dev;
-+ void __iomem *base;
-+ struct hwrng rng;
-+};
-+
-+static inline void vic_wait_till_idle(struct vic_rng *hrng)
-+{
-+ while(readl(hrng->base + VIC_STAT) & VIC_STAT_BUSY)
-+ ;
-+}
-+
-+static inline void vic_rng_irq_mask_clear(struct vic_rng *hrng)
-+{
-+ // clear register: ISTAT
-+ u32 data = readl(hrng->base + VIC_ISTAT);
-+ writel(data, hrng->base + VIC_ISTAT);
-+ writel(0, hrng->base + VIC_ALARM);
-+}
-+
-+static int vic_trng_cmd(struct vic_rng *hrng, u32 cmd) {
-+ int res = 0;
-+ // wait till idle
-+ vic_wait_till_idle(hrng);
-+ switch (cmd) {
-+ case VIC_CTRL_CMD_NOP:
-+ case VIC_CTRL_CMD_GEN_NOISE:
-+ case VIC_CTRL_CMD_GEN_NONCE:
-+ case VIC_CTRL_CMD_CREATE_STATE:
-+ case VIC_CTRL_CMD_RENEW_STATE:
-+ case VIC_CTRL_CMD_REFRESH_ADDIN:
-+ case VIC_CTRL_CMD_GEN_RANDOM:
-+ case VIC_CTRL_CMD_ADVANCE_STATE:
-+ case VIC_CTRL_CMD_KAT:
-+ case VIC_CTRL_CMD_ZEROIZE:
-+ writel(cmd, hrng->base + VIC_CTRL);
-+ break;
-+ default:
-+ res = -1;
-+ break;
-+ }
-+
-+ return res;
-+}
-+
-+static int vic_rng_init(struct hwrng *rng)
-+{
-+ struct vic_rng *hrng = to_vic_rng(rng);
-+
-+ // wait till idle
-+
-+ // clear register: ISTAT
-+ vic_rng_irq_mask_clear(hrng);
-+
-+ // set mission mode
-+ writel(VIC_SMODE_SECURE_EN(1), hrng->base + VIC_SMODE);
-+
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE);
-+ vic_wait_till_idle(hrng);
-+
-+ // set interrupt
-+ writel(VIC_IE_ALL, hrng->base + VIC_IE);
-+
-+ // zeroize
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
-+
-+ vic_wait_till_idle(hrng);
-+
-+ return 0;
-+}
-+
-+static irqreturn_t vic_rng_irq(int irq, void *priv)
-+{
-+ u32 status, val;
-+ struct vic_rng *hrng = (struct vic_rng *)priv;
-+
-+ /*
-+ * clearing the interrupt will also clear the error register
-+ * read error and status before clearing
-+ */
-+ status = readl(hrng->base + VIC_ISTAT);
-+
-+ if (status & VIC_ISTAT_ALARMS) {
-+ writel(VIC_ISTAT_ALARMS, hrng->base + VIC_ISTAT);
-+ val = readl(hrng->base + VIC_ALARM);
-+ if (val & VIC_ALARM_ILLEGAL_CMD_SEQ) {
-+ writel(VIC_ALARM_ILLEGAL_CMD_SEQ, hrng->base + VIC_ALARM);
-+ //dev_info(hrng->dev, "ILLEGAL CMD SEQ: LAST_CMD=0x%x\r\n",
-+ //VIC_STAT_LAST_CMD(readl(hrng->base + VIC_STAT)));
-+ } else {
-+ dev_info(hrng->dev, "Failed test: %x\r\n", val);
-+ }
-+ }
-+
-+ if (status & VIC_ISTAT_ZEROIZE) {
-+ writel(VIC_ISTAT_ZEROIZE, hrng->base + VIC_ISTAT);
-+ //dev_info(hrng->dev, "zeroized\r\n");
-+ }
-+
-+ if (status & VIC_ISTAT_KAT_COMPLETE) {
-+ writel(VIC_ISTAT_KAT_COMPLETE, hrng->base + VIC_ISTAT);
-+ //dev_info(hrng->dev, "kat_completed\r\n");
-+ }
-+
-+ if (status & VIC_ISTAT_NOISE_RDY) {
-+ writel(VIC_ISTAT_NOISE_RDY, hrng->base + VIC_ISTAT);
-+ //dev_info(hrng->dev, "noise_rdy\r\n");
-+ }
-+
-+ if (status & VIC_ISTAT_DONE) {
-+ writel(VIC_ISTAT_DONE, hrng->base + VIC_ISTAT);
-+ //dev_info(hrng->dev, "done\r\n");
-+ /*
-+ if (VIC_STAT_LAST_CMD(readl(hrng->base + VIC_STAT)) ==
-+ VIC_CTRL_CMD_GEN_RANDOM) {
-+ dev_info(hrng->dev, "Need Update Buffer\r\n");
-+ }
-+ */
-+ }
-+ vic_rng_irq_mask_clear(hrng);
-+
-+ return IRQ_HANDLED;
-+}
-+
-+static void vic_rng_cleanup(struct hwrng *rng)
-+{
-+ struct vic_rng *hrng = to_vic_rng(rng);
-+
-+ writel(0, hrng->base + VIC_CTRL);
-+}
-+
-+static int vic_rng_read(struct hwrng *rng, void *buf, size_t max, bool wait)
-+{
-+ struct vic_rng *hrng = to_vic_rng(rng);
-+
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_NOISE);
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_CREATE_STATE);
-+
-+ vic_wait_till_idle(hrng);
-+ max = min_t(size_t, max, (VIC_RAND_LEN * 4));
-+
-+ writel(0x0, hrng->base + VIC_MODE);
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_GEN_RANDOM);
-+
-+ vic_wait_till_idle(hrng);
-+ memcpy_fromio(buf, hrng->base + VIC_RAND0, max);
-+ vic_trng_cmd(hrng, VIC_CTRL_CMD_ZEROIZE);
-+
-+ vic_wait_till_idle(hrng);
-+ return max;
-+}
-+
-+static int vic_rng_probe(struct platform_device *pdev)
-+{
-+ int ret;
-+ int irq;
-+ struct vic_rng *rng;
-+ struct resource *res;
-+
-+ rng = devm_kzalloc(&pdev->dev, sizeof(*rng), GFP_KERNEL);
-+ if (!rng){
-+ return -ENOMEM;
-+ }
-+
-+ platform_set_drvdata(pdev, rng);
-+
-+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-+ rng->base = devm_ioremap_resource(&pdev->dev, res);
-+ if (IS_ERR(rng->base)){
-+ return PTR_ERR(rng->base);
-+ }
-+
-+ irq = platform_get_irq(pdev, 0);
-+ if (irq <= 0) {
-+ dev_err(&pdev->dev, "Couldn't get irq %d\n", irq);
-+ return irq;
-+ }
-+
-+ ret = devm_request_irq(&pdev->dev, irq, vic_rng_irq, 0, pdev->name,
-+ (void *)rng);
-+ if (ret) {
-+ dev_err(&pdev->dev, "Can't get interrupt working.\n");
-+ return ret;
-+ }
-+
-+ rng->rng.name = pdev->name;
-+ rng->rng.init = vic_rng_init;
-+ rng->rng.cleanup = vic_rng_cleanup;
-+ rng->rng.read = vic_rng_read;
-+
-+ rng->dev = &pdev->dev;
-+
-+ ret = devm_hwrng_register(&pdev->dev, &rng->rng);
-+ if (ret) {
-+ dev_err(&pdev->dev, "failed to register hwrng\n");
-+ return ret;
-+ }
-+
-+ dev_info(&pdev->dev, "Initialized\n");
-+
-+ return 0;
-+}
-+
-+static const struct of_device_id vic_rng_dt_ids[] = {
-+ { .compatible = "starfive,vic-rng" },
-+ { }
-+};
-+MODULE_DEVICE_TABLE(of, vic_rng_dt_ids);
-+
-+static struct platform_driver vic_rng_driver = {
-+ .probe = vic_rng_probe,
-+ .driver = {
-+ .name = "vic-rng",
-+ .of_match_table = vic_rng_dt_ids,
-+ },
-+};
-+
-+module_platform_driver(vic_rng_driver);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_AUTHOR("Huan Feng <huan.feng@starfivetech.com>");
-+MODULE_DESCRIPTION("Starfive VIC random number generator driver");
---- /dev/null
-+++ b/drivers/char/hw_random/starfive-vic-rng.h
-@@ -0,0 +1,167 @@
-+/*
-+ ******************************************************************************
-+ * @file starfive-vic-rng.h
-+ * @author StarFive Technology
-+ * @version V1.0
-+ * @date 08/13/2020
-+ * @brief
-+ ******************************************************************************
-+ * @copy
-+ *
-+ * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
-+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
-+ * TIME. AS A RESULT, STARFIVE SHALL NOT BE HELD LIABLE FOR ANY
-+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
-+ * FROM THE CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
-+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
-+ *
-+ * COPYRIGHT 2020 Shanghai StarFive Technology Co., Ltd.
-+ */
-+
-+#define VIC_CTRL 0x00
-+#define VIC_MODE 0x04
-+#define VIC_SMODE 0x08
-+#define VIC_STAT 0x0C
-+#define VIC_IE 0x10
-+#define VIC_ISTAT 0x14
-+#define VIC_ALARM 0x18
-+#define VIC_BUILD_ID 0x1C
-+#define VIC_FEATURES 0x20
-+#define VIC_RAND0 0x24
-+#define VIC_NPA_DATA0 0x34
-+#define VIC_SEED0 0x74
-+#define VIC_IA_RDATA 0xA4
-+#define VIC_IA_WDATA 0xA8
-+#define VIC_IA_ADDR 0xAC
-+#define VIC_IA_CMD 0xB0
-+
-+/* CTRL */
-+#define VIC_CTRL_CMD_NOP 0
-+#define VIC_CTRL_CMD_GEN_NOISE 1
-+#define VIC_CTRL_CMD_GEN_NONCE 2
-+#define VIC_CTRL_CMD_CREATE_STATE 3
-+#define VIC_CTRL_CMD_RENEW_STATE 4
-+#define VIC_CTRL_CMD_REFRESH_ADDIN 5
-+#define VIC_CTRL_CMD_GEN_RANDOM 6
-+#define VIC_CTRL_CMD_ADVANCE_STATE 7
-+#define VIC_CTRL_CMD_KAT 8
-+#define VIC_CTRL_CMD_ZEROIZE 15
-+
-+/* MODE */
-+#define _VIC_MODE_ADDIN_PRESENT 4
-+#define _VIC_MODE_PRED_RESIST 3
-+#define _VIC_MODE_KAT_SEL 2
-+#define _VIC_MODE_KAT_VEC 1
-+#define _VIC_MODE_SEC_ALG 0
-+
-+#define VIC_MODE_ADDIN_PRESENT (1UL << _VIC_MODE_ADDIN_PRESENT)
-+#define VIC_MODE_PRED_RESIST (1UL << _VIC_MODE_PRED_RESIST)
-+#define VIC_MODE_KAT_SEL (1UL << _VIC_MODE_KAT_SEL)
-+#define VIC_MODE_KAT_VEC (1UL << _VIC_MODE_KAT_VEC)
-+#define VIC_MODE_SEC_ALG (1UL << _VIC_MODE_SEC_ALG)
-+
-+/* SMODE */
-+#define _VIC_SMODE_MAX_REJECTS 2
-+#define _VIC_SMODE_SECURE_EN 1
-+#define _VIC_SMODE_NONCE 0
-+
-+#define VIC_SMODE_MAX_REJECTS(x) ((x) << _VIC_SMODE_MAX_REJECTS)
-+#define VIC_SMODE_SECURE_EN(x) ((x) << _VIC_SMODE_SECURE_EN)
-+#define VIC_SMODE_NONCE (1UL << _VIC_SMODE_NONCE)
-+
-+/* STAT */
-+#define _VIC_STAT_BUSY 31
-+#define _VIC_STAT_DRBG_STATE 7
-+#define _VIC_STAT_SECURE 6
-+#define _VIC_STAT_NONCE_MODE 5
-+#define _VIC_STAT_SEC_ALG 4
-+#define _VIC_STAT_LAST_CMD 0
-+
-+#define VIC_STAT_BUSY (1UL << _VIC_STAT_BUSY)
-+#define VIC_STAT_DRBG_STATE (1UL << _VIC_STAT_DRBG_STATE)
-+#define VIC_STAT_SECURE (1UL << _VIC_STAT_SECURE)
-+#define VIC_STAT_NONCE_MODE (1UL << _VIC_STAT_NONCE_MODE)
-+#define VIC_STAT_SEC_ALG (1UL << _VIC_STAT_SEC_ALG)
-+#define VIC_STAT_LAST_CMD(x) (((x) >> _VIC_STAT_LAST_CMD) & 0xF)
-+
-+/* IE */
-+#define _VIC_IE_GLBL 31
-+#define _VIC_IE_DONE 4
-+#define _VIC_IE_ALARMS 3
-+#define _VIC_IE_NOISE_RDY 2
-+#define _VIC_IE_KAT_COMPLETE 1
-+#define _VIC_IE_ZEROIZE 0
-+
-+#define VIC_IE_GLBL (1UL << _VIC_IE_GLBL)
-+#define VIC_IE_DONE (1UL << _VIC_IE_DONE)
-+#define VIC_IE_ALARMS (1UL << _VIC_IE_ALARMS)
-+#define VIC_IE_NOISE_RDY (1UL << _VIC_IE_NOISE_RDY)
-+#define VIC_IE_KAT_COMPLETE (1UL << _VIC_IE_KAT_COMPLETE)
-+#define VIC_IE_ZEROIZE (1UL << _VIC_IE_ZEROIZE)
-+#define VIC_IE_ALL (VIC_IE_GLBL | VIC_IE_DONE | VIC_IE_ALARMS | \
-+ VIC_IE_NOISE_RDY | VIC_IE_KAT_COMPLETE | VIC_IE_ZEROIZE)
-+
-+/* ISTAT */
-+#define _VIC_ISTAT_DONE 4
-+#define _VIC_ISTAT_ALARMS 3
-+#define _VIC_ISTAT_NOISE_RDY 2
-+#define _VIC_ISTAT_KAT_COMPLETE 1
-+#define _VIC_ISTAT_ZEROIZE 0
-+
-+#define VIC_ISTAT_DONE (1UL << _VIC_ISTAT_DONE)
-+#define VIC_ISTAT_ALARMS (1UL << _VIC_ISTAT_ALARMS)
-+#define VIC_ISTAT_NOISE_RDY (1UL << _VIC_ISTAT_NOISE_RDY)
-+#define VIC_ISTAT_KAT_COMPLETE (1UL << _VIC_ISTAT_KAT_COMPLETE)
-+#define VIC_ISTAT_ZEROIZE (1UL << _VIC_ISTAT_ZEROIZE)
-+
-+/* ALARMS */
-+#define VIC_ALARM_ILLEGAL_CMD_SEQ (1UL << 4)
-+#define VIC_ALARM_FAILED_TEST_ID_OK 0
-+#define VIC_ALARM_FAILED_TEST_ID_KAT_STAT 1
-+#define VIC_ALARM_FAILED_TEST_ID_KAT 2
-+#define VIC_ALARM_FAILED_TEST_ID_MONOBIT 3
-+#define VIC_ALARM_FAILED_TEST_ID_RUN 4
-+#define VIC_ALARM_FAILED_TEST_ID_LONGRUN 5
-+#define VIC_ALARM_FAILED_TEST_ID_AUTOCORRELATION 6
-+#define VIC_ALARM_FAILED_TEST_ID_POKER 7
-+#define VIC_ALARM_FAILED_TEST_ID_REPETITION_COUNT 8
-+#define VIC_ALARM_FAILED_TEST_ID_ADAPATIVE_PROPORTION 9
-+
-+/* BUILD_ID */
-+#define VIC_BUILD_ID_STEPPING(x) (((x) >> 28) & 0xF)
-+#define VIC_BUILD_ID_EPN(x) ((x) & 0xFFFF)
-+
-+/* FEATURES */
-+#define VIC_FEATURES_AES_256(x) (((x) >> 9) & 1)
-+#define VIC_FEATURES_EXTRA_PS_PRESENT(x) (((x) >> 8) & 1)
-+#define VIC_FEATURES_DIAG_LEVEL_NS(x) (((x) >> 7) & 1)
-+#define VIC_FEATURES_DIAG_LEVEL_CLP800(x) (((x) >> 4) & 7)
-+#define VIC_FEATURES_DIAG_LEVEL_ST_HLT(x) (((x) >> 1) & 7)
-+#define VIC_FEATURES_SECURE_RST_STATE(x) ((x) & 1)
-+
-+/* IA_CMD */
-+#define VIC_IA_CMD_GO (1UL << 31)
-+#define VIC_IA_CMD_WR (1)
-+
-+#define _VIC_SMODE_MAX_REJECTS_MASK 255UL
-+#define _VIC_SMODE_SECURE_EN_MASK 1UL
-+#define _VIC_SMODE_NONCE_MASK 1UL
-+#define _VIC_MODE_SEC_ALG_MASK 1UL
-+#define _VIC_MODE_ADDIN_PRESENT_MASK 1UL
-+#define _VIC_MODE_PRED_RESIST_MASK 1UL
-+
-+#define VIC_SMODE_SET_MAX_REJECTS(y, x) (((y) & ~(_VIC_SMODE_MAX_REJECTS_MASK << _VIC_SMODE_MAX_REJECTS)) | ((x) << _VIC_SMODE_MAX_REJECTS))
-+#define VIC_SMODE_SET_SECURE_EN(y, x) (((y) & ~(_VIC_SMODE_SECURE_EN_MASK << _VIC_SMODE_SECURE_EN)) | ((x) << _VIC_SMODE_SECURE_EN))
-+#define VIC_SMODE_SET_NONCE(y, x) (((y) & ~(_VIC_SMODE_NONCE_MASK << _VIC_SMODE_NONCE)) | ((x) << _VIC_SMODE_NONCE))
-+#define VIC_SMODE_GET_MAX_REJECTS(x) (((x) >> _VIC_SMODE_MAX_REJECTS) & _VIC_SMODE_MAX_REJECTS_MASK)
-+#define VIC_SMODE_GET_SECURE_EN(x) (((x) >> _VIC_SMODE_SECURE_EN) & _VIC_SMODE_SECURE_EN_MASK)
-+#define VIC_SMODE_GET_NONCE(x) (((x) >> _VIC_SMODE_NONCE) & _VIC_SMODE_NONCE_MASK)
-+
-+#define VIC_MODE_SET_SEC_ALG(y, x) (((y) & ~(_VIC_MODE_SEC_ALG_MASK << _VIC_MODE_SEC_ALG)) | ((x) << _VIC_MODE_SEC_ALG))
-+#define VIC_MODE_SET_PRED_RESIST(y, x) (((y) & ~(_VIC_MODE_PRED_RESIST_MASK << _VIC_MODE_PRED_RESIST)) | ((x) << _VIC_MODE_PRED_RESIST))
-+#define VIC_MODE_SET_ADDIN_PRESENT(y, x) (((y) & ~(_VIC_MODE_ADDIN_PRESENT_MASK << _VIC_MODE_ADDIN_PRESENT)) | ((x) << _VIC_MODE_ADDIN_PRESENT))
-+#define VIC_MODE_GET_SEC_ALG(x) (((x) >> _VIC_MODE_SEC_ALG) & _VIC_MODE_SEC_ALG_MASK)
-+#define VIC_MODE_GET_PRED_RESIST(x) (((x) >> _VIC_MODE_PRED_RESIST) & _VIC_MODE_PRED_RESIST_MASK)
-+#define VIC_MODE_GET_ADDIN_PRESENT(x) (((x) >> _VIC_MODE_ADDIN_PRESENT) & _VIC_MODE_ADDIN_PRESENT_MASK)
-+
-+#define VIC_RAND_LEN 4
+++ /dev/null
-From d3bef81bd427caf4cbf7ecef64f0268a6ac8ce52 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 22 Jul 2023 15:59:02 +0200
-Subject: [PATCH 1016/1021] usb: cdns3: starfive: Simplify mode init
-
-The syscon regmap and offset to the USB mode register is only used at
-probe time, so there is no need to store it in the device data. Just get
-the regmap pointer in the cdns_mode_init() function where it is needed.
-Also this function never uses the platform device, so just pass the
-device pointer directly.
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- drivers/usb/cdns3/cdns3-starfive.c | 51 ++++++++++++------------------
- 1 file changed, 21 insertions(+), 30 deletions(-)
-
---- a/drivers/usb/cdns3/cdns3-starfive.c
-+++ b/drivers/usb/cdns3/cdns3-starfive.c
-@@ -34,46 +34,45 @@
-
- struct cdns_starfive {
- struct device *dev;
-- struct regmap *stg_syscon;
- struct reset_control *resets;
- struct clk_bulk_data *clks;
- int num_clks;
-- u32 stg_usb_mode;
- };
-
--static void cdns_mode_init(struct platform_device *pdev,
-- struct cdns_starfive *data)
-+static int cdns_mode_init(struct device *dev, struct cdns_starfive *data)
- {
-+ struct regmap *syscon;
-+ unsigned int usb_mode;
- enum usb_dr_mode mode;
-
-- regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
-+ syscon = syscon_regmap_lookup_by_phandle_args(dev->of_node,
-+ "starfive,stg-syscon", 1, &usb_mode);
-+ if (IS_ERR(syscon))
-+ return dev_err_probe(dev, PTR_ERR(syscon),
-+ "Failed to parse starfive,stg-syscon\n");
-+
-+ regmap_update_bits(syscon, usb_mode,
- USB_MISC_CFG_MASK,
- USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE);
-
- /* dr mode setting */
-- mode = usb_get_dr_mode(&pdev->dev);
-+ mode = usb_get_dr_mode(dev);
-
- switch (mode) {
- case USB_DR_MODE_HOST:
-- regmap_update_bits(data->stg_syscon,
-- data->stg_usb_mode,
-- USB_STRAP_MASK,
-- USB_STRAP_HOST);
-- regmap_update_bits(data->stg_syscon,
-- data->stg_usb_mode,
-- USB_SUSPENDM_MASK,
-- USB_SUSPENDM_HOST);
-+ regmap_update_bits(syscon, usb_mode, USB_STRAP_MASK, USB_STRAP_HOST);
-+ regmap_update_bits(syscon, usb_mode, USB_SUSPENDM_MASK, USB_SUSPENDM_HOST);
- break;
-
- case USB_DR_MODE_PERIPHERAL:
-- regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
-- USB_STRAP_MASK, USB_STRAP_DEVICE);
-- regmap_update_bits(data->stg_syscon, data->stg_usb_mode,
-- USB_SUSPENDM_MASK, 0);
-+ regmap_update_bits(syscon, usb_mode, USB_STRAP_MASK, USB_STRAP_DEVICE);
-+ regmap_update_bits(syscon, usb_mode, USB_SUSPENDM_MASK, 0);
- break;
- default:
- break;
- }
-+
-+ return 0;
- }
-
- static int cdns_clk_rst_init(struct cdns_starfive *data)
-@@ -108,7 +107,6 @@ static int cdns_starfive_probe(struct pl
- {
- struct device *dev = &pdev->dev;
- struct cdns_starfive *data;
-- unsigned int args;
- int ret;
-
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-@@ -117,16 +115,6 @@ static int cdns_starfive_probe(struct pl
-
- data->dev = dev;
-
-- data->stg_syscon =
-- syscon_regmap_lookup_by_phandle_args(pdev->dev.of_node,
-- "starfive,stg-syscon", 1, &args);
--
-- if (IS_ERR(data->stg_syscon))
-- return dev_err_probe(dev, PTR_ERR(data->stg_syscon),
-- "Failed to parse starfive,stg-syscon\n");
--
-- data->stg_usb_mode = args;
--
- data->num_clks = devm_clk_bulk_get_all(data->dev, &data->clks);
- if (data->num_clks < 0)
- return dev_err_probe(data->dev, -ENODEV,
-@@ -137,7 +125,10 @@ static int cdns_starfive_probe(struct pl
- return dev_err_probe(data->dev, PTR_ERR(data->resets),
- "Failed to get resets");
-
-- cdns_mode_init(pdev, data);
-+ ret = cdns_mode_init(dev, data);
-+ if (ret)
-+ return ret;
-+
- ret = cdns_clk_rst_init(data);
- if (ret)
- return ret;
+++ /dev/null
-From 38b62b73015e3c843ff05400cd972683a7f3af04 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 22 Jul 2023 16:18:24 +0200
-Subject: [PATCH 1017/1021] usb: cdns3: starfive: Don't store device
- backpointer
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- drivers/usb/cdns3/cdns3-starfive.c | 37 ++++++++++++------------------
- 1 file changed, 15 insertions(+), 22 deletions(-)
-
---- a/drivers/usb/cdns3/cdns3-starfive.c
-+++ b/drivers/usb/cdns3/cdns3-starfive.c
-@@ -33,7 +33,6 @@
- #define USB_REFCLK_MODE BIT(23)
-
- struct cdns_starfive {
-- struct device *dev;
- struct reset_control *resets;
- struct clk_bulk_data *clks;
- int num_clks;
-@@ -49,7 +48,7 @@ static int cdns_mode_init(struct device
- "starfive,stg-syscon", 1, &usb_mode);
- if (IS_ERR(syscon))
- return dev_err_probe(dev, PTR_ERR(syscon),
-- "Failed to parse starfive,stg-syscon\n");
-+ "failed to parse starfive,stg-syscon\n");
-
- regmap_update_bits(syscon, usb_mode,
- USB_MISC_CFG_MASK,
-@@ -75,18 +74,17 @@ static int cdns_mode_init(struct device
- return 0;
- }
-
--static int cdns_clk_rst_init(struct cdns_starfive *data)
-+static int cdns_clk_rst_init(struct device *dev, struct cdns_starfive *data)
- {
- int ret;
-
- ret = clk_bulk_prepare_enable(data->num_clks, data->clks);
- if (ret)
-- return dev_err_probe(data->dev, ret,
-- "failed to enable clocks\n");
-+ return dev_err_probe(dev, ret, "failed to enable clocks\n");
-
- ret = reset_control_deassert(data->resets);
- if (ret) {
-- dev_err(data->dev, "failed to reset clocks\n");
-+ dev_err(dev, "failed to reset clocks\n");
- goto err_clk_init;
- }
-
-@@ -97,7 +95,7 @@ err_clk_init:
- return ret;
- }
-
--static void cdns_clk_rst_deinit(struct cdns_starfive *data)
-+static void cdns_clk_rst_deinit(struct device *dev, struct cdns_starfive *data)
- {
- reset_control_assert(data->resets);
- clk_bulk_disable_unprepare(data->num_clks, data->clks);
-@@ -113,31 +111,26 @@ static int cdns_starfive_probe(struct pl
- if (!data)
- return -ENOMEM;
-
-- data->dev = dev;
--
-- data->num_clks = devm_clk_bulk_get_all(data->dev, &data->clks);
-+ data->num_clks = devm_clk_bulk_get_all(dev, &data->clks);
- if (data->num_clks < 0)
-- return dev_err_probe(data->dev, -ENODEV,
-- "Failed to get clocks\n");
-+ return dev_err_probe(dev, -ENODEV, "failed to get clocks\n");
-
-- data->resets = devm_reset_control_array_get_exclusive(data->dev);
-+ data->resets = devm_reset_control_array_get_exclusive(dev);
- if (IS_ERR(data->resets))
-- return dev_err_probe(data->dev, PTR_ERR(data->resets),
-- "Failed to get resets");
-+ return dev_err_probe(dev, PTR_ERR(data->resets), "failed to get resets\n");
-
- ret = cdns_mode_init(dev, data);
- if (ret)
- return ret;
-
-- ret = cdns_clk_rst_init(data);
-+ ret = cdns_clk_rst_init(dev, data);
- if (ret)
- return ret;
-
- ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
- if (ret) {
-- dev_err(dev, "Failed to create children\n");
-- cdns_clk_rst_deinit(data);
-- return ret;
-+ cdns_clk_rst_deinit(dev, data);
-+ return dev_err_probe(dev, ret, "failed to create children\n");
- }
-
- device_set_wakeup_capable(dev, true);
-@@ -167,7 +160,7 @@ static void cdns_starfive_remove(struct
-
- pm_runtime_disable(dev);
- pm_runtime_put_noidle(dev);
-- cdns_clk_rst_deinit(data);
-+ cdns_clk_rst_deinit(dev, data);
- platform_set_drvdata(pdev, NULL);
- }
-
-@@ -193,14 +186,14 @@ static int cdns_starfive_resume(struct d
- {
- struct cdns_starfive *data = dev_get_drvdata(dev);
-
-- return cdns_clk_rst_init(data);
-+ return cdns_clk_rst_init(dev, data);
- }
-
- static int cdns_starfive_suspend(struct device *dev)
- {
- struct cdns_starfive *data = dev_get_drvdata(dev);
-
-- cdns_clk_rst_deinit(data);
-+ cdns_clk_rst_deinit(dev, data);
-
- return 0;
- }
+++ /dev/null
-From eae127ccbe02ba20e4eb86081268205f7f40b8fc Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 22 Jul 2023 16:21:04 +0200
-Subject: [PATCH 1018/1021] usb: cdns3: starfive: Add StarFive JH7100 support
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- drivers/usb/cdns3/cdns3-starfive.c | 46 ++++++++++++++++++------------
- 1 file changed, 28 insertions(+), 18 deletions(-)
-
---- a/drivers/usb/cdns3/cdns3-starfive.c
-+++ b/drivers/usb/cdns3/cdns3-starfive.c
-@@ -20,17 +20,17 @@
- #include <linux/usb/otg.h>
- #include "core.h"
-
--#define USB_STRAP_HOST BIT(17)
--#define USB_STRAP_DEVICE BIT(18)
--#define USB_STRAP_MASK GENMASK(18, 16)
--
--#define USB_SUSPENDM_HOST BIT(19)
--#define USB_SUSPENDM_MASK BIT(19)
--
--#define USB_MISC_CFG_MASK GENMASK(23, 20)
--#define USB_SUSPENDM_BYPS BIT(20)
--#define USB_PLL_EN BIT(22)
--#define USB_REFCLK_MODE BIT(23)
-+#define JH7110_STRAP_HOST BIT(17)
-+#define JH7110_STRAP_DEVICE BIT(18)
-+#define JH7110_STRAP_MASK GENMASK(18, 16)
-+
-+#define JH7110_SUSPENDM_HOST BIT(19)
-+#define JH7110_SUSPENDM_MASK BIT(19)
-+
-+#define JH7110_MISC_CFG_MASK GENMASK(23, 20)
-+#define JH7110_SUSPENDM_BYPS BIT(20)
-+#define JH7110_PLL_EN BIT(22)
-+#define JH7110_REFCLK_MODE BIT(23)
-
- struct cdns_starfive {
- struct reset_control *resets;
-@@ -38,7 +38,14 @@ struct cdns_starfive {
- int num_clks;
- };
-
--static int cdns_mode_init(struct device *dev, struct cdns_starfive *data)
-+typedef int (cdns_starfive_mode_init_t)(struct device *dev, struct cdns_starfive *data);
-+
-+static int cdns_jh7100_mode_init(struct device *dev, struct cdns_starfive *data)
-+{
-+ return 0;
-+}
-+
-+static int cdns_jh7110_mode_init(struct device *dev, struct cdns_starfive *data)
- {
- struct regmap *syscon;
- unsigned int usb_mode;
-@@ -51,21 +58,21 @@ static int cdns_mode_init(struct device
- "failed to parse starfive,stg-syscon\n");
-
- regmap_update_bits(syscon, usb_mode,
-- USB_MISC_CFG_MASK,
-- USB_SUSPENDM_BYPS | USB_PLL_EN | USB_REFCLK_MODE);
-+ JH7110_MISC_CFG_MASK,
-+ JH7110_SUSPENDM_BYPS | JH7110_PLL_EN | JH7110_REFCLK_MODE);
-
- /* dr mode setting */
- mode = usb_get_dr_mode(dev);
-
- switch (mode) {
- case USB_DR_MODE_HOST:
-- regmap_update_bits(syscon, usb_mode, USB_STRAP_MASK, USB_STRAP_HOST);
-- regmap_update_bits(syscon, usb_mode, USB_SUSPENDM_MASK, USB_SUSPENDM_HOST);
-+ regmap_update_bits(syscon, usb_mode, JH7110_STRAP_MASK, JH7110_STRAP_HOST);
-+ regmap_update_bits(syscon, usb_mode, JH7110_SUSPENDM_MASK, JH7110_SUSPENDM_HOST);
- break;
-
- case USB_DR_MODE_PERIPHERAL:
-- regmap_update_bits(syscon, usb_mode, USB_STRAP_MASK, USB_STRAP_DEVICE);
-- regmap_update_bits(syscon, usb_mode, USB_SUSPENDM_MASK, 0);
-+ regmap_update_bits(syscon, usb_mode, JH7110_STRAP_MASK, JH7110_STRAP_DEVICE);
-+ regmap_update_bits(syscon, usb_mode, JH7110_SUSPENDM_MASK, 0);
- break;
- default:
- break;
-@@ -105,6 +112,7 @@ static int cdns_starfive_probe(struct pl
- {
- struct device *dev = &pdev->dev;
- struct cdns_starfive *data;
-+ cdns_starfive_mode_init_t *mode_init;
- int ret;
-
- data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
-@@ -119,7 +127,8 @@ static int cdns_starfive_probe(struct pl
- if (IS_ERR(data->resets))
- return dev_err_probe(dev, PTR_ERR(data->resets), "failed to get resets\n");
-
-- ret = cdns_mode_init(dev, data);
-+ mode_init = device_get_match_data(dev);
-+ ret = mode_init(dev, data);
- if (ret)
- return ret;
-
-@@ -207,7 +216,8 @@ static const struct dev_pm_ops cdns_star
- };
-
- static const struct of_device_id cdns_starfive_of_match[] = {
-- { .compatible = "starfive,jh7110-usb", },
-+ { .compatible = "starfive,jh7100-usb", .data = cdns_jh7100_mode_init },
-+ { .compatible = "starfive,jh7110-usb", .data = cdns_jh7110_mode_init },
- { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(of, cdns_starfive_of_match);
+++ /dev/null
-From e73da6a4dc3f127d45e26d68ee051199c1fc2bb9 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 22 Jul 2023 16:36:17 +0200
-Subject: [PATCH 1019/1021] riscv: dts: starfive: Add JH7100 USB node
-
-Add the device tree node for the USB 3.0 peripheral on the
-StarFive JH7100 SoC.
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- .../boot/dts/starfive/jh7100-common.dtsi | 5 ++++
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 26 +++++++++++++++++++
- 2 files changed, 31 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -447,3 +447,8 @@
- pinctrl-0 = <&uart3_pins>;
- status = "okay";
- };
-+
-+&usb3 {
-+ dr_mode = "host";
-+ status = "okay";
-+};
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -255,6 +255,32 @@
- #reset-cells = <1>;
- };
-
-+ usb3: usb@104c0000 {
-+ compatible = "starfive,jh7100-usb";
-+ ranges = <0x0 0x0 0x104c0000 0x100000>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ clocks = <&audclk JH7100_AUDCLK_USB_LPM>,
-+ <&audclk JH7100_AUDCLK_USB_STB>,
-+ <&clkgen JH7100_CLK_USB_AXI>,
-+ <&clkgen JH7100_CLK_USBNOC_AXI>;
-+ clock-names = "lpm", "stb", "axi", "nocaxi";
-+ resets = <&rstgen JH7100_RSTN_USB_AXI>,
-+ <&rstgen JH7100_RSTN_USBNOC_AXI>;
-+ reset-names = "axi", "nocaxi";
-+ status = "disabled";
-+
-+ usb_cdns3: usb@0 {
-+ compatible = "cdns,usb3";
-+ reg = <0x00000 0x10000>,
-+ <0x10000 0x10000>,
-+ <0x20000 0x10000>;
-+ reg-names = "otg", "xhci", "dev";
-+ interrupts = <44>, <52>, <43>;
-+ interrupt-names = "host", "peripheral", "otg";
-+ };
-+ };
-+
- clkgen: clock-controller@11800000 {
- compatible = "starfive,jh7100-clkgen";
- reg = <0x0 0x11800000 0x0 0x10000>;
+++ /dev/null
-From 8deff65d2d7ffea00231ec592d956aebf7de0852 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <emil.renner.berthing@canonical.com>
-Date: Sat, 22 Jul 2023 18:50:49 +0200
-Subject: [PATCH 1020/1021] usb: cdns3: starfive: Initialize JH7100 host mode
-
-These settings are directly copied from StarFive's port of u-boot
-for the JH7100:
-
- /* config strap */
- _SET_SYSCON_REG_SCFG_usb0_mode_strap(0x2);
- _SET_SYSCON_REG_SCFG_usb7_PLL_EN(0x1);
- _SET_SYSCON_REG_SCFG_usb7_U3_EQ_EN(0x1);
- _SET_SYSCON_REG_SCFG_usb7_U3_SSRX_SEL(0x1);
- _SET_SYSCON_REG_SCFG_usb7_U3_SSTX_SEL(0x1);
- _SET_SYSCON_REG_SCFG_usb3_utmi_iddig(0x1);
-
-Signed-off-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
----
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 6 ++++
- drivers/usb/cdns3/cdns3-starfive.c | 43 ++++++++++++++++++++++++
- 2 files changed, 49 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -255,6 +255,11 @@
- #reset-cells = <1>;
- };
-
-+ sysaudio: syscon@104a0000 {
-+ compatible = "starfive,jh7100-sysaudio", "syscon";
-+ reg = <0x0 0x104a0000 0x0 0x10000>;
-+ };
-+
- usb3: usb@104c0000 {
- compatible = "starfive,jh7100-usb";
- ranges = <0x0 0x0 0x104c0000 0x100000>;
-@@ -268,6 +273,7 @@
- resets = <&rstgen JH7100_RSTN_USB_AXI>,
- <&rstgen JH7100_RSTN_USBNOC_AXI>;
- reset-names = "axi", "nocaxi";
-+ starfive,syscon = <&sysaudio>;
- status = "disabled";
-
- usb_cdns3: usb@0 {
---- a/drivers/usb/cdns3/cdns3-starfive.c
-+++ b/drivers/usb/cdns3/cdns3-starfive.c
-@@ -20,6 +20,19 @@
- #include <linux/usb/otg.h>
- #include "core.h"
-
-+#define JH7100_USB0 0x20
-+#define JH7100_USB0_MODE_STRAP_MASK GENMASK(2, 0)
-+#define JH7100_USB0_MODE_STRAP_HOST 2
-+
-+#define JH7100_USB3 0x2c
-+#define JH7100_USB3_UTMI_IDDIG BIT(21)
-+
-+#define JH7100_USB7 0x3c
-+#define JH7100_USB7_SSRX_SEL BIT(18)
-+#define JH7100_USB7_SSTX_SEL BIT(19)
-+#define JH7100_USB7_PLL_EN BIT(23)
-+#define JH7100_USB7_EQ_EN BIT(25)
-+
- #define JH7110_STRAP_HOST BIT(17)
- #define JH7110_STRAP_DEVICE BIT(18)
- #define JH7110_STRAP_MASK GENMASK(18, 16)
-@@ -42,6 +55,36 @@ typedef int (cdns_starfive_mode_init_t)(
-
- static int cdns_jh7100_mode_init(struct device *dev, struct cdns_starfive *data)
- {
-+ struct regmap *syscon;
-+ enum usb_dr_mode mode;
-+
-+ syscon = syscon_regmap_lookup_by_phandle(dev->of_node, "starfive,syscon");
-+ if (IS_ERR(syscon))
-+ return dev_err_probe(dev, PTR_ERR(syscon),
-+ "failed to get starfive,syscon\n");
-+
-+ /* dr mode setting */
-+ mode = usb_get_dr_mode(dev);
-+
-+ switch (mode) {
-+ case USB_DR_MODE_HOST:
-+ regmap_update_bits(syscon, JH7100_USB0,
-+ JH7100_USB0_MODE_STRAP_MASK, JH7100_USB0_MODE_STRAP_HOST);
-+ regmap_update_bits(syscon, JH7100_USB7,
-+ JH7100_USB7_PLL_EN, JH7100_USB7_PLL_EN);
-+ regmap_update_bits(syscon, JH7100_USB7,
-+ JH7100_USB7_EQ_EN, JH7100_USB7_EQ_EN);
-+ regmap_update_bits(syscon, JH7100_USB7,
-+ JH7100_USB7_SSRX_SEL, JH7100_USB7_SSRX_SEL);
-+ regmap_update_bits(syscon, JH7100_USB7,
-+ JH7100_USB7_SSTX_SEL, JH7100_USB7_SSTX_SEL);
-+ regmap_update_bits(syscon, JH7100_USB3,
-+ JH7100_USB3_UTMI_IDDIG, JH7100_USB3_UTMI_IDDIG);
-+ break;
-+ default:
-+ break;
-+ }
-+
- return 0;
- }
-
+++ /dev/null
-From a861bf8cf26216da57b4886ecf48222e01e4fba9 Mon Sep 17 00:00:00 2001
-From: Emil Renner Berthing <kernel@esmil.dk>
-Date: Sun, 31 Oct 2021 17:15:58 +0100
-Subject: [PATCH 1021/1021] riscv: dts: Add full JH7100, Starlight and
- VisionFive support
-
-Based on the device tree in https://github.com/starfive-tech/u-boot/
-with contributions from:
-yanhong.wang <yanhong.wang@starfivetech.com>
-Huan.Feng <huan.feng@starfivetech.com>
-ke.zhu <ke.zhu@starfivetech.com>
-yiming.li <yiming.li@starfivetech.com>
-jack.zhu <jack.zhu@starfivetech.com>
-Samin Guo <samin.guo@starfivetech.com>
-Chenjieqin <Jessica.Chen@starfivetech.com>
-bo.li <bo.li@starfivetech.com>
-
-Rearranged, cleanups, fixes, pins and resets added by Emil.
-Cleanups, fixes, clocks added by Geert.
-Cleanups and GPIO fixes from Drew.
-Thermal zone added by Stephen.
-PWM pins added by Jianlong.
-cpu-map added by Jonas.
-
-Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
-Signed-off-by: Stephen L Arnold <nerdboy@gentoo.org>
-Signed-off-by: Drew Fustini <drew@beagleboard.org>
-Signed-off-by: Jianlong Huang <jianlong.huang@starfivetech.com>
-Signed-off-by: Jonas Hahnfeld <hahnjo@hahnjo.de>
-Signed-off-by: Emil Renner Berthing <kernel@esmil.dk>
----
- arch/riscv/boot/dts/starfive/Makefile | 2 +
- .../starfive/jh7100-beaglev-starlight-a1.dts | 24 ++
- .../dts/starfive/jh7100-beaglev-starlight.dts | 6 +
- .../boot/dts/starfive/jh7100-common.dtsi | 177 ++++++++
- .../jh7100-starfive-visionfive-v1.dts | 13 +
- arch/riscv/boot/dts/starfive/jh7100.dtsi | 389 ++++++++++++++++++
- 6 files changed, 611 insertions(+)
- create mode 100644 arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight-a1.dts
-
---- a/arch/riscv/boot/dts/starfive/Makefile
-+++ b/arch/riscv/boot/dts/starfive/Makefile
-@@ -1,10 +1,12 @@
- # SPDX-License-Identifier: GPL-2.0
- # Enables support for device-tree overlays
-+DTC_FLAGS_jh7100-beaglev-starlight-a1 := -@
- DTC_FLAGS_jh7100-beaglev-starlight := -@
- DTC_FLAGS_jh7100-starfive-visionfive-v1 := -@
- DTC_FLAGS_jh7110-starfive-visionfive-2-v1.2a := -@
- DTC_FLAGS_jh7110-starfive-visionfive-2-v1.3b := -@
-
-+dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight-a1.dtb
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-beaglev-starlight.dtb
- dtb-$(CONFIG_ARCH_STARFIVE) += jh7100-starfive-visionfive-v1.dtb
-
---- /dev/null
-+++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight-a1.dts
-@@ -0,0 +1,24 @@
-+// SPDX-License-Identifier: GPL-2.0 OR MIT
-+/*
-+ * Copyright (C) 2021 Emil Renner Berthing <kernel@esmil.dk>
-+ */
-+
-+/dts-v1/;
-+#include "jh7100-common.dtsi"
-+#include <dt-bindings/gpio/gpio.h>
-+
-+/ {
-+ model = "BeagleV Starlight Beta A1";
-+ compatible = "beagle,beaglev-starlight-jh7100-a1", "starfive,jh7100";
-+
-+ gpio-restart {
-+ compatible = "gpio-restart";
-+ gpios = <&gpio 63 GPIO_ACTIVE_HIGH>;
-+ priority = <224>;
-+ };
-+};
-+
-+&gpio {
-+ /* don't reset gpio mux for serial console and reset gpio */
-+ starfive,keep-gpiomux = <13 14 63>;
-+};
---- a/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7100-beaglev-starlight.dts
-@@ -6,6 +6,7 @@
-
- /dts-v1/;
- #include "jh7100-common.dtsi"
-+#include <dt-bindings/gpio/gpio.h>
-
- / {
- model = "BeagleV Starlight Beta";
-@@ -16,6 +17,11 @@
- phy-handle = <&phy>;
- };
-
-+&gpio {
-+ /* don't reset gpio mux for serial console on uart3 */
-+ starfive,keep-gpiomux = <13 14>;
-+};
-+
- &mdio {
- phy: ethernet-phy@7 {
- reg = <7>;
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -15,6 +15,7 @@
- mmc0 = &sdio0;
- mmc1 = &sdio1;
- serial0 = &uart3;
-+ serial1 = &uart0;
- };
-
- chosen {
-@@ -47,11 +48,41 @@
- #size-cells = <2>;
- ranges;
-
-+ linux,cma {
-+ compatible = "shared-dma-pool";
-+ alloc-ranges = <0x0 0xa0000000 0x0 0x28000000>;
-+ size = <0x0 0x28000000>;
-+ alignment = <0x0 0x1000>;
-+ reusable;
-+ linux,cma-default;
-+ };
-+
-+ jpu_reserved: framebuffer@c9000000 {
-+ reg = <0x0 0xc9000000 0x0 0x4000000>;
-+ };
-+
-+ nvdla_reserved: framebuffer@d0000000 {
-+ reg = <0x0 0xd0000000 0x0 0x28000000>;
-+ no-map;
-+ };
-+
-+ vin_reserved: framebuffer@f9000000 {
-+ compatible = "shared-dma-pool";
-+ reg = <0x0 0xf9000000 0x0 0x1000000>;
-+ no-map;
-+ };
-+
- dma-reserved@fa000000 {
- reg = <0x0 0xfa000000 0x0 0x1000000>;
- no-map;
- };
-
-+ sffb_reserved: framebuffer@fb000000 {
-+ compatible = "shared-dma-pool";
-+ reg = <0x0 0xfb000000 0x0 0x2000000>;
-+ no-map;
-+ };
-+
- linux,dma@107a000000 {
- compatible = "shared-dma-pool";
- reg = <0x10 0x7a000000 0x0 0x1000000>;
-@@ -72,6 +103,44 @@
- };
- };
-
-+&display {
-+ memory-region = <&sffb_reserved>;
-+ status = "okay";
-+};
-+
-+&crtc {
-+ ddr-format = <4>; //<WIN_FMT_RGB565>;
-+ status = "okay";
-+
-+ port: port@0 {
-+ reg = <0>;
-+
-+ crtc_0_out: endpoint {
-+ remote-endpoint = <&hdmi_input0>;
-+ };
-+ };
-+};
-+
-+&encoder {
-+ encoder-type = <2>; // 2-TMDS, 3-LVDS, 6-DSI, 8-DPI
-+ status = "okay";
-+
-+ ports {
-+ port@0 {
-+ hdmi_out: endpoint {
-+ remote-endpoint = <&tda998x_0_input>;
-+ };
-+ };
-+
-+ port@1 {
-+ hdmi_input0: endpoint {
-+ remote-endpoint = <&crtc_0_out>;
-+ };
-+ };
-+
-+ };
-+};
-+
- &gmac {
- pinctrl-names = "default";
- pinctrl-0 = <&gmac_pins>;
-@@ -199,6 +268,20 @@
- };
- };
-
-+ pwmdac_pins: pwmdac-0 {
-+ pwmdac-pins {
-+ pinmux = <GPIOMUX(23, GPO_PWMDAC_LEFT_OUT,
-+ GPO_ENABLE, GPI_NONE)>,
-+ <GPIOMUX(24, GPO_PWMDAC_RIGHT_OUT,
-+ GPO_ENABLE, GPI_NONE)>;
-+ bias-disable;
-+ drive-strength = <35>;
-+ input-disable;
-+ input-schmitt-disable;
-+ slew-rate = <0>;
-+ };
-+ };
-+
- pwm_pins: pwm-0 {
- pwm-pins {
- pinmux = <GPIOMUX(7,
-@@ -289,6 +372,39 @@
- };
- };
-
-+ spi2_pins: spi2-0 {
-+ mosi-pins {
-+ pinmux = <GPIOMUX(18, GPO_SPI2_PAD_TXD,
-+ GPO_ENABLE, GPI_NONE)>;
-+ bias-disable;
-+ input-disable;
-+ input-schmitt-disable;
-+ };
-+ miso-pins {
-+ pinmux = <GPIOMUX(16, GPO_LOW, GPO_DISABLE,
-+ GPI_SPI2_PAD_RXD)>;
-+ bias-pull-up;
-+ input-enable;
-+ input-schmitt-enable;
-+ };
-+ sck-pins {
-+ pinmux = <GPIOMUX(12, GPO_SPI2_PAD_SCK_OUT,
-+ GPO_ENABLE, GPI_NONE)>;
-+ bias-disable;
-+ input-disable;
-+ input-schmitt-disable;
-+ };
-+ ss-pins {
-+ pinmux = <GPIOMUX(15, GPO_SPI2_PAD_SS_0_N,
-+ GPO_ENABLE, GPI_NONE)>,
-+ <GPIOMUX(11, GPO_SPI2_PAD_SS_1_N,
-+ GPO_ENABLE, GPI_NONE)>;
-+ bias-disable;
-+ input-disable;
-+ input-schmitt-disable;
-+ };
-+ };
-+
- uart0_pins: uart0-0 {
- rx-pins {
- pinmux = <GPIOMUX(40, GPO_LOW, GPO_DISABLE,
-@@ -364,6 +480,17 @@
- regulators {
- };
- };
-+
-+ tda998x@70 {
-+ compatible = "nxp,tda998x";
-+ reg = <0x70>;
-+
-+ port {
-+ tda998x_0_input: endpoint {
-+ remote-endpoint = <&hdmi_out>;
-+ };
-+ };
-+ };
- };
-
- &i2c1 {
-@@ -400,6 +527,44 @@
- status = "okay";
- };
-
-+&pwmdac {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&pwmdac_pins>;
-+ status = "okay";
-+};
-+
-+&qspi {
-+ nor_flash: nor-flash@0 {
-+ compatible = "spi-flash";
-+ reg = <0>;
-+ spi-max-frequency = <31250000>;
-+ page-size = <256>;
-+ block-size = <16>;
-+ cdns,read-delay = <4>;
-+ cdns,tshsl-ns = <1>;
-+ cdns,tsd2d-ns = <1>;
-+ cdns,tchsh-ns = <1>;
-+ cdns,tslch-ns = <1>;
-+ spi-tx-bus-width = <1>;
-+ spi-rx-bus-width = <1>;
-+ };
-+
-+ nand_flash: nand-flash@1 {
-+ compatible = "spi-flash-nand";
-+ reg = <1>;
-+ spi-max-frequency = <31250000>;
-+ page-size = <2048>;
-+ block-size = <17>;
-+ cdns,read-delay = <4>;
-+ cdns,tshsl-ns = <1>;
-+ cdns,tsd2d-ns = <1>;
-+ cdns,tchsh-ns = <1>;
-+ cdns,tslch-ns = <1>;
-+ spi-tx-bus-width = <1>;
-+ spi-rx-bus-width = <1>;
-+ };
-+};
-+
- &sdio0 {
- broken-cd;
- bus-width = <4>;
-@@ -428,6 +593,18 @@
- };
- };
-
-+&spi2 {
-+ pinctrl-names = "default";
-+ pinctrl-0 = <&spi2_pins>;
-+ status = "okay";
-+
-+ spi_dev0: spi@0 {
-+ compatible = "rohm,dh2228fv";
-+ spi-max-frequency = <10000000>;
-+ reg = <0>;
-+ };
-+};
-+
- &uart0 {
- pinctrl-names = "default";
- pinctrl-0 = <&uart0_pins>;
---- a/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
-+++ b/arch/riscv/boot/dts/starfive/jh7100-starfive-visionfive-v1.dts
-@@ -22,6 +22,19 @@
- phy-handle = <&phy>;
- };
-
-+&gpio {
-+ /* don't reset gpio mux for serial console and reset gpio */
-+ starfive,keep-gpiomux = <13 14 63>;
-+};
-+
-+&i2c0 {
-+ eeprom@50 {
-+ compatible = "atmel,24c04";
-+ reg = <0x50>;
-+ pagesize = <16>;
-+ };
-+};
-+
- /*
- * The board uses a Motorcomm YT8521 PHY supporting RGMII-ID, but requires
- * manual adjustment of the RX internal delay to work properly. The default
---- a/arch/riscv/boot/dts/starfive/jh7100.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100.dtsi
-@@ -6,7 +6,9 @@
-
- /dts-v1/;
- #include <dt-bindings/clock/starfive-jh7100.h>
-+#include <dt-bindings/clock/starfive-jh7100-audio.h>
- #include <dt-bindings/reset/starfive-jh7100.h>
-+#include <dt-bindings/reset/starfive-jh7100-audio.h>
-
- / {
- compatible = "starfive,jh7100";
-@@ -37,6 +39,7 @@
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
- "zifencei", "zihpm";
-+ starfive,itim = <&itim0>;
- tlb-split;
-
- cpu0_intc: interrupt-controller {
-@@ -66,6 +69,7 @@
- riscv,isa-base = "rv64i";
- riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "zicntr", "zicsr",
- "zifencei", "zihpm";
-+ starfive,itim = <&itim1>;
- tlb-split;
-
- cpu1_intc: interrupt-controller {
-@@ -153,6 +157,24 @@
- dma-noncoherent;
- ranges;
-
-+ dtim: dtim@1000000 {
-+ compatible = "starfive,dtim0";
-+ reg = <0x0 0x1000000 0x0 0x2000>;
-+ reg-names = "mem";
-+ };
-+
-+ itim0: itim@1808000 {
-+ compatible = "starfive,itim0";
-+ reg = <0x0 0x1808000 0x0 0x8000>;
-+ reg-names = "mem";
-+ };
-+
-+ itim1: itim@1820000 {
-+ compatible = "starfive,itim0";
-+ reg = <0x0 0x1820000 0x0 0x8000>;
-+ reg-names = "mem";
-+ };
-+
- clint: clint@2000000 {
- compatible = "starfive,jh7100-clint", "sifive,clint0";
- reg = <0x0 0x2000000 0x0 0x10000>;
-@@ -239,6 +261,124 @@
- };
- };
-
-+ dma2p: dma-controller@100b0000 {
-+ compatible = "starfive,jh7100-axi-dma";
-+ reg = <0x0 0x100b0000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_SGDMA2P_AXI>,
-+ <&clkgen JH7100_CLK_SGDMA2P_AHB>;
-+ clock-names = "core-clk", "cfgr-clk";
-+ resets = <&rstgen JH7100_RSTN_SGDMA2P_AXI>,
-+ <&rstgen JH7100_RSTN_SGDMA2P_AHB>;
-+ reset-names = "axi", "ahb";
-+ interrupts = <2>;
-+ #dma-cells = <1>;
-+ dma-channels = <4>;
-+ snps,dma-masters = <1>;
-+ snps,data-width = <4>;
-+ snps,block-size = <4096 4096 4096 4096>;
-+ snps,priority = <0 1 2 3>;
-+ snps,axi-max-burst-len = <128>;
-+ dma-coherent;
-+ };
-+
-+ crypto: crypto@100d0000 {
-+ compatible = "starfive,vic-sec";
-+ reg = <0x0 0x100d0000 0x0 0x20000>,
-+ <0x0 0x11800234 0x0 0xc>;
-+ reg-names = "secmem", "secclk";
-+ clocks = <&clkgen JH7100_CLK_SEC_AHB>;
-+ interrupts = <31>;
-+ };
-+
-+ i2sadc0: i2sadc0@10400000 {
-+ compatible = "snps,designware-i2sadc0";
-+ reg = <0x0 0x10400000 0x0 0x1000>;
-+ clocks = <&clkgen JH7100_CLK_APB1_BUS>;
-+ clock-names = "i2sclk";
-+ interrupt-parent = <&plic>;
-+ #sound-dai-cells = <0>;
-+ dmas = <&dma2p 28>;
-+ dma-names = "rx";
-+ };
-+
-+ i2svad: i2svad@10420000 {
-+ compatible = "starfive,sf-i2svad";
-+ reg = <0x0 0x10420000 0x0 0x1000> ;
-+ clocks = <&audclk JH7100_AUDCLK_I2SVAD_APB>;
-+ clock-names = "i2svad_apb";
-+ resets = <&audrst JH7100_AUDRSTN_I2SVAD_APB>,
-+ <&audrst JH7100_AUDRSTN_I2SVAD_SRST>;
-+ reset-names = "apb_i2svad", "i2svad_srst";
-+ interrupts = <60>, <61>;
-+ interrupt-names = "spintr", "slintr";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ pwmdac: pwmdac@10440000 {
-+ compatible = "starfive,pwmdac";
-+ reg = <0x0 0x10440000 0x0 0x1000>;
-+ clocks = <&clkgen JH7100_CLK_AUDIO_ROOT>,
-+ <&clkgen JH7100_CLK_AUDIO_SRC>,
-+ <&clkgen JH7100_CLK_AUDIO_12288>,
-+ <&audclk JH7100_AUDCLK_DMA1P_AHB>,
-+ <&audclk JH7100_AUDCLK_PWMDAC_APB>,
-+ <&audclk JH7100_AUDCLK_DAC_MCLK>;
-+ clock-names = "audio_root",
-+ "audio_src",
-+ "audio_12288",
-+ "dma1p_ahb",
-+ "pwmdac_apb",
-+ "dac_mclk";
-+ resets = <&audrst JH7100_AUDRSTN_APB_BUS>,
-+ <&audrst JH7100_AUDRSTN_DMA1P_AHB>,
-+ <&audrst JH7100_AUDRSTN_PWMDAC_APB>;
-+ reset-names = "apb_bus", "dma1p_ahb", "apb_pwmdac";
-+ dmas = <&dma2p 23>;
-+ dma-names = "tx";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ i2sdac0: i2sdac0@10450000 {
-+ compatible = "snps,designware-i2sdac0";
-+ reg = <0x0 0x10450000 0x0 0x1000>;
-+ clocks = <&audclk JH7100_AUDCLK_DAC_MCLK>,
-+ <&audclk JH7100_AUDCLK_I2SDAC_BCLK>,
-+ <&audclk JH7100_AUDCLK_I2SDAC_LRCLK>,
-+ <&audclk JH7100_AUDCLK_I2SDAC_APB>;
-+ clock-names = "dac_mclk", "i2sdac0_bclk", "i2sdac0_lrclk", "i2sdac_apb";
-+ resets = <&audrst JH7100_AUDRSTN_I2SDAC_APB>,
-+ <&audrst JH7100_AUDRSTN_I2SDAC_SRST>;
-+ reset-names = "apb_i2sdac", "i2sdac_srst";
-+ #sound-dai-cells = <0>;
-+ dmas = <&dma2p 30>;
-+ dma-names = "tx";
-+ };
-+
-+ i2sdac1: i2sdac1@10460000 {
-+ compatible = "snps,designware-i2sdac1";
-+ reg = <0x0 0x10460000 0x0 0x1000>;
-+ clocks = <&audclk JH7100_AUDCLK_DAC_MCLK>,
-+ <&audclk JH7100_AUDCLK_I2S1_BCLK>,
-+ <&audclk JH7100_AUDCLK_I2S1_LRCLK>,
-+ <&audclk JH7100_AUDCLK_I2S1_APB>;
-+ clock-names = "dac_mclk", "i2sdac1_bclk", "i2sdac1_lrclk", "i2s1_apb";
-+ resets = <&audrst JH7100_AUDRSTN_I2S1_APB>,
-+ <&audrst JH7100_AUDRSTN_I2S1_SRST>;
-+ #sound-dai-cells = <0>;
-+ dmas = <&dma2p 31>;
-+ dma-names = "tx";
-+ };
-+
-+ i2sdac16k: i2sdac16k@10470000 {
-+ compatible = "snps,designware-i2sdac16k";
-+ reg = <0x0 0x10470000 0x0 0x1000>;
-+ clocks = <&clkgen JH7100_CLK_APB1_BUS>;
-+ clock-names = "i2sclk";
-+ #sound-dai-cells = <0>;
-+ dmas = <&dma2p 29>;
-+ dma-names = "tx";
-+ };
-+
- audclk: clock-controller@10480000 {
- compatible = "starfive,jh7100-audclk";
- reg = <0x0 0x10480000 0x0 0x10000>;
-@@ -255,6 +395,50 @@
- #reset-cells = <1>;
- };
-
-+ spdif_transmitter: spdif-transmitter {
-+ compatible = "linux,spdif-dit";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ spdif_receiver: spdif-receiver {
-+ compatible = "linux,spdif-dir";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ pwmdac_codec: pwmdac-transmitter {
-+ compatible = "linux,pwmdac-dit";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ dmic_codec: dmic {
-+ compatible = "dmic-codec";
-+ #sound-dai-cells = <0>;
-+ };
-+
-+ sound: snd-card {
-+ compatible = "simple-audio-card";
-+ simple-audio-card,name = "Starfive-Multi-Sound-Card";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+
-+ /* pwmdac */
-+ simple-audio-card,dai-link@0 {
-+ reg = <0>;
-+ status = "okay";
-+ format = "left_j";
-+ bitclock-master = <&sndcpu0>;
-+ frame-master = <&sndcpu0>;
-+
-+ sndcpu0: cpu {
-+ sound-dai = <&pwmdac>;
-+ };
-+
-+ codec {
-+ sound-dai = <&pwmdac_codec>;
-+ };
-+ };
-+ };
-+
- sysaudio: syscon@104a0000 {
- compatible = "starfive,jh7100-sysaudio", "syscon";
- reg = <0x0 0x104a0000 0x0 0x10000>;
-@@ -287,6 +471,25 @@
- };
- };
-
-+ dma1p: dma-controller@10500000 {
-+ compatible = "starfive,jh7100-axi-dma";
-+ reg = <0x0 0x10500000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_SGDMA1P_AXI>,
-+ <&clkgen JH7100_CLK_SGDMA1P_BUS>;
-+ clock-names = "core-clk", "cfgr-clk";
-+ resets = <&rstgen JH7100_RSTN_DMA1P_AXI>,
-+ <&rstgen JH7100_RSTN_SGDMA1P_AXI>;
-+ reset-names = "axi", "ahb";
-+ interrupts = <1>;
-+ #dma-cells = <1>;
-+ dma-channels = <16>;
-+ snps,dma-masters = <1>;
-+ snps,data-width = <3>;
-+ snps,block-size = <4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096 4096>;
-+ snps,priority = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15>;
-+ snps,axi-max-burst-len = <64>;
-+ };
-+
- clkgen: clock-controller@11800000 {
- compatible = "starfive,jh7100-clkgen";
- reg = <0x0 0x11800000 0x0 0x10000>;
-@@ -295,6 +498,13 @@
- #clock-cells = <1>;
- };
-
-+ otp: otp@11810000 {
-+ compatible = "starfive,fu740-otp";
-+ reg = <0x0 0x11810000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_OTP_APB>;
-+ fuse-count = <0x200>;
-+ };
-+
- rstgen: reset-controller@11840000 {
- compatible = "starfive,jh7100-reset";
- reg = <0x0 0x11840000 0x0 0x10000>;
-@@ -306,6 +516,21 @@
- reg = <0x0 0x11850000 0x0 0x10000>;
- };
-
-+ qspi: spi@11860000 {
-+ compatible = "cdns,qspi-nor";
-+ reg = <0x0 0x11860000 0x0 0x10000>,
-+ <0x0 0x20000000 0x0 0x20000000>;
-+ clocks = <&clkgen JH7100_CLK_QSPI_AHB>;
-+ interrupts = <3>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ cdns,fifo-depth = <256>;
-+ cdns,fifo-width = <4>;
-+ cdns,trigger-address = <0x0>;
-+ spi-max-frequency = <250000000>;
-+ status = "disabled";
-+ };
-+
- uart0: serial@11870000 {
- compatible = "starfive,jh7100-hsuart", "snps,dw-apb-uart";
- reg = <0x0 0x11870000 0x0 0x10000>;
-@@ -332,6 +557,34 @@
- status = "disabled";
- };
-
-+ spi0: spi@11890000 {
-+ compatible = "snps,dw-apb-ssi";
-+ reg = <0x0 0x11890000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_SPI0_CORE>,
-+ <&clkgen JH7100_CLK_SPI0_APB>;
-+ clock-names = "ssi_clk", "pclk";
-+ resets = <&rstgen JH7100_RSTN_SPI0_APB>;
-+ reset-names = "spi";
-+ interrupts = <94>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ spi1: spi@118a0000 {
-+ compatible = "snps,dw-apb-ssi";
-+ reg = <0x0 0x118a0000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_SPI1_CORE>,
-+ <&clkgen JH7100_CLK_SPI1_APB>;
-+ clock-names = "ssi_clk", "pclk";
-+ resets = <&rstgen JH7100_RSTN_SPI1_APB>;
-+ reset-names = "spi";
-+ interrupts = <95>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
- i2c0: i2c@118b0000 {
- compatible = "snps,designware-i2c";
- reg = <0x0 0x118b0000 0x0 0x10000>;
-@@ -358,6 +611,41 @@
- status = "disabled";
- };
-
-+ trng: trng@118d0000 {
-+ compatible = "starfive,vic-rng";
-+ reg = <0x0 0x118d0000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_TRNG_APB>;
-+ interrupts = <98>;
-+ };
-+
-+ vpu_enc: vpu_enc@118e0000 {
-+ compatible = "cm,cm521-vpu";
-+ reg = <0x0 0x118e0000 0x0 0x4000>;
-+ reg-names = "control";
-+ clocks = <&clkgen JH7100_CLK_VP6_CORE>;
-+ clock-names = "vcodec";
-+ interrupts = <26>;
-+ };
-+
-+ vpu_dec: vpu_dec@118f0000 {
-+ compatible = "c&m,cm511-vpu";
-+ reg = <0 0x118f0000 0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_VP6_CORE>;
-+ clock-names = "vcodec";
-+ interrupts = <23>;
-+ //memory-region = <&vpu_reserved>;
-+ };
-+
-+ jpu: coadj12@11900000 {
-+ compatible = "cm,codaj12-jpu-1";
-+ reg = <0x0 0x11900000 0x0 0x300>;
-+ reg-names = "control";
-+ clocks = <&clkgen JH7100_CLK_JPEG_APB>;
-+ clock-names = "jpege";
-+ interrupts = <24>;
-+ memory-region = <&jpu_reserved>;
-+ };
-+
- gpio: pinctrl@11910000 {
- compatible = "starfive,jh7100-pinctrl";
- reg = <0x0 0x11910000 0x0 0x10000>,
-@@ -372,6 +660,86 @@
- #interrupt-cells = <2>;
- };
-
-+ nvdla@11940000 {
-+ compatible = "nvidia,nvdla_os_initial";
-+ interrupts = <22>;
-+ memory-region = <&nvdla_reserved>;
-+ reg = <0x0 0x11940000 0x0 0x40000>;
-+ status = "okay";
-+ };
-+
-+ display: display-subsystem {
-+ compatible = "starfive,display-subsystem";
-+ dma-coherent;
-+ status = "disabled";
-+ };
-+
-+ encoder: display-encoder {
-+ compatible = "starfive,display-encoder";
-+ status = "disabled";
-+ };
-+
-+ crtc: crtc@12000000 {
-+ compatible = "starfive,jh7100-crtc";
-+ reg = <0x0 0x12000000 0x0 0x10000>,
-+ <0x0 0x12040000 0x0 0x10000>,
-+ <0x0 0x12080000 0x0 0x10000>,
-+ <0x0 0x120c0000 0x0 0x10000>,
-+ <0x0 0x12240000 0x0 0x10000>,
-+ <0x0 0x12250000 0x0 0x10000>,
-+ <0x0 0x12260000 0x0 0x10000>;
-+ reg-names = "lcdc", "vpp0", "vpp1", "vpp2", "clk", "rst", "sys";
-+ clocks = <&clkgen JH7100_CLK_DISP_AXI>, <&clkgen JH7100_CLK_VOUT_SRC>;
-+ clock-names = "disp_axi", "vout_src";
-+ resets = <&rstgen JH7100_RSTN_DISP_AXI>, <&rstgen JH7100_RSTN_VOUT_SRC>;
-+ reset-names = "disp_axi", "vout_src";
-+ interrupts = <101>, <103>;
-+ interrupt-names = "lcdc_irq", "vpp1_irq";
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+
-+ pp1 {
-+ pp-id = <1>;
-+ fifo-out;
-+ //sys-bus-out;
-+ src-format = <11>; //<COLOR_RGB565>;
-+ src-width = <1920>;
-+ src-height = <1080>;
-+ dst-format = <7>; //<COLOR_RGB888_ARGB>;
-+ dst-width = <1920>;
-+ dst-height = <1080>;
-+ };
-+ };
-+
-+ spi2: spi@12410000 {
-+ compatible = "snps,dw-apb-ssi";
-+ reg = <0x0 0x12410000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_SPI2_CORE>,
-+ <&clkgen JH7100_CLK_SPI2_APB>;
-+ clock-names = "ssi_clk", "pclk";
-+ resets = <&rstgen JH7100_RSTN_SPI2_APB>;
-+ reset-names = "spi";
-+ interrupts = <70>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
-+ spi3: spi@12420000 {
-+ compatible = "snps,dw-apb-ssi";
-+ reg = <0x0 0x12420000 0x0 0x10000>;
-+ clocks = <&clkgen JH7100_CLK_SPI3_CORE>,
-+ <&clkgen JH7100_CLK_SPI3_APB>;
-+ clock-names = "ssi_clk", "pclk";
-+ resets = <&rstgen JH7100_RSTN_SPI3_APB>;
-+ reset-names = "spi";
-+ interrupts = <71>;
-+ #address-cells = <1>;
-+ #size-cells = <0>;
-+ status = "disabled";
-+ };
-+
- uart2: serial@12430000 {
- compatible = "starfive,jh7100-uart", "snps,dw-apb-uart";
- reg = <0x0 0x12430000 0x0 0x10000>;
-@@ -454,5 +822,26 @@
- reset-names = "sense", "bus";
- #thermal-sensor-cells = <0>;
- };
-+
-+ xrp@f0000000 {
-+ compatible = "cdns,xrp";
-+ reg = <0x0 0xf0000000 0x0 0x01ffffff>,
-+ <0x10 0x72000000 0x0 0x00001000>,
-+ <0x10 0x72001000 0x0 0x00fff000>,
-+ <0x0 0x124b0000 0x0 0x00010000>;
-+ clocks = <&clkgen JH7100_CLK_VP6_CORE>;
-+ interrupts = <27>, <28>;
-+ firmware-name = "vp6_elf";
-+ dsp-irq = <19 20>;
-+ dsp-irq-src = <0x20 0x21>;
-+ intc-irq-mode = <1>;
-+ intc-irq = <0 1>;
-+ #address-cells = <1>;
-+ #size-cells = <1>;
-+ ranges = <0x40000000 0x0 0x40000000 0x01000000>,
-+ <0xb0000000 0x10 0x70000000 0x3000000>;
-+ dsp@0 {
-+ };
-+ };
- };
- };
+++ /dev/null
-From ec25d5b3e4ac00b76dce3593b54062ee7826cbbd Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sat, 31 May 2025 22:17:21 +0000
-Subject: [PATCH 1022/1022] riscv: dts: starfive: vf1: add LED aliases and stop
- heartbeat
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- arch/riscv/boot/dts/starfive/jh7100-common.dtsi | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
---- a/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7100-common.dtsi
-@@ -16,6 +16,10 @@
- mmc1 = &sdio1;
- serial0 = &uart3;
- serial1 = &uart0;
-+ led-boot = &led_ack;
-+ led-failsafe = &led_ack;
-+ led-running = &led_ack;
-+ led-upgrade = &led_ack;
- };
-
- chosen {
-@@ -34,11 +38,11 @@
- leds {
- compatible = "gpio-leds";
-
-- led-ack {
-+ led_ack: led-ack {
- gpios = <&gpio 43 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_GREEN>;
- function = LED_FUNCTION_HEARTBEAT;
-- linux,default-trigger = "heartbeat";
-+ default-state = "on";
- label = "ack";
- };
- };
+++ /dev/null
-From 3a92ee5a97f030bdb1e88272a5d277ecb76836d6 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sun, 1 Jun 2025 14:03:30 +0000
-Subject: [PATCH 7/8] riscv: dts: starfive: visionfive2: add SYSLED support
-
-A SYS LED is available at aongpio-3. Add standard heartbeat
-support for it.
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- .../dts/starfive/jh7110-starfive-visionfive-2.dtsi | 12 ++++++++++++
- 1 file changed, 12 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -21,6 +21,18 @@
- reg = <0x0 0x6ce00000 0x0 0x1600000>;
- };
- };
-+
-+ leds {
-+ compatible = "gpio-leds";
-+
-+ led-ack {
-+ gpios = <&aongpio 3 GPIO_ACTIVE_HIGH>;
-+ color = <LED_COLOR_ID_GREEN>;
-+ function = LED_FUNCTION_HEARTBEAT;
-+ linux,default-trigger = "heartbeat";
-+ label = "ack";
-+ };
-+ };
- };
-
- &gmac1 {
+++ /dev/null
-From d930d3d22dcca6946dbdc822d7b8681f0d6372e5 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sun, 1 Jun 2025 14:06:04 +0000
-Subject: [PATCH 8/8] riscv: dts: starfive: visionfive2: add LED aliases and
- stop heartbeat
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- .../boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi | 8 ++++++--
- 1 file changed, 6 insertions(+), 2 deletions(-)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -6,10 +6,15 @@
-
- /dts-v1/;
- #include "jh7110-common.dtsi"
-+#include <dt-bindings/leds/common.h>
-
- / {
- aliases {
- ethernet1 = &gmac1;
-+ led-boot = &led_ack;
-+ led-failsafe = &led_ack;
-+ led-running = &led_ack;
-+ led-upgrade = &led_ack;
- };
-
- reserved-memory {
-@@ -25,11 +30,11 @@
- leds {
- compatible = "gpio-leds";
-
-- led-ack {
-+ led_ack: led-ack {
- gpios = <&aongpio 3 GPIO_ACTIVE_HIGH>;
- color = <LED_COLOR_ID_GREEN>;
- function = LED_FUNCTION_HEARTBEAT;
-- linux,default-trigger = "heartbeat";
-+ default-state = "on";
- label = "ack";
- };
- };
+++ /dev/null
-From 928a660ec1124853d2dae074e74ec7b20fe9bac2 Mon Sep 17 00:00:00 2001
-From: Zoltan HERPAI <wigyori@uid0.hu>
-Date: Sun, 1 Jun 2025 16:02:38 +0000
-Subject: [PATCH] riscv: dts: starfive: visionfive2: add dma pool entry
-
-In the VF2 SDK there is a reserved memory for a shared dma pool, which is
-also updated by the SDK bootloader. Add this node here as well.
-
-Signed-off-by: Zoltan HERPAI <wigyori@uid0.hu>
----
- .../boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi | 9 +++++++++
- 1 file changed, 9 insertions(+)
-
---- a/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-+++ b/arch/riscv/boot/dts/starfive/jh7110-starfive-visionfive-2.dtsi
-@@ -25,6 +25,15 @@
- e24_mem: e24@c0000000 {
- reg = <0x0 0x6ce00000 0x0 0x1600000>;
- };
-+
-+ linux,cma {
-+ compatible = "shared-dma-pool";
-+ reusable;
-+ size = <0x0 0x20000000>;
-+ alignment = <0x0 0x1000>;
-+ alloc-ranges = <0x0 0x70000000 0x0 0x20000000>;
-+ linux,cma-default;
-+ };
- };
-
- leds {