From fd555dc7fa0820b43bc2f55c56fa40494c41ef29 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 15 Mar 2021 16:35:00 +0530 Subject: [PATCH 001/120] RISC-V: Use SBI SRST extension when available The SBI SRST extension provides a standard way to poweroff and reboot the system irrespective to whether Linux RISC-V S-mode is running natively (HS-mode) or inside Guest/VM (VS-mode). The SBI SRST extension is available in latest SBI v0.3-draft specification at: https://github.com/riscv/riscv-sbi-doc. This patch extends Linux RISC-V SBI implementation to detect and use SBI SRST extension. Signed-off-by: Anup Patel Reviewed-by: Atish Patra --- arch/riscv/include/asm/sbi.h | 24 ++++++++++++++++++++++++ arch/riscv/kernel/sbi.c | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 0d42693cb65e9c..289621da4a2a8f 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -27,6 +27,7 @@ enum sbi_ext_id { SBI_EXT_IPI = 0x735049, SBI_EXT_RFENCE = 0x52464E43, SBI_EXT_HSM = 0x48534D, + SBI_EXT_SRST = 0x53525354, }; enum sbi_ext_base_fid { @@ -70,6 +71,21 @@ enum sbi_hsm_hart_status { SBI_HSM_HART_STATUS_STOP_PENDING, }; +enum sbi_ext_srst_fid { + SBI_EXT_SRST_RESET = 0, +}; + +enum sbi_srst_reset_type { + SBI_SRST_RESET_TYPE_SHUTDOWN = 0, + SBI_SRST_RESET_TYPE_COLD_REBOOT, + SBI_SRST_RESET_TYPE_WARM_REBOOT, +}; + +enum sbi_srst_reset_reason { + SBI_SRST_RESET_REASON_NONE = 0, + SBI_SRST_RESET_REASON_SYS_FAILURE, +}; + #define SBI_SPEC_VERSION_DEFAULT 0x1 #define SBI_SPEC_VERSION_MAJOR_SHIFT 24 #define SBI_SPEC_VERSION_MAJOR_MASK 0x7f @@ -148,6 +164,14 @@ static inline unsigned long sbi_minor_version(void) return sbi_spec_version & SBI_SPEC_VERSION_MINOR_MASK; } +/* Make SBI version */ +static inline unsigned long sbi_mk_version(unsigned long major, + unsigned long minor) +{ + return ((major & SBI_SPEC_VERSION_MAJOR_MASK) << + SBI_SPEC_VERSION_MAJOR_SHIFT) | minor; +} + int sbi_err_map_linux_errno(int err); #else /* CONFIG_RISCV_SBI */ static inline int sbi_remote_fence_i(const unsigned long *hart_mask) { return -1; } diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index 7402a417f38e38..9a84f0cb517511 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -7,6 +7,7 @@ #include #include +#include #include #include @@ -501,6 +502,32 @@ int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, } EXPORT_SYMBOL(sbi_remote_hfence_vvma_asid); +static void sbi_srst_reset(unsigned long type, unsigned long reason) +{ + sbi_ecall(SBI_EXT_SRST, SBI_EXT_SRST_RESET, type, reason, + 0, 0, 0, 0); + pr_warn("%s: type=0x%lx reason=0x%lx failed\n", + __func__, type, reason); +} + +static int sbi_srst_reboot(struct notifier_block *this, + unsigned long mode, void *cmd) +{ + sbi_srst_reset((mode == REBOOT_WARM || mode == REBOOT_SOFT) ? + SBI_SRST_RESET_TYPE_WARM_REBOOT : + SBI_SRST_RESET_TYPE_COLD_REBOOT, + SBI_SRST_RESET_REASON_NONE); + return NOTIFY_DONE; +} + +static struct notifier_block sbi_srst_reboot_nb; + +static void sbi_srst_power_off(void) +{ + sbi_srst_reset(SBI_SRST_RESET_TYPE_SHUTDOWN, + SBI_SRST_RESET_REASON_NONE); +} + /** * sbi_probe_extension() - Check if an SBI extension ID is supported or not. * @extid: The extension ID to be probed. @@ -608,6 +635,14 @@ void __init sbi_init(void) } else { __sbi_rfence = __sbi_rfence_v01; } + if ((sbi_spec_version >= sbi_mk_version(0, 3)) && + (sbi_probe_extension(SBI_EXT_SRST) > 0)) { + pr_info("SBI SRST extension detected\n"); + pm_power_off = sbi_srst_power_off; + sbi_srst_reboot_nb.notifier_call = sbi_srst_reboot; + sbi_srst_reboot_nb.priority = 192; + register_restart_handler(&sbi_srst_reboot_nb); + } } else { __sbi_set_timer = __sbi_set_timer_v01; __sbi_send_ipi = __sbi_send_ipi_v01; From a8f9da3edafe31f3a134f2d8492bbfce38c2fbbf Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:16 +0530 Subject: [PATCH 002/120] RISC-V: Enable CPU_IDLE drivers We force select CPU_PM and provide asm/cpuidle.h so that we can use CPU IDLE drivers for Linux RISC-V kernel. Signed-off-by: Anup Patel --- arch/riscv/Kconfig | 7 +++++++ arch/riscv/configs/defconfig | 12 +++++------- arch/riscv/configs/rv32_defconfig | 5 ++--- arch/riscv/include/asm/cpuidle.h | 24 ++++++++++++++++++++++++ arch/riscv/kernel/process.c | 3 ++- 5 files changed, 40 insertions(+), 11 deletions(-) create mode 100644 arch/riscv/include/asm/cpuidle.h diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 8fcceb8eda076a..773372252c5d75 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -42,6 +42,7 @@ config RISCV select CLONE_BACKWARDS select CLINT_TIMER if !MMU select COMMON_CLK + select CPU_PM if CPU_IDLE select EDAC_SUPPORT select GENERIC_ARCH_TOPOLOGY if SMP select GENERIC_ATOMIC64 if !64BIT @@ -552,4 +553,10 @@ source "kernel/power/Kconfig" endmenu +menu "CPU Power Management" + +source "drivers/cpuidle/Kconfig" + +endmenu + source "drivers/firmware/Kconfig" diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index 1f2be234b11cdb..57a24d40d43f81 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -13,12 +13,14 @@ CONFIG_USER_NS=y CONFIG_CHECKPOINT_RESTORE=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y +# CONFIG_SYSFS_SYSCALL is not set CONFIG_BPF_SYSCALL=y +CONFIG_SOC_MICROCHIP_POLARFIRE=y CONFIG_SOC_SIFIVE=y CONFIG_SOC_VIRT=y -CONFIG_SOC_MICROCHIP_POLARFIRE=y CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y +CONFIG_CPU_IDLE=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y @@ -66,10 +68,9 @@ CONFIG_HW_RANDOM=y CONFIG_HW_RANDOM_VIRTIO=y CONFIG_SPI=y CONFIG_SPI_SIFIVE=y +# CONFIG_PTP_1588_CLOCK is not set CONFIG_GPIOLIB=y CONFIG_GPIO_SIFIVE=y -# CONFIG_PTP_1588_CLOCK is not set -CONFIG_POWER_RESET=y CONFIG_DRM=y CONFIG_DRM_RADEON=y CONFIG_DRM_VIRTIO_GPU=y @@ -83,10 +84,10 @@ CONFIG_USB_OHCI_HCD=y CONFIG_USB_OHCI_HCD_PLATFORM=y CONFIG_USB_STORAGE=y CONFIG_USB_UAS=y +CONFIG_MMC=y CONFIG_MMC_SDHCI=y CONFIG_MMC_SDHCI_PLTFM=y CONFIG_MMC_SDHCI_CADENCE=y -CONFIG_MMC=y CONFIG_MMC_SPI=y CONFIG_RTC_CLASS=y CONFIG_VIRTIO_PCI=y @@ -135,6 +136,3 @@ CONFIG_RCU_EQS_DEBUG=y CONFIG_DEBUG_BLOCK_EXT_DEVT=y # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set -CONFIG_MEMTEST=y -# CONFIG_SYSFS_SYSCALL is not set -CONFIG_EFI=y diff --git a/arch/riscv/configs/rv32_defconfig b/arch/riscv/configs/rv32_defconfig index 8dd02b842fef8c..97d899df244511 100644 --- a/arch/riscv/configs/rv32_defconfig +++ b/arch/riscv/configs/rv32_defconfig @@ -13,12 +13,14 @@ CONFIG_USER_NS=y CONFIG_CHECKPOINT_RESTORE=y CONFIG_BLK_DEV_INITRD=y CONFIG_EXPERT=y +# CONFIG_SYSFS_SYSCALL is not set CONFIG_BPF_SYSCALL=y CONFIG_SOC_SIFIVE=y CONFIG_SOC_VIRT=y CONFIG_ARCH_RV32I=y CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y +CONFIG_CPU_IDLE=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y @@ -67,7 +69,6 @@ CONFIG_HW_RANDOM_VIRTIO=y CONFIG_SPI=y CONFIG_SPI_SIFIVE=y # CONFIG_PTP_1588_CLOCK is not set -CONFIG_POWER_RESET=y CONFIG_DRM=y CONFIG_DRM_RADEON=y CONFIG_DRM_VIRTIO_GPU=y @@ -130,5 +131,3 @@ CONFIG_RCU_EQS_DEBUG=y CONFIG_DEBUG_BLOCK_EXT_DEVT=y # CONFIG_FTRACE is not set # CONFIG_RUNTIME_TESTING_MENU is not set -CONFIG_MEMTEST=y -# CONFIG_SYSFS_SYSCALL is not set diff --git a/arch/riscv/include/asm/cpuidle.h b/arch/riscv/include/asm/cpuidle.h new file mode 100644 index 00000000000000..71fdc607d4bc52 --- /dev/null +++ b/arch/riscv/include/asm/cpuidle.h @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 Allwinner Ltd + * Copyright (C) 2021 Western Digital Corporation or its affiliates. + */ + +#ifndef _ASM_RISCV_CPUIDLE_H +#define _ASM_RISCV_CPUIDLE_H + +#include +#include + +static inline void cpu_do_idle(void) +{ + /* + * Add mb() here to ensure that all + * IO/MEM accesses are completed prior + * to entering WFI. + */ + mb(); + wait_for_interrupt(); +} + +#endif diff --git a/arch/riscv/kernel/process.c b/arch/riscv/kernel/process.c index 03ac3aa611f59c..504b496787aa4d 100644 --- a/arch/riscv/kernel/process.c +++ b/arch/riscv/kernel/process.c @@ -23,6 +23,7 @@ #include #include #include +#include register unsigned long gp_in_global __asm__("gp"); @@ -37,7 +38,7 @@ extern asmlinkage void ret_from_kernel_thread(void); void arch_cpu_idle(void) { - wait_for_interrupt(); + cpu_do_idle(); raw_local_irq_enable(); } From 7a44e45d244095b02ec7307730a28fd6eeb10caa Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:17 +0530 Subject: [PATCH 003/120] RISC-V: Rename relocate() and make it global The low-level relocate() function enables mmu and relocates execution to link-time addresses. We rename relocate() function to relocate_enable_mmu() function which is more informative. Also, the relocate_enable_mmu() function will be used in the resume path when a CPU wakes-up from a non-retentive suspend so we make it global symbol. Signed-off-by: Anup Patel --- arch/riscv/kernel/head.S | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index fce5184b22c345..8ff8412db99fb4 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -79,7 +79,8 @@ pe_head_start: .align 2 #ifdef CONFIG_MMU -relocate: + .global relocate_enable_mmu +relocate_enable_mmu: /* Relocate return address */ la a1, kernel_map XIP_FIXUP_OFFSET a1 @@ -174,7 +175,7 @@ secondary_start_common: /* Enable virtual memory and relocate to virtual address */ la a0, swapper_pg_dir XIP_FIXUP_OFFSET a0 - call relocate + call relocate_enable_mmu #endif call setup_trap_vector tail smp_callin @@ -311,7 +312,7 @@ clear_bss_done: #ifdef CONFIG_MMU la a0, early_pg_dir XIP_FIXUP_OFFSET a0 - call relocate + call relocate_enable_mmu #endif /* CONFIG_MMU */ call setup_trap_vector From e9b62bc7b13a8388f5eecc280f3f92f74ab74c51 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:18 +0530 Subject: [PATCH 004/120] RISC-V: Add arch functions for non-retentive suspend entry/exit The hart registers and CSRs are not preserved in non-retentative suspend state so we provide arch specific helper functions which will save/restore hart context upon entry/exit to non-retentive suspend state. These helper functions can be used by cpuidle drivers for non-retentive suspend entry/exit. Signed-off-by: Anup Patel --- arch/riscv/include/asm/asm.h | 17 +++++ arch/riscv/include/asm/suspend.h | 35 +++++++++ arch/riscv/kernel/Makefile | 2 + arch/riscv/kernel/asm-offsets.c | 3 + arch/riscv/kernel/head.S | 11 --- arch/riscv/kernel/suspend.c | 86 +++++++++++++++++++++ arch/riscv/kernel/suspend_entry.S | 123 ++++++++++++++++++++++++++++++ 7 files changed, 266 insertions(+), 11 deletions(-) create mode 100644 arch/riscv/include/asm/suspend.h create mode 100644 arch/riscv/kernel/suspend.c create mode 100644 arch/riscv/kernel/suspend_entry.S diff --git a/arch/riscv/include/asm/asm.h b/arch/riscv/include/asm/asm.h index 618d7c5af1a2df..6c93f2806eb716 100644 --- a/arch/riscv/include/asm/asm.h +++ b/arch/riscv/include/asm/asm.h @@ -67,4 +67,21 @@ #error "Unexpected __SIZEOF_SHORT__" #endif +#ifdef __ASSEMBLY__ + +/* Common assembly source macros */ + +#ifdef CONFIG_XIP_KERNEL +.macro XIP_FIXUP_OFFSET reg + REG_L t0, _xip_fixup + add \reg, \reg, t0 +.endm +_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET +#else +.macro XIP_FIXUP_OFFSET reg +.endm +#endif /* CONFIG_XIP_KERNEL */ + +#endif + #endif /* _ASM_RISCV_ASM_H */ diff --git a/arch/riscv/include/asm/suspend.h b/arch/riscv/include/asm/suspend.h new file mode 100644 index 00000000000000..63e9f434fb8933 --- /dev/null +++ b/arch/riscv/include/asm/suspend.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + */ + +#ifndef _ASM_RISCV_SUSPEND_H +#define _ASM_RISCV_SUSPEND_H + +#include + +struct suspend_context { + /* Saved and restored by low-level functions */ + struct pt_regs regs; + /* Saved and restored by high-level functions */ + unsigned long scratch; + unsigned long tvec; + unsigned long ie; +#ifdef CONFIG_MMU + unsigned long satp; +#endif +}; + +/* Low-level CPU suspend entry function */ +int __cpu_suspend_enter(struct suspend_context *context); + +/* High-level CPU suspend which will save context and call finish() */ +int cpu_suspend(unsigned long arg, + int (*finish)(unsigned long arg, + unsigned long entry, + unsigned long context)); + +/* Low-level CPU resume entry function */ +int __cpu_resume_enter(unsigned long hartid, unsigned long context); + +#endif diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile index d3081e4d96006d..5a2fc649ad11a1 100644 --- a/arch/riscv/kernel/Makefile +++ b/arch/riscv/kernel/Makefile @@ -47,6 +47,8 @@ obj-$(CONFIG_SMP) += cpu_ops_spinwait.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_MODULE_SECTIONS) += module-sections.o +obj-$(CONFIG_CPU_PM) += suspend_entry.o suspend.o + obj-$(CONFIG_FUNCTION_TRACER) += mcount.o ftrace.o obj-$(CONFIG_DYNAMIC_FTRACE) += mcount-dyn.o diff --git a/arch/riscv/kernel/asm-offsets.c b/arch/riscv/kernel/asm-offsets.c index 90f8ce64fa6f10..5eae19971f4765 100644 --- a/arch/riscv/kernel/asm-offsets.c +++ b/arch/riscv/kernel/asm-offsets.c @@ -10,6 +10,7 @@ #include #include #include +#include void asm_offsets(void); @@ -111,6 +112,8 @@ void asm_offsets(void) OFFSET(PT_BADADDR, pt_regs, badaddr); OFFSET(PT_CAUSE, pt_regs, cause); + OFFSET(SUSPEND_CONTEXT_REGS, suspend_context, regs); + /* * THREAD_{F,X}* might be larger than a S-type offset can handle, but * these are used in performance-sensitive assembly so we can't resort diff --git a/arch/riscv/kernel/head.S b/arch/riscv/kernel/head.S index 8ff8412db99fb4..6cb6f6eec575ba 100644 --- a/arch/riscv/kernel/head.S +++ b/arch/riscv/kernel/head.S @@ -15,17 +15,6 @@ #include #include "efi-header.S" -#ifdef CONFIG_XIP_KERNEL -.macro XIP_FIXUP_OFFSET reg - REG_L t0, _xip_fixup - add \reg, \reg, t0 -.endm -_xip_fixup: .dword CONFIG_PHYS_RAM_BASE - CONFIG_XIP_PHYS_ADDR - XIP_OFFSET -#else -.macro XIP_FIXUP_OFFSET reg -.endm -#endif /* CONFIG_XIP_KERNEL */ - __HEAD ENTRY(_start) /* diff --git a/arch/riscv/kernel/suspend.c b/arch/riscv/kernel/suspend.c new file mode 100644 index 00000000000000..49dddec30e9968 --- /dev/null +++ b/arch/riscv/kernel/suspend.c @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + */ + +#include +#include +#include + +static void suspend_save_csrs(struct suspend_context *context) +{ + context->scratch = csr_read(CSR_SCRATCH); + context->tvec = csr_read(CSR_TVEC); + context->ie = csr_read(CSR_IE); + + /* + * No need to save/restore IP CSR (i.e. MIP or SIP) because: + * + * 1. For no-MMU (M-mode) kernel, the bits in MIP are set by + * external devices (such as interrupt controller, timer, etc). + * 2. For MMU (S-mode) kernel, the bits in SIP are set by + * M-mode firmware and external devices (such as interrupt + * controller, etc). + */ + +#ifdef CONFIG_MMU + context->satp = csr_read(CSR_SATP); +#endif +} + +static void suspend_restore_csrs(struct suspend_context *context) +{ + csr_write(CSR_SCRATCH, context->scratch); + csr_write(CSR_TVEC, context->tvec); + csr_write(CSR_IE, context->ie); + +#ifdef CONFIG_MMU + csr_write(CSR_SATP, context->satp); +#endif +} + +int cpu_suspend(unsigned long arg, + int (*finish)(unsigned long arg, + unsigned long entry, + unsigned long context)) +{ + int rc = 0; + struct suspend_context context = { 0 }; + + /* Finisher should be non-NULL */ + if (!finish) + return -EINVAL; + + /* Save additional CSRs*/ + suspend_save_csrs(&context); + + /* + * Function graph tracer state gets incosistent when the kernel + * calls functions that never return (aka finishers) hence disable + * graph tracing during their execution. + */ + pause_graph_tracing(); + + /* Save context on stack */ + if (__cpu_suspend_enter(&context)) { + /* Call the finisher */ + rc = finish(arg, __pa_symbol(__cpu_resume_enter), + (ulong)&context); + + /* + * Should never reach here, unless the suspend finisher + * fails. Successful cpu_suspend() should return from + * __cpu_resume_entry() + */ + if (!rc) + rc = -EOPNOTSUPP; + } + + /* Enable function graph tracer */ + unpause_graph_tracing(); + + /* Restore additional CSRs */ + suspend_restore_csrs(&context); + + return rc; +} diff --git a/arch/riscv/kernel/suspend_entry.S b/arch/riscv/kernel/suspend_entry.S new file mode 100644 index 00000000000000..b8d20decfc280b --- /dev/null +++ b/arch/riscv/kernel/suspend_entry.S @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + */ + +#include +#include +#include +#include + + .text + .altmacro + .option norelax + +ENTRY(__cpu_suspend_enter) + /* Save registers (except A0 and T0-T6) */ + REG_S ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0) + REG_S sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0) + REG_S gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0) + REG_S tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0) + REG_S s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0) + REG_S s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0) + REG_S a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0) + REG_S a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0) + REG_S a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0) + REG_S a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0) + REG_S a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0) + REG_S a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0) + REG_S a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0) + REG_S s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0) + REG_S s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0) + REG_S s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0) + REG_S s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0) + REG_S s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0) + REG_S s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0) + REG_S s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0) + REG_S s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0) + REG_S s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0) + REG_S s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0) + + /* Save CSRs */ + csrr t0, CSR_EPC + REG_S t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0) + csrr t0, CSR_STATUS + REG_S t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0) + csrr t0, CSR_TVAL + REG_S t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0) + csrr t0, CSR_CAUSE + REG_S t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0) + + /* Return non-zero value */ + li a0, 1 + + /* Return to C code */ + ret +END(__cpu_suspend_enter) + +ENTRY(__cpu_resume_enter) + /* Load the global pointer */ + .option push + .option norelax + la gp, __global_pointer$ + .option pop + +#ifdef CONFIG_MMU + /* Save A0 and A1 */ + add t0, a0, zero + add t1, a1, zero + + /* Enable MMU */ + la a0, swapper_pg_dir + XIP_FIXUP_OFFSET a0 + call relocate_enable_mmu + + /* Restore A0 and A1 */ + add a0, t0, zero + add a1, t1, zero +#endif + + /* Make A0 point to suspend context */ + add a0, a1, zero + + /* Restore CSRs */ + REG_L t0, (SUSPEND_CONTEXT_REGS + PT_EPC)(a0) + csrw CSR_EPC, t0 + REG_L t0, (SUSPEND_CONTEXT_REGS + PT_STATUS)(a0) + csrw CSR_STATUS, t0 + REG_L t0, (SUSPEND_CONTEXT_REGS + PT_BADADDR)(a0) + csrw CSR_TVAL, t0 + REG_L t0, (SUSPEND_CONTEXT_REGS + PT_CAUSE)(a0) + csrw CSR_CAUSE, t0 + + /* Restore registers (except A0 and T0-T6) */ + REG_L ra, (SUSPEND_CONTEXT_REGS + PT_RA)(a0) + REG_L sp, (SUSPEND_CONTEXT_REGS + PT_SP)(a0) + REG_L gp, (SUSPEND_CONTEXT_REGS + PT_GP)(a0) + REG_L tp, (SUSPEND_CONTEXT_REGS + PT_TP)(a0) + REG_L s0, (SUSPEND_CONTEXT_REGS + PT_S0)(a0) + REG_L s1, (SUSPEND_CONTEXT_REGS + PT_S1)(a0) + REG_L a1, (SUSPEND_CONTEXT_REGS + PT_A1)(a0) + REG_L a2, (SUSPEND_CONTEXT_REGS + PT_A2)(a0) + REG_L a3, (SUSPEND_CONTEXT_REGS + PT_A3)(a0) + REG_L a4, (SUSPEND_CONTEXT_REGS + PT_A4)(a0) + REG_L a5, (SUSPEND_CONTEXT_REGS + PT_A5)(a0) + REG_L a6, (SUSPEND_CONTEXT_REGS + PT_A6)(a0) + REG_L a7, (SUSPEND_CONTEXT_REGS + PT_A7)(a0) + REG_L s2, (SUSPEND_CONTEXT_REGS + PT_S2)(a0) + REG_L s3, (SUSPEND_CONTEXT_REGS + PT_S3)(a0) + REG_L s4, (SUSPEND_CONTEXT_REGS + PT_S4)(a0) + REG_L s5, (SUSPEND_CONTEXT_REGS + PT_S5)(a0) + REG_L s6, (SUSPEND_CONTEXT_REGS + PT_S6)(a0) + REG_L s7, (SUSPEND_CONTEXT_REGS + PT_S7)(a0) + REG_L s8, (SUSPEND_CONTEXT_REGS + PT_S8)(a0) + REG_L s9, (SUSPEND_CONTEXT_REGS + PT_S9)(a0) + REG_L s10, (SUSPEND_CONTEXT_REGS + PT_S10)(a0) + REG_L s11, (SUSPEND_CONTEXT_REGS + PT_S11)(a0) + + /* Return zero value */ + add a0, zero, zero + + /* Return to C code */ + ret +END(__cpu_resume_enter) From 7c99495679255e3e43dc916d17f60d845aaa8054 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:19 +0530 Subject: [PATCH 005/120] RISC-V: Add SBI HSM suspend related defines We add defines related to SBI HSM suspend call and also update HSM states naming as-per latest SBI specification. Signed-off-by: Anup Patel --- arch/riscv/include/asm/sbi.h | 27 ++++++++++++++++++++++----- arch/riscv/kernel/cpu_ops_sbi.c | 2 +- 2 files changed, 23 insertions(+), 6 deletions(-) diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index 289621da4a2a8f..ab9782f8da52e0 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -62,15 +62,32 @@ enum sbi_ext_hsm_fid { SBI_EXT_HSM_HART_START = 0, SBI_EXT_HSM_HART_STOP, SBI_EXT_HSM_HART_STATUS, + SBI_EXT_HSM_HART_SUSPEND, }; -enum sbi_hsm_hart_status { - SBI_HSM_HART_STATUS_STARTED = 0, - SBI_HSM_HART_STATUS_STOPPED, - SBI_HSM_HART_STATUS_START_PENDING, - SBI_HSM_HART_STATUS_STOP_PENDING, +enum sbi_hsm_hart_state { + SBI_HSM_STATE_STARTED = 0, + SBI_HSM_STATE_STOPPED, + SBI_HSM_STATE_START_PENDING, + SBI_HSM_STATE_STOP_PENDING, + SBI_HSM_STATE_SUSPENDED, + SBI_HSM_STATE_SUSPEND_PENDING, + SBI_HSM_STATE_RESUME_PENDING, }; +#define SBI_HSM_SUSP_BASE_MASK 0x7fffffff +#define SBI_HSM_SUSP_NON_RET_BIT 0x80000000 +#define SBI_HSM_SUSP_PLAT_BASE 0x10000000 + +#define SBI_HSM_SUSPEND_RET_DEFAULT 0x00000000 +#define SBI_HSM_SUSPEND_RET_PLATFORM SBI_HSM_SUSP_PLAT_BASE +#define SBI_HSM_SUSPEND_RET_LAST SBI_HSM_SUSP_BASE_MASK +#define SBI_HSM_SUSPEND_NON_RET_DEFAULT SBI_HSM_SUSP_NON_RET_BIT +#define SBI_HSM_SUSPEND_NON_RET_PLATFORM (SBI_HSM_SUSP_NON_RET_BIT | \ + SBI_HSM_SUSP_PLAT_BASE) +#define SBI_HSM_SUSPEND_NON_RET_LAST (SBI_HSM_SUSP_NON_RET_BIT | \ + SBI_HSM_SUSP_BASE_MASK) + enum sbi_ext_srst_fid { SBI_EXT_SRST_RESET = 0, }; diff --git a/arch/riscv/kernel/cpu_ops_sbi.c b/arch/riscv/kernel/cpu_ops_sbi.c index 685fae72b7f5c7..5fd90f03a3e9bc 100644 --- a/arch/riscv/kernel/cpu_ops_sbi.c +++ b/arch/riscv/kernel/cpu_ops_sbi.c @@ -97,7 +97,7 @@ static int sbi_cpu_is_stopped(unsigned int cpuid) rc = sbi_hsm_hart_get_status(hartid); - if (rc == SBI_HSM_HART_STATUS_STOPPED) + if (rc == SBI_HSM_STATE_STOPPED) return 0; return rc; } From e87de219858afcc6082a737cddd60b2357b10dd8 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:20 +0530 Subject: [PATCH 006/120] cpuidle: Factor-out power domain related code from PSCI domain driver The generic power domain related code in PSCI domain driver is largely independent of PSCI and can be shared with RISC-V SBI domain driver hence we factor-out this code into dt_idle_genpd.c and dt_idle_genpd.h. Signed-off-by: Anup Patel --- drivers/cpuidle/Kconfig | 4 + drivers/cpuidle/Kconfig.arm | 1 + drivers/cpuidle/Makefile | 1 + drivers/cpuidle/cpuidle-psci-domain.c | 138 +------------------ drivers/cpuidle/cpuidle-psci.h | 15 ++- drivers/cpuidle/dt_idle_genpd.c | 182 ++++++++++++++++++++++++++ drivers/cpuidle/dt_idle_genpd.h | 50 +++++++ 7 files changed, 256 insertions(+), 135 deletions(-) create mode 100644 drivers/cpuidle/dt_idle_genpd.c create mode 100644 drivers/cpuidle/dt_idle_genpd.h diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index c0aeedd66f022a..f1afe7ab6b54c5 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -47,6 +47,10 @@ config CPU_IDLE_GOV_HALTPOLL config DT_IDLE_STATES bool +config DT_IDLE_GENPD + depends on PM_GENERIC_DOMAINS_OF + bool + menu "ARM CPU Idle Drivers" depends on ARM || ARM64 source "drivers/cpuidle/Kconfig.arm" diff --git a/drivers/cpuidle/Kconfig.arm b/drivers/cpuidle/Kconfig.arm index 334f83e56120c0..be12a9ca78f029 100644 --- a/drivers/cpuidle/Kconfig.arm +++ b/drivers/cpuidle/Kconfig.arm @@ -27,6 +27,7 @@ config ARM_PSCI_CPUIDLE_DOMAIN bool "PSCI CPU idle Domain" depends on ARM_PSCI_CPUIDLE depends on PM_GENERIC_DOMAINS_OF + select DT_IDLE_GENPD default y help Select this to enable the PSCI based CPUidle driver to use PM domains, diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 26bbc5e7412366..11a26cef279ff0 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -6,6 +6,7 @@ obj-y += cpuidle.o driver.o governor.o sysfs.o governors/ obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o obj-$(CONFIG_DT_IDLE_STATES) += dt_idle_states.o +obj-$(CONFIG_DT_IDLE_GENPD) += dt_idle_genpd.o obj-$(CONFIG_ARCH_HAS_CPU_RELAX) += poll_state.o obj-$(CONFIG_HALTPOLL_CPUIDLE) += cpuidle-haltpoll.o diff --git a/drivers/cpuidle/cpuidle-psci-domain.c b/drivers/cpuidle/cpuidle-psci-domain.c index ff2c3f8e4668ae..3ceec0ee9f02ac 100644 --- a/drivers/cpuidle/cpuidle-psci-domain.c +++ b/drivers/cpuidle/cpuidle-psci-domain.c @@ -47,73 +47,14 @@ static int psci_pd_power_off(struct generic_pm_domain *pd) return 0; } -static int psci_pd_parse_state_nodes(struct genpd_power_state *states, - int state_count) -{ - int i, ret; - u32 psci_state, *psci_state_buf; - - for (i = 0; i < state_count; i++) { - ret = psci_dt_parse_state_node(to_of_node(states[i].fwnode), - &psci_state); - if (ret) - goto free_state; - - psci_state_buf = kmalloc(sizeof(u32), GFP_KERNEL); - if (!psci_state_buf) { - ret = -ENOMEM; - goto free_state; - } - *psci_state_buf = psci_state; - states[i].data = psci_state_buf; - } - - return 0; - -free_state: - i--; - for (; i >= 0; i--) - kfree(states[i].data); - return ret; -} - -static int psci_pd_parse_states(struct device_node *np, - struct genpd_power_state **states, int *state_count) -{ - int ret; - - /* Parse the domain idle states. */ - ret = of_genpd_parse_idle_states(np, states, state_count); - if (ret) - return ret; - - /* Fill out the PSCI specifics for each found state. */ - ret = psci_pd_parse_state_nodes(*states, *state_count); - if (ret) - kfree(*states); - - return ret; -} - -static void psci_pd_free_states(struct genpd_power_state *states, - unsigned int state_count) -{ - int i; - - for (i = 0; i < state_count; i++) - kfree(states[i].data); - kfree(states); -} - static int psci_pd_init(struct device_node *np, bool use_osi) { struct generic_pm_domain *pd; struct psci_pd_provider *pd_provider; struct dev_power_governor *pd_gov; - struct genpd_power_state *states = NULL; int ret = -ENOMEM, state_count = 0; - pd = kzalloc(sizeof(*pd), GFP_KERNEL); + pd = dt_pd_alloc(np, psci_dt_parse_state_node); if (!pd) goto out; @@ -121,22 +62,6 @@ static int psci_pd_init(struct device_node *np, bool use_osi) if (!pd_provider) goto free_pd; - pd->name = kasprintf(GFP_KERNEL, "%pOF", np); - if (!pd->name) - goto free_pd_prov; - - /* - * Parse the domain idle states and let genpd manage the state selection - * for those being compatible with "domain-idle-state". - */ - ret = psci_pd_parse_states(np, &states, &state_count); - if (ret) - goto free_name; - - pd->free_states = psci_pd_free_states; - pd->name = kbasename(pd->name); - pd->states = states; - pd->state_count = state_count; pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN; /* Allow power off when OSI has been successfully enabled. */ @@ -149,10 +74,8 @@ static int psci_pd_init(struct device_node *np, bool use_osi) pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL; ret = pm_genpd_init(pd, pd_gov, false); - if (ret) { - psci_pd_free_states(states, state_count); - goto free_name; - } + if (ret) + goto free_pd_prov; ret = of_genpd_add_provider_simple(np, pd); if (ret) @@ -166,12 +89,10 @@ static int psci_pd_init(struct device_node *np, bool use_osi) remove_pd: pm_genpd_remove(pd); -free_name: - kfree(pd->name); free_pd_prov: kfree(pd_provider); free_pd: - kfree(pd); + dt_pd_free(pd); out: pr_err("failed to init PM domain ret=%d %pOF\n", ret, np); return ret; @@ -195,30 +116,6 @@ static void psci_pd_remove(void) } } -static int psci_pd_init_topology(struct device_node *np) -{ - struct device_node *node; - struct of_phandle_args child, parent; - int ret; - - for_each_child_of_node(np, node) { - if (of_parse_phandle_with_args(node, "power-domains", - "#power-domain-cells", 0, &parent)) - continue; - - child.np = node; - child.args_count = 0; - ret = of_genpd_add_subdomain(&parent, &child); - of_node_put(parent.np); - if (ret) { - of_node_put(node); - return ret; - } - } - - return 0; -} - static bool psci_pd_try_set_osi_mode(void) { int ret; @@ -282,7 +179,7 @@ static int psci_cpuidle_domain_probe(struct platform_device *pdev) goto no_pd; /* Link genpd masters/subdomains to model the CPU topology. */ - ret = psci_pd_init_topology(np); + ret = dt_pd_init_topology(np); if (ret) goto remove_pd; @@ -314,28 +211,3 @@ static int __init psci_idle_init_domains(void) return platform_driver_register(&psci_cpuidle_domain_driver); } subsys_initcall(psci_idle_init_domains); - -struct device *psci_dt_attach_cpu(int cpu) -{ - struct device *dev; - - dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), "psci"); - if (IS_ERR_OR_NULL(dev)) - return dev; - - pm_runtime_irq_safe(dev); - if (cpu_online(cpu)) - pm_runtime_get_sync(dev); - - dev_pm_syscore_device(dev, true); - - return dev; -} - -void psci_dt_detach_cpu(struct device *dev) -{ - if (IS_ERR_OR_NULL(dev)) - return; - - dev_pm_domain_detach(dev, false); -} diff --git a/drivers/cpuidle/cpuidle-psci.h b/drivers/cpuidle/cpuidle-psci.h index d8e925e84c27af..70de1e3c00af07 100644 --- a/drivers/cpuidle/cpuidle-psci.h +++ b/drivers/cpuidle/cpuidle-psci.h @@ -10,8 +10,19 @@ void psci_set_domain_state(u32 state); int psci_dt_parse_state_node(struct device_node *np, u32 *state); #ifdef CONFIG_ARM_PSCI_CPUIDLE_DOMAIN -struct device *psci_dt_attach_cpu(int cpu); -void psci_dt_detach_cpu(struct device *dev); + +#include "dt_idle_genpd.h" + +static inline struct device *psci_dt_attach_cpu(int cpu) +{ + return dt_idle_genpd_attach_cpu(cpu, "psci"); +} + +static inline void psci_dt_detach_cpu(struct device *dev) +{ + dt_idle_genpd_detach_cpu(dev); +} + #else static inline struct device *psci_dt_attach_cpu(int cpu) { return NULL; } static inline void psci_dt_detach_cpu(struct device *dev) { } diff --git a/drivers/cpuidle/dt_idle_genpd.c b/drivers/cpuidle/dt_idle_genpd.c new file mode 100644 index 00000000000000..5a901773db60f4 --- /dev/null +++ b/drivers/cpuidle/dt_idle_genpd.c @@ -0,0 +1,182 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * PM domains for CPUs via genpd. + * + * Copyright (C) 2019 Linaro Ltd. + * Author: Ulf Hansson + * + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + */ + +#define pr_fmt(fmt) "dt-idle-genpd: " fmt + +#include +#include +#include +#include +#include +#include +#include + +#include "dt_idle_genpd.h" + +static int dt_pd_parse_state_nodes( + int (*parse_state)(struct device_node *, u32 *), + struct genpd_power_state *states, int state_count) +{ + int i, ret; + u32 state, *state_buf; + + for (i = 0; i < state_count; i++) { + ret = parse_state(to_of_node(states[i].fwnode), &state); + if (ret) + goto free_state; + + state_buf = kmalloc(sizeof(u32), GFP_KERNEL); + if (!state_buf) { + ret = -ENOMEM; + goto free_state; + } + *state_buf = state; + states[i].data = state_buf; + } + + return 0; + +free_state: + i--; + for (; i >= 0; i--) + kfree(states[i].data); + return ret; +} + +static int dt_pd_parse_states(struct device_node *np, + int (*parse_state)(struct device_node *, u32 *), + struct genpd_power_state **states, + int *state_count) +{ + int ret; + + /* Parse the domain idle states. */ + ret = of_genpd_parse_idle_states(np, states, state_count); + if (ret) + return ret; + + /* Fill out the dt specifics for each found state. */ + ret = dt_pd_parse_state_nodes(parse_state, *states, *state_count); + if (ret) + kfree(*states); + + return ret; +} + +static void dt_pd_free_states(struct genpd_power_state *states, + unsigned int state_count) +{ + int i; + + for (i = 0; i < state_count; i++) + kfree(states[i].data); + kfree(states); +} + +void dt_pd_free(struct generic_pm_domain *pd) +{ + dt_pd_free_states(pd->states, pd->state_count); + kfree(pd->name); + kfree(pd); +} +EXPORT_SYMBOL_GPL(dt_pd_free); + +struct generic_pm_domain *dt_pd_alloc(struct device_node *np, + int (*parse_state)(struct device_node *, u32 *)) +{ + struct generic_pm_domain *pd; + struct genpd_power_state *states = NULL; + int ret, state_count = 0; + + pd = kzalloc(sizeof(*pd), GFP_KERNEL); + if (!pd) + goto out; + + pd->name = kasprintf(GFP_KERNEL, "%pOF", np); + if (!pd->name) + goto free_pd; + + /* + * Parse the domain idle states and let genpd manage the state selection + * for those being compatible with "domain-idle-state". + */ + ret = dt_pd_parse_states(np, parse_state, &states, &state_count); + if (ret) + goto free_name; + + pd->free_states = dt_pd_free_states; + pd->name = kbasename(pd->name); + pd->states = states; + pd->state_count = state_count; + + pr_debug("alloc PM domain %s\n", pd->name); + return pd; + +free_name: + kfree(pd->name); +free_pd: + kfree(pd); +out: + pr_err("failed to alloc PM domain %pOF\n", np); + return NULL; +} +EXPORT_SYMBOL_GPL(dt_pd_alloc); + +int dt_pd_init_topology(struct device_node *np) +{ + struct device_node *node; + struct of_phandle_args child, parent; + int ret; + + for_each_child_of_node(np, node) { + if (of_parse_phandle_with_args(node, "power-domains", + "#power-domain-cells", 0, &parent)) + continue; + + child.np = node; + child.args_count = 0; + ret = of_genpd_add_subdomain(&parent, &child); + of_node_put(parent.np); + if (ret) { + of_node_put(node); + return ret; + } + } + + return 0; +} +EXPORT_SYMBOL_GPL(dt_pd_init_topology); + +struct device *dt_idle_genpd_attach_cpu(int cpu, const char *name) +{ + struct device *dev; + + dev = dev_pm_domain_attach_by_name(get_cpu_device(cpu), name); + if (IS_ERR_OR_NULL(dev)) + return dev; + + pm_runtime_irq_safe(dev); + if (cpu_online(cpu)) + pm_runtime_get_sync(dev); + + dev_pm_syscore_device(dev, true); + + return dev; +} +EXPORT_SYMBOL_GPL(dt_idle_genpd_attach_cpu); + +void dt_idle_genpd_detach_cpu(struct device *dev) +{ + if (IS_ERR_OR_NULL(dev)) + return; + + dev_pm_domain_detach(dev, false); +} +EXPORT_SYMBOL_GPL(dt_idle_genpd_detach_cpu); diff --git a/drivers/cpuidle/dt_idle_genpd.h b/drivers/cpuidle/dt_idle_genpd.h new file mode 100644 index 00000000000000..5e113625cc69b1 --- /dev/null +++ b/drivers/cpuidle/dt_idle_genpd.h @@ -0,0 +1,50 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __DT_IDLE_GENPD +#define __DT_IDLE_GENPD + +struct device_node; +struct generic_pm_domain; + +#ifdef CONFIG_DT_IDLE_GENPD + +void dt_pd_free(struct generic_pm_domain *pd); + +struct generic_pm_domain *dt_pd_alloc(struct device_node *np, + int (*parse_state)(struct device_node *, u32 *)); + +int dt_pd_init_topology(struct device_node *np); + +struct device *dt_idle_genpd_attach_cpu(int cpu, const char *name); + +void dt_idle_genpd_detach_cpu(struct device *dev); + +#else + +static inline void dt_pd_free(struct generic_pm_domain *pd) +{ +} + +static inline struct generic_pm_domain *dt_pd_alloc(struct device_node *np, + int (*parse_state)(struct device_node *, u32 *)) +{ + return NULL; +} + +static inline int dt_pd_init_topology(struct device_node *np) +{ + return 0; +} + +static inline struct device *dt_idle_genpd_attach_cpu(int cpu, + const char *name) +{ + return NULL; +} + +static inline void dt_idle_genpd_detach_cpu(struct device *dev) +{ +} + +#endif + +#endif From 2aeeefb443e9968eb75e19e1d356dca165bc84fa Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:21 +0530 Subject: [PATCH 007/120] cpuidle: Add RISC-V SBI CPU idle driver The RISC-V SBI HSM extension provides HSM suspend call which can be used by Linux RISC-V to enter platform specific low-power state. This patch adds a CPU idle driver based on RISC-V SBI calls which will populate idle states from device tree and use SBI calls to entry these idle states. Signed-off-by: Anup Patel --- MAINTAINERS | 7 + drivers/cpuidle/Kconfig | 5 + drivers/cpuidle/Kconfig.riscv | 15 + drivers/cpuidle/Makefile | 4 + drivers/cpuidle/cpuidle-sbi.c | 625 ++++++++++++++++++++++++++++++++++ 5 files changed, 656 insertions(+) create mode 100644 drivers/cpuidle/Kconfig.riscv create mode 100644 drivers/cpuidle/cpuidle-sbi.c diff --git a/MAINTAINERS b/MAINTAINERS index c9467d2839f5e8..bd26af81094d5e 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -4866,6 +4866,13 @@ S: Supported F: drivers/cpuidle/cpuidle-psci.h F: drivers/cpuidle/cpuidle-psci-domain.c +CPUIDLE DRIVER - RISC-V SBI +M: Anup Patel +L: linux-pm@vger.kernel.org +L: linux-riscv@lists.infradead.org +S: Supported +F: drivers/cpuidle/cpuidle-sbi.c + CRAMFS FILESYSTEM M: Nicolas Pitre S: Maintained diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index f1afe7ab6b54c5..ff71dd662880d9 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -66,6 +66,11 @@ depends on PPC source "drivers/cpuidle/Kconfig.powerpc" endmenu +menu "RISC-V CPU Idle Drivers" +depends on RISCV +source "drivers/cpuidle/Kconfig.riscv" +endmenu + config HALTPOLL_CPUIDLE tristate "Halt poll cpuidle driver" depends on X86 && KVM_GUEST diff --git a/drivers/cpuidle/Kconfig.riscv b/drivers/cpuidle/Kconfig.riscv new file mode 100644 index 00000000000000..78518c26af74ca --- /dev/null +++ b/drivers/cpuidle/Kconfig.riscv @@ -0,0 +1,15 @@ +# SPDX-License-Identifier: GPL-2.0-only +# +# RISC-V CPU Idle drivers +# + +config RISCV_SBI_CPUIDLE + bool "RISC-V SBI CPU idle Driver" + depends on RISCV_SBI + select DT_IDLE_STATES + select CPU_IDLE_MULTIPLE_DRIVERS + select DT_IDLE_GENPD if PM_GENERIC_DOMAINS_OF + help + Select this option to enable RISC-V SBI firmware based CPU idle + driver for RISC-V systems. This drivers also supports hierarchical + DT based layout of the idle state. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 11a26cef279ff0..a36922c185105f 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -35,3 +35,7 @@ obj-$(CONFIG_MIPS_CPS_CPUIDLE) += cpuidle-cps.o # POWERPC drivers obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o + +############################################################################### +# RISC-V drivers +obj-$(CONFIG_RISCV_SBI_CPUIDLE) += cpuidle-sbi.o diff --git a/drivers/cpuidle/cpuidle-sbi.c b/drivers/cpuidle/cpuidle-sbi.c new file mode 100644 index 00000000000000..b04664c8877db4 --- /dev/null +++ b/drivers/cpuidle/cpuidle-sbi.c @@ -0,0 +1,625 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * RISC-V SBI CPU idle driver. + * + * Copyright (c) 2021 Western Digital Corporation or its affiliates. + */ + +#define pr_fmt(fmt) "cpuidle-sbi: " fmt + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "dt_idle_states.h" +#include "dt_idle_genpd.h" + +struct sbi_cpuidle_data { + u32 *states; + struct device *dev; +}; + +struct sbi_domain_state { + bool available; + u32 state; +}; + +static DEFINE_PER_CPU_READ_MOSTLY(struct sbi_cpuidle_data, sbi_cpuidle_data); +static DEFINE_PER_CPU(struct sbi_domain_state, domain_state); +static bool sbi_cpuidle_use_osi; +static bool sbi_cpuidle_use_cpuhp; +static bool sbi_cpuidle_pd_allow_domain_state; + +static inline void sbi_set_domain_state(u32 state) +{ + struct sbi_domain_state *data = this_cpu_ptr(&domain_state); + + data->available = true; + data->state = state; +} + +static inline u32 sbi_get_domain_state(void) +{ + struct sbi_domain_state *data = this_cpu_ptr(&domain_state); + + return data->state; +} + +static inline void sbi_clear_domain_state(void) +{ + struct sbi_domain_state *data = this_cpu_ptr(&domain_state); + + data->available = false; +} + +static inline bool sbi_is_domain_state_available(void) +{ + struct sbi_domain_state *data = this_cpu_ptr(&domain_state); + + return data->available; +} + +static int sbi_suspend_finisher(unsigned long suspend_type, + unsigned long resume_addr, + unsigned long opaque) +{ + struct sbiret ret; + + ret = sbi_ecall(SBI_EXT_HSM, SBI_EXT_HSM_HART_SUSPEND, + suspend_type, resume_addr, opaque, 0, 0, 0); + + return (ret.error) ? sbi_err_map_linux_errno(ret.error) : 0; +} + +static int sbi_suspend(u32 state) +{ + if (state & SBI_HSM_SUSP_NON_RET_BIT) + return cpu_suspend(state, sbi_suspend_finisher); + else + return sbi_suspend_finisher(state, 0, 0); +} + +static int sbi_cpuidle_enter_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) +{ + u32 *states = __this_cpu_read(sbi_cpuidle_data.states); + + return CPU_PM_CPU_IDLE_ENTER_PARAM(sbi_suspend, idx, states[idx]); +} + +static int __sbi_enter_domain_idle_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx, + bool s2idle) +{ + struct sbi_cpuidle_data *data = this_cpu_ptr(&sbi_cpuidle_data); + u32 *states = data->states; + struct device *pd_dev = data->dev; + u32 state; + int ret; + + ret = cpu_pm_enter(); + if (ret) + return -1; + + /* Do runtime PM to manage a hierarchical CPU toplogy. */ + rcu_irq_enter_irqson(); + if (s2idle) + dev_pm_genpd_suspend(pd_dev); + else + pm_runtime_put_sync_suspend(pd_dev); + rcu_irq_exit_irqson(); + + if (sbi_is_domain_state_available()) + state = sbi_get_domain_state(); + else + state = states[idx]; + + ret = sbi_suspend(state) ? -1 : idx; + + rcu_irq_enter_irqson(); + if (s2idle) + dev_pm_genpd_resume(pd_dev); + else + pm_runtime_get_sync(pd_dev); + rcu_irq_exit_irqson(); + + cpu_pm_exit(); + + /* Clear the domain state to start fresh when back from idle. */ + sbi_clear_domain_state(); + return ret; +} + +static int sbi_enter_domain_idle_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int idx) +{ + return __sbi_enter_domain_idle_state(dev, drv, idx, false); +} + +static int sbi_enter_s2idle_domain_idle_state(struct cpuidle_device *dev, + struct cpuidle_driver *drv, + int idx) +{ + return __sbi_enter_domain_idle_state(dev, drv, idx, true); +} + +static int sbi_cpuidle_cpuhp_up(unsigned int cpu) +{ + struct device *pd_dev = __this_cpu_read(sbi_cpuidle_data.dev); + + if (pd_dev) + pm_runtime_get_sync(pd_dev); + + return 0; +} + +static int sbi_cpuidle_cpuhp_down(unsigned int cpu) +{ + struct device *pd_dev = __this_cpu_read(sbi_cpuidle_data.dev); + + if (pd_dev) { + pm_runtime_put_sync(pd_dev); + /* Clear domain state to start fresh at next online. */ + sbi_clear_domain_state(); + } + + return 0; +} + +static void sbi_idle_init_cpuhp(void) +{ + int err; + + if (!sbi_cpuidle_use_cpuhp) + return; + + err = cpuhp_setup_state_nocalls(CPUHP_AP_CPU_PM_STARTING, + "cpuidle/sbi:online", + sbi_cpuidle_cpuhp_up, + sbi_cpuidle_cpuhp_down); + if (err) + pr_warn("Failed %d while setup cpuhp state\n", err); +} + +static const struct of_device_id sbi_cpuidle_state_match[] = { + { .compatible = "riscv,idle-state", + .data = sbi_cpuidle_enter_state }, + { }, +}; + +static bool sbi_suspend_state_is_valid(u32 state) +{ + if (state > SBI_HSM_SUSPEND_RET_DEFAULT && + state < SBI_HSM_SUSPEND_RET_PLATFORM) + return false; + if (state > SBI_HSM_SUSPEND_NON_RET_DEFAULT && + state < SBI_HSM_SUSPEND_NON_RET_PLATFORM) + return false; + return true; +} + +static int sbi_dt_parse_state_node(struct device_node *np, u32 *state) +{ + int err = of_property_read_u32(np, "riscv,sbi-suspend-param", state); + + if (err) { + pr_warn("%pOF missing riscv,sbi-suspend-param property\n", np); + return err; + } + + if (!sbi_suspend_state_is_valid(*state)) { + pr_warn("Invalid SBI suspend state %#x\n", *state); + return -EINVAL; + } + + return 0; +} + +static int sbi_dt_cpu_init_topology(struct cpuidle_driver *drv, + struct sbi_cpuidle_data *data, + unsigned int state_count, int cpu) +{ + /* Currently limit the hierarchical topology to be used in OSI mode. */ + if (!sbi_cpuidle_use_osi) + return 0; + + data->dev = dt_idle_genpd_attach_cpu(cpu, "sbi"); + if (IS_ERR_OR_NULL(data->dev)) + return PTR_ERR_OR_ZERO(data->dev); + + /* + * Using the deepest state for the CPU to trigger a potential selection + * of a shared state for the domain, assumes the domain states are all + * deeper states. + */ + drv->states[state_count - 1].enter = sbi_enter_domain_idle_state; + drv->states[state_count - 1].enter_s2idle = sbi_enter_s2idle_domain_idle_state; + sbi_cpuidle_use_cpuhp = true; + + return 0; +} + +static int sbi_cpuidle_dt_init_states(struct device *dev, + struct cpuidle_driver *drv, + unsigned int cpu, + unsigned int state_count) +{ + struct sbi_cpuidle_data *data = per_cpu_ptr(&sbi_cpuidle_data, cpu); + struct device_node *state_node; + struct device_node *cpu_node; + u32 *states; + int i, ret; + + cpu_node = of_cpu_device_node_get(cpu); + if (!cpu_node) + return -ENODEV; + + states = devm_kcalloc(dev, state_count, sizeof(*states), GFP_KERNEL); + if (!states) { + ret = -ENOMEM; + goto fail; + } + + /* Parse SBI specific details from state DT nodes */ + for (i = 1; i < state_count; i++) { + state_node = of_get_cpu_state_node(cpu_node, i - 1); + if (!state_node) + break; + + ret = sbi_dt_parse_state_node(state_node, &states[i]); + of_node_put(state_node); + + if (ret) + return ret; + + pr_debug("sbi-state %#x index %d\n", states[i], i); + } + if (i != state_count) { + ret = -ENODEV; + goto fail; + } + + /* Initialize optional data, used for the hierarchical topology. */ + ret = sbi_dt_cpu_init_topology(drv, data, state_count, cpu); + if (ret < 0) + return ret; + + /* Store states in the per-cpu struct. */ + data->states = states; + +fail: + of_node_put(cpu_node); + + return ret; +} + +static void sbi_cpuidle_deinit_cpu(int cpu) +{ + struct sbi_cpuidle_data *data = per_cpu_ptr(&sbi_cpuidle_data, cpu); + + dt_idle_genpd_detach_cpu(data->dev); + sbi_cpuidle_use_cpuhp = false; +} + +static int sbi_cpuidle_init_cpu(struct device *dev, int cpu) +{ + struct cpuidle_driver *drv; + unsigned int state_count = 0; + int ret = 0; + + drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + drv->name = "sbi_cpuidle"; + drv->owner = THIS_MODULE; + drv->cpumask = (struct cpumask *)cpumask_of(cpu); + + /* RISC-V architectural WFI to be represented as state index 0. */ + drv->states[0].enter = sbi_cpuidle_enter_state; + drv->states[0].exit_latency = 1; + drv->states[0].target_residency = 1; + drv->states[0].power_usage = UINT_MAX; + strcpy(drv->states[0].name, "WFI"); + strcpy(drv->states[0].desc, "RISC-V WFI"); + + /* + * If no DT idle states are detected (ret == 0) let the driver + * initialization fail accordingly since there is no reason to + * initialize the idle driver if only wfi is supported, the + * default archictectural back-end already executes wfi + * on idle entry. + */ + ret = dt_init_idle_driver(drv, sbi_cpuidle_state_match, 1); + if (ret <= 0) { + pr_debug("HART%ld: failed to parse DT idle states\n", + cpuid_to_hartid_map(cpu)); + return ret ? : -ENODEV; + } + state_count = ret + 1; /* Include WFI state as well */ + + /* Initialize idle states from DT. */ + ret = sbi_cpuidle_dt_init_states(dev, drv, cpu, state_count); + if (ret) { + pr_err("HART%ld: failed to init idle states\n", + cpuid_to_hartid_map(cpu)); + return ret; + } + + ret = cpuidle_register(drv, NULL); + if (ret) + goto deinit; + + cpuidle_cooling_register(drv); + + return 0; +deinit: + sbi_cpuidle_deinit_cpu(cpu); + return ret; +} + +static void sbi_cpuidle_domain_sync_state(struct device *dev) +{ + /* + * All devices have now been attached/probed to the PM domain + * topology, hence it's fine to allow domain states to be picked. + */ + sbi_cpuidle_pd_allow_domain_state = true; +} + +#ifdef CONFIG_DT_IDLE_GENPD + +static int sbi_cpuidle_pd_power_off(struct generic_pm_domain *pd) +{ + struct genpd_power_state *state = &pd->states[pd->state_idx]; + u32 *pd_state; + + if (!state->data) + return 0; + + if (!sbi_cpuidle_pd_allow_domain_state) + return -EBUSY; + + /* OSI mode is enabled, set the corresponding domain state. */ + pd_state = state->data; + sbi_set_domain_state(*pd_state); + + return 0; +} + +struct sbi_pd_provider { + struct list_head link; + struct device_node *node; +}; + +static LIST_HEAD(sbi_pd_providers); + +static int sbi_pd_init(struct device_node *np) +{ + struct generic_pm_domain *pd; + struct sbi_pd_provider *pd_provider; + struct dev_power_governor *pd_gov; + int ret = -ENOMEM, state_count = 0; + + pd = dt_pd_alloc(np, sbi_dt_parse_state_node); + if (!pd) + goto out; + + pd_provider = kzalloc(sizeof(*pd_provider), GFP_KERNEL); + if (!pd_provider) + goto free_pd; + + pd->flags |= GENPD_FLAG_IRQ_SAFE | GENPD_FLAG_CPU_DOMAIN; + + /* Allow power off when OSI is available. */ + if (sbi_cpuidle_use_osi) + pd->power_off = sbi_cpuidle_pd_power_off; + else + pd->flags |= GENPD_FLAG_ALWAYS_ON; + + /* Use governor for CPU PM domains if it has some states to manage. */ + pd_gov = state_count > 0 ? &pm_domain_cpu_gov : NULL; + + ret = pm_genpd_init(pd, pd_gov, false); + if (ret) + goto free_pd_prov; + + ret = of_genpd_add_provider_simple(np, pd); + if (ret) + goto remove_pd; + + pd_provider->node = of_node_get(np); + list_add(&pd_provider->link, &sbi_pd_providers); + + pr_debug("init PM domain %s\n", pd->name); + return 0; + +remove_pd: + pm_genpd_remove(pd); +free_pd_prov: + kfree(pd_provider); +free_pd: + dt_pd_free(pd); +out: + pr_err("failed to init PM domain ret=%d %pOF\n", ret, np); + return ret; +} + +static void sbi_pd_remove(void) +{ + struct sbi_pd_provider *pd_provider, *it; + struct generic_pm_domain *genpd; + + list_for_each_entry_safe(pd_provider, it, &sbi_pd_providers, link) { + of_genpd_del_provider(pd_provider->node); + + genpd = of_genpd_remove_last(pd_provider->node); + if (!IS_ERR(genpd)) + kfree(genpd); + + of_node_put(pd_provider->node); + list_del(&pd_provider->link); + kfree(pd_provider); + } +} + +static int sbi_genpd_probe(struct device_node *np) +{ + struct device_node *node; + int ret = 0, pd_count = 0; + + if (!np) + return -ENODEV; + + /* + * Parse child nodes for the "#power-domain-cells" property and + * initialize a genpd/genpd-of-provider pair when it's found. + */ + for_each_child_of_node(np, node) { + if (!of_find_property(node, "#power-domain-cells", NULL)) + continue; + + ret = sbi_pd_init(node); + if (ret) + goto put_node; + + pd_count++; + } + + /* Bail out if not using the hierarchical CPU topology. */ + if (!pd_count) + goto no_pd; + + /* Link genpd masters/subdomains to model the CPU topology. */ + ret = dt_pd_init_topology(np); + if (ret) + goto remove_pd; + + return 0; + +put_node: + of_node_put(node); +remove_pd: + sbi_pd_remove(); + pr_err("failed to create CPU PM domains ret=%d\n", ret); +no_pd: + return ret; +} + +#else + +static inline int sbi_genpd_probe(struct device_node *np) +{ + return 0; +} + +#endif + +static int sbi_cpuidle_probe(struct platform_device *pdev) +{ + int cpu, ret; + struct cpuidle_driver *drv; + struct cpuidle_device *dev; + struct device_node *np, *pds_node; + + /* Detect OSI support based on CPU DT nodes */ + sbi_cpuidle_use_osi = true; + for_each_possible_cpu(cpu) { + np = of_cpu_device_node_get(cpu); + if (np && + of_find_property(np, "power-domains", NULL) && + of_find_property(np, "power-domain-names", NULL)) { + continue; + } else { + sbi_cpuidle_use_osi = false; + break; + } + } + + /* Populate generic power domains from DT nodes */ + pds_node = of_find_node_by_path("/cpus/power-domains"); + if (pds_node) { + ret = sbi_genpd_probe(pds_node); + of_node_put(pds_node); + if (ret) + return ret; + } + + /* Initialize CPU idle driver for each CPU */ + for_each_possible_cpu(cpu) { + ret = sbi_cpuidle_init_cpu(&pdev->dev, cpu); + if (ret) { + pr_debug("HART%ld: idle driver init failed\n", + cpuid_to_hartid_map(cpu)); + goto out_fail; + } + } + + /* Setup CPU hotplut notifiers */ + sbi_idle_init_cpuhp(); + + pr_info("idle driver registered for all CPUs\n"); + + return 0; + +out_fail: + while (--cpu >= 0) { + dev = per_cpu(cpuidle_devices, cpu); + drv = cpuidle_get_cpu_driver(dev); + cpuidle_unregister(drv); + sbi_cpuidle_deinit_cpu(cpu); + } + + return ret; +} + +static struct platform_driver sbi_cpuidle_driver = { + .probe = sbi_cpuidle_probe, + .driver = { + .name = "sbi-cpuidle", + .sync_state = sbi_cpuidle_domain_sync_state, + }, +}; + +static int __init sbi_cpuidle_init(void) +{ + int ret; + struct platform_device *pdev; + + /* + * The SBI HSM suspend function is only available when: + * 1) SBI version is 0.3 or higher + * 2) SBI HSM extension is available + */ + if ((sbi_spec_version < sbi_mk_version(0, 3)) || + sbi_probe_extension(SBI_EXT_HSM) <= 0) { + pr_info("HSM suspend not available\n"); + return 0; + } + + ret = platform_driver_register(&sbi_cpuidle_driver); + if (ret) + return ret; + + pdev = platform_device_register_simple("sbi-cpuidle", + -1, NULL, 0); + if (IS_ERR(pdev)) { + platform_driver_unregister(&sbi_cpuidle_driver); + return PTR_ERR(pdev); + } + + return 0; +} +device_initcall(sbi_cpuidle_init); From b3f391da4cbf12368e97e7c7ce305ff3e874118f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:44:48 -0500 Subject: [PATCH 008/120] cpuidle: sbi: Fix build with !CONFIG_SMP Signed-off-by: Samuel Holland --- drivers/cpuidle/cpuidle-sbi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/cpuidle/cpuidle-sbi.c b/drivers/cpuidle/cpuidle-sbi.c index b04664c8877db4..5ef1ac12d8310f 100644 --- a/drivers/cpuidle/cpuidle-sbi.c +++ b/drivers/cpuidle/cpuidle-sbi.c @@ -19,8 +19,10 @@ #include #include #include + #include #include +#include #include #include "dt_idle_states.h" From afd096ce91b6338621ae96454991242037f84483 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:22 +0530 Subject: [PATCH 009/120] dt-bindings: Add common bindings for ARM and RISC-V idle states The RISC-V CPU idle states will be described in under the /cpus/idle-states DT node in the same way as ARM CPU idle states. This patch adds common bindings documentation for both ARM and RISC-V idle states. Signed-off-by: Anup Patel Reviewed-by: Rob Herring --- .../bindings/{arm => cpu}/idle-states.yaml | 228 ++++++++++++++++-- .../devicetree/bindings/riscv/cpus.yaml | 6 + 2 files changed, 217 insertions(+), 17 deletions(-) rename Documentation/devicetree/bindings/{arm => cpu}/idle-states.yaml (74%) diff --git a/Documentation/devicetree/bindings/arm/idle-states.yaml b/Documentation/devicetree/bindings/cpu/idle-states.yaml similarity index 74% rename from Documentation/devicetree/bindings/arm/idle-states.yaml rename to Documentation/devicetree/bindings/cpu/idle-states.yaml index 52bce5dbb11f56..74466f160cb29a 100644 --- a/Documentation/devicetree/bindings/arm/idle-states.yaml +++ b/Documentation/devicetree/bindings/cpu/idle-states.yaml @@ -1,25 +1,30 @@ # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) %YAML 1.2 --- -$id: http://devicetree.org/schemas/arm/idle-states.yaml# +$id: http://devicetree.org/schemas/cpu/idle-states.yaml# $schema: http://devicetree.org/meta-schemas/core.yaml# -title: ARM idle states binding description +title: Idle states binding description maintainers: - Lorenzo Pieralisi + - Anup Patel description: |+ ========================================== 1 - Introduction ========================================== - ARM systems contain HW capable of managing power consumption dynamically, - where cores can be put in different low-power states (ranging from simple wfi - to power gating) according to OS PM policies. The CPU states representing the - range of dynamic idle states that a processor can enter at run-time, can be - specified through device tree bindings representing the parameters required to - enter/exit specific idle states on a given processor. + ARM and RISC-V systems contain HW capable of managing power consumption + dynamically, where cores can be put in different low-power states (ranging + from simple wfi to power gating) according to OS PM policies. The CPU states + representing the range of dynamic idle states that a processor can enter at + run-time, can be specified through device tree bindings representing the + parameters required to enter/exit specific idle states on a given processor. + + ========================================== + 2 - ARM idle states + ========================================== According to the Server Base System Architecture document (SBSA, [3]), the power states an ARM CPU can be put into are identified by the following list: @@ -43,8 +48,23 @@ description: |+ The device tree binding definition for ARM idle states is the subject of this document. + ========================================== + 3 - RISC-V idle states + ========================================== + + On RISC-V systems, the HARTs (or CPUs) [6] can be put in platform specific + suspend (or idle) states (ranging from simple WFI, power gating, etc). The + RISC-V SBI v0.3 (or higher) [7] hart state management extension provides a + standard mechanism for OS to request HART state transitions. + + The platform specific suspend (or idle) states of a hart can be either + retentive or non-rententive in nature. A retentive suspend state will + preserve HART registers and CSR values for all privilege modes whereas + a non-retentive suspend state will not preserve HART registers and CSR + values. + =========================================== - 2 - idle-states definitions + 4 - idle-states definitions =========================================== Idle states are characterized for a specific system through a set of @@ -211,10 +231,10 @@ description: |+ properties specification that is the subject of the following sections. =========================================== - 3 - idle-states node + 5 - idle-states node =========================================== - ARM processor idle states are defined within the idle-states node, which is + The processor idle states are defined within the idle-states node, which is a direct child of the cpus node [1] and provides a container where the processor idle states, defined as device tree nodes, are listed. @@ -223,7 +243,7 @@ description: |+ just supports idle_standby, an idle-states node is not required. =========================================== - 4 - References + 6 - References =========================================== [1] ARM Linux Kernel documentation - CPUs bindings @@ -238,9 +258,15 @@ description: |+ [4] ARM Architecture Reference Manuals http://infocenter.arm.com/help/index.jsp - [6] ARM Linux Kernel documentation - Booting AArch64 Linux + [5] ARM Linux Kernel documentation - Booting AArch64 Linux Documentation/arm64/booting.rst + [6] RISC-V Linux Kernel documentation - CPUs bindings + Documentation/devicetree/bindings/riscv/cpus.yaml + + [7] RISC-V Supervisor Binary Interface (SBI) + http://github.com/riscv/riscv-sbi-doc/riscv-sbi.adoc + properties: $nodename: const: idle-states @@ -253,7 +279,7 @@ properties: On ARM 32-bit systems this property is optional This assumes that the "enable-method" property is set to "psci" in the cpu - node[6] that is responsible for setting up CPU idle management in the OS + node[5] that is responsible for setting up CPU idle management in the OS implementation. const: psci @@ -265,8 +291,8 @@ patternProperties: as follows. The idle state entered by executing the wfi instruction (idle_standby - SBSA,[3][4]) is considered standard on all ARM platforms and therefore - must not be listed. + SBSA,[3][4]) is considered standard on all ARM and RISC-V platforms and + therefore must not be listed. In addition to the properties listed above, a state node may require additional properties specific to the entry-method defined in the @@ -275,7 +301,27 @@ patternProperties: properties: compatible: - const: arm,idle-state + oneOf: + - const: arm,idle-state + - const: riscv,idle-state + + arm,psci-suspend-param: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + power_state parameter to pass to the ARM PSCI suspend call. + + Device tree nodes that require usage of PSCI CPU_SUSPEND function + (i.e. idle states node with entry-method property is set to "psci") + must specify this property. + + riscv,sbi-suspend-param: + $ref: /schemas/types.yaml#/definitions/uint32 + description: | + suspend_type parameter to pass to the RISC-V SBI HSM suspend call. + + This property is required in idle state nodes of device tree meant + for RISC-V systems. For more details on the suspend_type parameter + refer the SBI specifiation v0.3 (or higher) [7]. local-timer-stop: description: @@ -317,6 +363,8 @@ patternProperties: description: A string used as a descriptive name for the idle state. + additionalProperties: false + required: - compatible - entry-latency-us @@ -658,4 +706,150 @@ examples: }; }; + - | + // Example 3 (RISC-V 64-bit, 4-cpu systems, two clusters): + + cpus { + #size-cells = <0>; + #address-cells = <1>; + + cpu@0 { + device_type = "cpu"; + compatible = "riscv"; + reg = <0x0>; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv48"; + cpu-idle-states = <&CPU_RET_0_0 &CPU_NONRET_0_0 + &CLUSTER_RET_0 &CLUSTER_NONRET_0>; + + cpu_intc0: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu@1 { + device_type = "cpu"; + compatible = "riscv"; + reg = <0x1>; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv48"; + cpu-idle-states = <&CPU_RET_0_0 &CPU_NONRET_0_0 + &CLUSTER_RET_0 &CLUSTER_NONRET_0>; + + cpu_intc1: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu@10 { + device_type = "cpu"; + compatible = "riscv"; + reg = <0x10>; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv48"; + cpu-idle-states = <&CPU_RET_1_0 &CPU_NONRET_1_0 + &CLUSTER_RET_1 &CLUSTER_NONRET_1>; + + cpu_intc10: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + cpu@11 { + device_type = "cpu"; + compatible = "riscv"; + reg = <0x11>; + riscv,isa = "rv64imafdc"; + mmu-type = "riscv,sv48"; + cpu-idle-states = <&CPU_RET_1_0 &CPU_NONRET_1_0 + &CLUSTER_RET_1 &CLUSTER_NONRET_1>; + + cpu_intc11: interrupt-controller { + #interrupt-cells = <1>; + compatible = "riscv,cpu-intc"; + interrupt-controller; + }; + }; + + idle-states { + CPU_RET_0_0: cpu-retentive-0-0 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x10000000>; + entry-latency-us = <20>; + exit-latency-us = <40>; + min-residency-us = <80>; + }; + + CPU_NONRET_0_0: cpu-nonretentive-0-0 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x90000000>; + entry-latency-us = <250>; + exit-latency-us = <500>; + min-residency-us = <950>; + }; + + CLUSTER_RET_0: cluster-retentive-0 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x11000000>; + local-timer-stop; + entry-latency-us = <50>; + exit-latency-us = <100>; + min-residency-us = <250>; + wakeup-latency-us = <130>; + }; + + CLUSTER_NONRET_0: cluster-nonretentive-0 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x91000000>; + local-timer-stop; + entry-latency-us = <600>; + exit-latency-us = <1100>; + min-residency-us = <2700>; + wakeup-latency-us = <1500>; + }; + + CPU_RET_1_0: cpu-retentive-1-0 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x10000010>; + entry-latency-us = <20>; + exit-latency-us = <40>; + min-residency-us = <80>; + }; + + CPU_NONRET_1_0: cpu-nonretentive-1-0 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x90000010>; + entry-latency-us = <250>; + exit-latency-us = <500>; + min-residency-us = <950>; + }; + + CLUSTER_RET_1: cluster-retentive-1 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x11000010>; + local-timer-stop; + entry-latency-us = <50>; + exit-latency-us = <100>; + min-residency-us = <250>; + wakeup-latency-us = <130>; + }; + + CLUSTER_NONRET_1: cluster-nonretentive-1 { + compatible = "riscv,idle-state"; + riscv,sbi-suspend-param = <0x91000010>; + local-timer-stop; + entry-latency-us = <600>; + exit-latency-us = <1100>; + min-residency-us = <2700>; + wakeup-latency-us = <1500>; + }; + }; + }; + ... diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml index e534f6a7cfa1f2..4829366305259e 100644 --- a/Documentation/devicetree/bindings/riscv/cpus.yaml +++ b/Documentation/devicetree/bindings/riscv/cpus.yaml @@ -95,6 +95,12 @@ properties: - compatible - interrupt-controller + cpu-idle-states: + $ref: '/schemas/types.yaml#/definitions/phandle-array' + description: | + List of phandles to idle state nodes supported + by this hart (see ./idle-states.yaml). + required: - riscv,isa - interrupt-controller From d0042e8dd44d31d1e6230dfc9b466df1ce1dc2d3 Mon Sep 17 00:00:00 2001 From: Anup Patel Date: Mon, 17 May 2021 18:38:23 +0530 Subject: [PATCH 010/120] RISC-V: Enable RISC-V SBI CPU Idle driver for QEMU virt machine We enable RISC-V SBI CPU Idle driver for QEMU virt machine to test SBI HSM Supend on QEMU. Signed-off-by: Anup Patel --- arch/riscv/Kconfig.socs | 3 +++ arch/riscv/configs/defconfig | 1 + arch/riscv/configs/rv32_defconfig | 1 + 3 files changed, 5 insertions(+) diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 30676ebb16ebd7..56bafc3dad4c6f 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -28,6 +28,9 @@ config SOC_VIRT select GOLDFISH select RTC_DRV_GOLDFISH if RTC_CLASS select SIFIVE_PLIC + select PM_GENERIC_DOMAINS if PM + select PM_GENERIC_DOMAINS_OF if PM && OF + select RISCV_SBI_CPUIDLE if CPU_IDLE help This enables support for QEMU Virt Machine. diff --git a/arch/riscv/configs/defconfig b/arch/riscv/configs/defconfig index 57a24d40d43f81..ed71f125cbc9d8 100644 --- a/arch/riscv/configs/defconfig +++ b/arch/riscv/configs/defconfig @@ -20,6 +20,7 @@ CONFIG_SOC_SIFIVE=y CONFIG_SOC_VIRT=y CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y +CONFIG_PM=y CONFIG_CPU_IDLE=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y diff --git a/arch/riscv/configs/rv32_defconfig b/arch/riscv/configs/rv32_defconfig index 97d899df244511..0088d698933228 100644 --- a/arch/riscv/configs/rv32_defconfig +++ b/arch/riscv/configs/rv32_defconfig @@ -20,6 +20,7 @@ CONFIG_SOC_VIRT=y CONFIG_ARCH_RV32I=y CONFIG_SMP=y CONFIG_HOTPLUG_CPU=y +CONFIG_PM=y CONFIG_CPU_IDLE=y CONFIG_JUMP_LABEL=y CONFIG_MODULES=y From 904f70fd07afaccd76b3c5cc1ce32b8dee21aaea Mon Sep 17 00:00:00 2001 From: Alexandre Ghiti Date: Tue, 18 May 2021 12:12:50 +0200 Subject: [PATCH 011/120] riscv: Introduce CONFIG_RELOCATABLE This config allows to compile 64b kernel as PIE and to relocate it at any virtual address at runtime: this paves the way to KASLR. Runtime relocation is possible since relocation metadata are embedded into the kernel. Note that relocating at runtime introduces an overhead even if the kernel is loaded at the same address it was linked at and that the compiler options are those used in arm64 which uses the same RELA relocation format. Signed-off-by: Alexandre Ghiti --- arch/riscv/Kconfig | 12 ++++++++ arch/riscv/Makefile | 5 +++- arch/riscv/kernel/vmlinux.lds.S | 6 ++++ arch/riscv/mm/Makefile | 4 +++ arch/riscv/mm/init.c | 53 ++++++++++++++++++++++++++++++++- 5 files changed, 78 insertions(+), 2 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 773372252c5d75..534d2faf48d2cb 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -210,6 +210,18 @@ config PGTABLE_LEVELS config LOCKDEP_SUPPORT def_bool y +config RELOCATABLE + bool + depends on MMU && 64BIT && !XIP_KERNEL + help + This builds a kernel as a Position Independent Executable (PIE), + which retains all relocation metadata required to relocate the + kernel binary at runtime to a different virtual address than the + address it was linked at. + Since RISCV uses the RELA relocation format, this requires a + relocation pass at runtime even if the kernel is loaded at the + same address it was linked at. + source "arch/riscv/Kconfig.socs" source "arch/riscv/Kconfig.erratas" diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile index bc74afdbf31e23..1fb09005488a42 100644 --- a/arch/riscv/Makefile +++ b/arch/riscv/Makefile @@ -9,7 +9,10 @@ # OBJCOPYFLAGS := -O binary -LDFLAGS_vmlinux := +ifeq ($(CONFIG_RELOCATABLE),y) +LDFLAGS_vmlinux := -shared -Bsymbolic -z notext -z norelro +KBUILD_CFLAGS += -fPIE +endif ifeq ($(CONFIG_DYNAMIC_FTRACE),y) LDFLAGS_vmlinux := --no-relax KBUILD_CPPFLAGS += -DCC_USING_PATCHABLE_FUNCTION_ENTRY diff --git a/arch/riscv/kernel/vmlinux.lds.S b/arch/riscv/kernel/vmlinux.lds.S index 502d0826ecb14c..0c26eb6ed54ed2 100644 --- a/arch/riscv/kernel/vmlinux.lds.S +++ b/arch/riscv/kernel/vmlinux.lds.S @@ -133,6 +133,12 @@ SECTIONS BSS_SECTION(PAGE_SIZE, PAGE_SIZE, 0) + .rela.dyn : ALIGN(8) { + __rela_dyn_start = .; + *(.rela .rela*) + __rela_dyn_end = .; + } + #ifdef CONFIG_EFI . = ALIGN(PECOFF_SECTION_ALIGNMENT); __pecoff_data_virt_size = ABSOLUTE(. - __pecoff_text_end); diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile index 7ebaef10ea1b69..2d33ec574bbb2f 100644 --- a/arch/riscv/mm/Makefile +++ b/arch/riscv/mm/Makefile @@ -1,6 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only CFLAGS_init.o := -mcmodel=medany +ifdef CONFIG_RELOCATABLE +CFLAGS_init.o += -fno-pie +endif + ifdef CONFIG_FTRACE CFLAGS_REMOVE_init.o = $(CC_FLAGS_FTRACE) CFLAGS_REMOVE_cacheflush.o = $(CC_FLAGS_FTRACE) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index a14bf3910eec95..bc179e22a0fb0e 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -19,6 +19,9 @@ #include #include #include +#ifdef CONFIG_RELOCATABLE +#include +#endif #include #include @@ -99,7 +102,7 @@ static void __init print_vm_layout(void) print_mlm("lowmem", (unsigned long)PAGE_OFFSET, (unsigned long)high_memory); #ifdef CONFIG_64BIT - print_mlm("kernel", (unsigned long)KERNEL_LINK_ADDR, + print_mlm("kernel", (unsigned long)kernel_map.virt_addr, (unsigned long)ADDRESS_SPACE_END); #endif } @@ -508,6 +511,44 @@ static __init pgprot_t pgprot_from_va(uintptr_t va) #error "setup_vm() is called from head.S before relocate so it should not use absolute addressing." #endif +#ifdef CONFIG_RELOCATABLE +extern unsigned long __rela_dyn_start, __rela_dyn_end; + +void __init relocate_kernel(uintptr_t load_pa) +{ + Elf64_Rela *rela = (Elf64_Rela *)&__rela_dyn_start; + /* + * This holds the offset between the linked virtual address and the + * relocated virtual address. + */ + uintptr_t reloc_offset = kernel_map.virt_addr - KERNEL_LINK_ADDR; + /* + * This holds the offset between kernel linked virtual address and + * physical address. + */ + uintptr_t va_kernel_link_pa_offset = KERNEL_LINK_ADDR - load_pa; + + for ( ; rela < (Elf64_Rela *)&__rela_dyn_end; rela++) { + Elf64_Addr addr = (rela->r_offset - va_kernel_link_pa_offset); + Elf64_Addr relocated_addr = rela->r_addend; + + if (rela->r_info != R_RISCV_RELATIVE) + continue; + + /* + * Make sure to not relocate vdso symbols like rt_sigreturn + * which are linked from the address 0 in vmlinux since + * vdso symbol addresses are actually used as an offset from + * mm->context.vdso in VDSO_OFFSET macro. + */ + if (relocated_addr >= KERNEL_LINK_ADDR) + relocated_addr += reloc_offset; + + *(Elf64_Addr *)addr = relocated_addr; + } +} +#endif + #ifdef CONFIG_XIP_KERNEL static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size, __always_unused bool early) @@ -574,6 +615,16 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) pfn_base = PFN_DOWN(kernel_map.phys_addr); +#ifdef CONFIG_RELOCATABLE + /* + * Early page table uses only one PGDIR, which makes it possible + * to map PGDIR_SIZE aligned on PGDIR_SIZE: if the relocation offset + * makes the kernel cross over a PGDIR_SIZE boundary, raise a bug + * since a part of the kernel would not get mapped. + */ + BUG_ON(PGDIR_SIZE - (kernel_map.virt_addr & (PGDIR_SIZE - 1)) < load_sz); + relocate_kernel(load_pa); +#endif /* * Enforce boot alignment requirements of RV32 and * RV64 by only allowing PMD or PGD mappings. From 57aadbda442e6670e9a9fb2c08706f63631bf193 Mon Sep 17 00:00:00 2001 From: Alexandre Ghiti Date: Tue, 18 May 2021 12:12:51 +0200 Subject: [PATCH 012/120] powerpc: Move script to check relocations at compile time in scripts/ Relocating kernel at runtime is done very early in the boot process, so it is not convenient to check for relocations there and react in case a relocation was not expected. Powerpc architecture has a script that allows to check at compile time for such unexpected relocations: extract the common logic to scripts/ so that other architectures can take advantage of it. Signed-off-by: Alexandre Ghiti Reviewed-by: Anup Patel Acked-by: Michael Ellerman (powerpc) --- arch/powerpc/tools/relocs_check.sh | 18 ++---------------- scripts/relocs_check.sh | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 16 deletions(-) create mode 100755 scripts/relocs_check.sh diff --git a/arch/powerpc/tools/relocs_check.sh b/arch/powerpc/tools/relocs_check.sh index 014e00e74d2b6c..e367895941ae90 100755 --- a/arch/powerpc/tools/relocs_check.sh +++ b/arch/powerpc/tools/relocs_check.sh @@ -15,21 +15,8 @@ if [ $# -lt 3 ]; then exit 1 fi -# Have Kbuild supply the path to objdump and nm so we handle cross compilation. -objdump="$1" -nm="$2" -vmlinux="$3" - -# Remove from the bad relocations those that match an undefined weak symbol -# which will result in an absolute relocation to 0. -# Weak unresolved symbols are of that form in nm output: -# " w _binary__btf_vmlinux_bin_end" -undef_weak_symbols=$($nm "$vmlinux" | awk '$1 ~ /w/ { print $2 }') - bad_relocs=$( -$objdump -R "$vmlinux" | - # Only look at relocation lines. - grep -E '\ Date: Tue, 18 May 2021 12:12:52 +0200 Subject: [PATCH 013/120] riscv: Check relocations at compile time Relocating kernel at runtime is done very early in the boot process, so it is not convenient to check for relocations there and react in case a relocation was not expected. There exists a script in scripts/ that extracts the relocations from vmlinux that is then used at postlink to check the relocations. Signed-off-by: Alexandre Ghiti Reviewed-by: Anup Patel --- arch/riscv/Makefile.postlink | 36 ++++++++++++++++++++++++++++++++ arch/riscv/tools/relocs_check.sh | 26 +++++++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 arch/riscv/Makefile.postlink create mode 100755 arch/riscv/tools/relocs_check.sh diff --git a/arch/riscv/Makefile.postlink b/arch/riscv/Makefile.postlink new file mode 100644 index 00000000000000..bf2b2bca184563 --- /dev/null +++ b/arch/riscv/Makefile.postlink @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: GPL-2.0 +# =========================================================================== +# Post-link riscv pass +# =========================================================================== +# +# Check that vmlinux relocations look sane + +PHONY := __archpost +__archpost: + +-include include/config/auto.conf +include scripts/Kbuild.include + +quiet_cmd_relocs_check = CHKREL $@ +cmd_relocs_check = \ + $(CONFIG_SHELL) $(srctree)/arch/riscv/tools/relocs_check.sh "$(OBJDUMP)" "$(NM)" "$@" + +# `@true` prevents complaint when there is nothing to be done + +vmlinux: FORCE + @true +ifdef CONFIG_RELOCATABLE + $(call if_changed,relocs_check) +endif + +%.ko: FORCE + @true + +clean: + @true + +PHONY += FORCE clean + +FORCE: + +.PHONY: $(PHONY) diff --git a/arch/riscv/tools/relocs_check.sh b/arch/riscv/tools/relocs_check.sh new file mode 100755 index 00000000000000..baeb2e7b229055 --- /dev/null +++ b/arch/riscv/tools/relocs_check.sh @@ -0,0 +1,26 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0-or-later +# Based on powerpc relocs_check.sh + +# This script checks the relocations of a vmlinux for "suspicious" +# relocations. + +if [ $# -lt 3 ]; then + echo "$0 [path to objdump] [path to nm] [path to vmlinux]" 1>&2 + exit 1 +fi + +bad_relocs=$( +${srctree}/scripts/relocs_check.sh "$@" | + # These relocations are okay + # R_RISCV_RELATIVE + grep -F -w -v 'R_RISCV_RELATIVE' +) + +if [ -z "$bad_relocs" ]; then + exit 0 +fi + +num_bad=$(echo "$bad_relocs" | wc -l) +echo "WARNING: $num_bad bad relocations" +echo "$bad_relocs" From 1197dbd375ed250b3e80c908279a98ffd439e9cc Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 6 Jun 2021 09:04:02 +0000 Subject: [PATCH 014/120] riscv: pgtable: Fixup _PAGE_CHG_MASK usage We should masks all attributes BITS first, and then using '>> _PAGE_PFN_SHIFT' to get the final PFN value. Adding '& _PAGE_CHG_MASK' makes the code semantics more accurate. Signed-off-by: Guo Ren Signed-off-by: Liu Shaohua Cc: Anup Patel Cc: Arnd Bergmann Cc: Chen-Yu Tsai Cc: Christoph Hellwig Cc: Drew Fustini Cc: Maxime Ripard Cc: Palmer Dabbelt Cc: Wei Fu Cc: Wei Wu --- arch/riscv/include/asm/pgtable-64.h | 6 +++--- arch/riscv/include/asm/pgtable.h | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/arch/riscv/include/asm/pgtable-64.h b/arch/riscv/include/asm/pgtable-64.h index 228261aa962868..6df493b55dde7e 100644 --- a/arch/riscv/include/asm/pgtable-64.h +++ b/arch/riscv/include/asm/pgtable-64.h @@ -61,12 +61,12 @@ static inline void pud_clear(pud_t *pudp) static inline pmd_t *pud_pgtable(pud_t pud) { - return (pmd_t *)pfn_to_virt(pud_val(pud) >> _PAGE_PFN_SHIFT); + return (pmd_t *)pfn_to_virt((pud_val(pud) & _PAGE_CHG_MASK) >> _PAGE_PFN_SHIFT); } static inline struct page *pud_page(pud_t pud) { - return pfn_to_page(pud_val(pud) >> _PAGE_PFN_SHIFT); + return pfn_to_page((pud_val(pud) & _PAGE_CHG_MASK) >> _PAGE_PFN_SHIFT); } static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot) @@ -76,7 +76,7 @@ static inline pmd_t pfn_pmd(unsigned long pfn, pgprot_t prot) static inline unsigned long _pmd_pfn(pmd_t pmd) { - return pmd_val(pmd) >> _PAGE_PFN_SHIFT; + return (pmd_val(pmd) & _PAGE_CHG_MASK) >> _PAGE_PFN_SHIFT; } #define mk_pmd(page, prot) pfn_pmd(page_to_pfn(page), prot) diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 39b550310ec645..163e583edbdfb9 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -230,12 +230,12 @@ static inline unsigned long _pgd_pfn(pgd_t pgd) static inline struct page *pmd_page(pmd_t pmd) { - return pfn_to_page(pmd_val(pmd) >> _PAGE_PFN_SHIFT); + return pfn_to_page((pmd_val(pmd) & _PAGE_CHG_MASK) >> _PAGE_PFN_SHIFT); } static inline unsigned long pmd_page_vaddr(pmd_t pmd) { - return (unsigned long)pfn_to_virt(pmd_val(pmd) >> _PAGE_PFN_SHIFT); + return (unsigned long)pfn_to_virt((pmd_val(pmd) & _PAGE_CHG_MASK) >> _PAGE_PFN_SHIFT); } static inline pte_t pmd_pte(pmd_t pmd) @@ -251,7 +251,7 @@ static inline pte_t pud_pte(pud_t pud) /* Yields the page frame number (PFN) of a page table entry */ static inline unsigned long pte_pfn(pte_t pte) { - return (pte_val(pte) >> _PAGE_PFN_SHIFT); + return (pte_val(pte) & _PAGE_CHG_MASK) >> _PAGE_PFN_SHIFT; } #define pte_page(x) pfn_to_page(pte_pfn(x)) From 036c88fbabe241e9612ec26f59a28a53d20ca55f Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 6 Jun 2021 09:04:03 +0000 Subject: [PATCH 015/120] riscv: pgtable: Add custom protection_map init Some RISC-V CPU vendors have defined their own PTE attributes to solve non-coherent DMA bus problems. That makes _P/SXXX definitions contain global variables which could be initialized at the early boot stage before setup_vm. This patch is similar to 316d097c4cd4 (x86/pti: Filter at vma->vm_page_prot population) which give a choice for arch custom implementation. Signed-off-by: Guo Ren Cc: Andrew Morton Cc: Arnd Bergmann Cc: Palmer Dabbelt --- arch/riscv/Kconfig | 4 ++++ arch/riscv/mm/init.c | 22 ++++++++++++++++++++++ mm/mmap.c | 4 ++++ 3 files changed, 30 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 534d2faf48d2cb..d6e4e6f155a81b 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -25,6 +25,7 @@ config RISCV select ARCH_HAS_GIGANTIC_PAGE select ARCH_HAS_KCOV select ARCH_HAS_MMIOWB + select ARCH_HAS_PROTECTION_MAP_INIT select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_SET_DIRECT_MAP if MMU select ARCH_HAS_SET_MEMORY if MMU @@ -202,6 +203,9 @@ config GENERIC_HWEIGHT config FIX_EARLYCON_MEM def_bool MMU +config ARCH_HAS_PROTECTION_MAP_INIT + def_bool y + config PGTABLE_LEVELS int default 3 if 64BIT diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index bc179e22a0fb0e..d1a3920ae5b791 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -585,6 +585,26 @@ static void __init create_kernel_page_table(pgd_t *pgdir, uintptr_t map_size, } #endif +static void __init setup_protection_map(void) +{ + protection_map[0] = __P000; + protection_map[1] = __P001; + protection_map[2] = __P010; + protection_map[3] = __P011; + protection_map[4] = __P100; + protection_map[5] = __P101; + protection_map[6] = __P110; + protection_map[7] = __P111; + protection_map[8] = __S000; + protection_map[9] = __S001; + protection_map[10] = __S010; + protection_map[11] = __S011; + protection_map[12] = __S100; + protection_map[13] = __S101; + protection_map[14] = __S110; + protection_map[15] = __S111; +} + asmlinkage void __init setup_vm(uintptr_t dtb_pa) { uintptr_t __maybe_unused pa; @@ -593,6 +613,8 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) pmd_t fix_bmap_spmd, fix_bmap_epmd; #endif + setup_protection_map(); + kernel_map.virt_addr = KERNEL_LINK_ADDR; #ifdef CONFIG_XIP_KERNEL diff --git a/mm/mmap.c b/mm/mmap.c index ca54d36d203ae4..286be9476398f9 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -100,10 +100,14 @@ static void unmap_region(struct mm_struct *mm, * w: (no) no * x: (yes) yes */ +#ifdef CONFIG_ARCH_HAS_PROTECTION_MAP_INIT +pgprot_t protection_map[16] __ro_after_init; +#else pgprot_t protection_map[16] __ro_after_init = { __P000, __P001, __P010, __P011, __P100, __P101, __P110, __P111, __S000, __S001, __S010, __S011, __S100, __S101, __S110, __S111 }; +#endif #ifndef CONFIG_ARCH_HAS_FILTER_PGPROT static inline pgprot_t arch_filter_pgprot(pgprot_t prot) From b789c51ee52626aae2da04fbef94d7e30cadbdaf Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 6 Jun 2021 09:04:04 +0000 Subject: [PATCH 016/120] riscv: pgtable: Add DMA_COHERENT with custom PTE attributes The dma-noncoherent SOCs need different virtual memory mappings with different attributes: - noncached + Strong Order (for IO/DMA descriptor) - noncached + Weak Order (for writecombine usage, eg: frame buffer) All above base on PTE attributes by MMU hardware. That means address attributes are determined by PTE entry, not PMA. RISC-V soc vendors have defined their own custom PTE attributes for dma-noncoherency. Signed-off-by: Guo Ren Signed-off-by: Liu Shaohua Cc: Palmer Dabbelt Cc: Christoph Hellwig Cc: Anup Patel Cc: Arnd Bergmann Cc: Drew Fustini Cc: Wei Fu Cc: Wei Wu Cc: Chen-Yu Tsai Cc: Maxime Ripard --- arch/riscv/include/asm/pgtable-bits.h | 22 +++++++++++++++++++++- arch/riscv/include/asm/pgtable.h | 11 ++++------- arch/riscv/include/asm/soc.h | 1 + arch/riscv/include/asm/vendorid_list.h | 1 + arch/riscv/kernel/soc.c | 22 ++++++++++++++++++++++ arch/riscv/mm/init.c | 4 ++++ 6 files changed, 53 insertions(+), 8 deletions(-) diff --git a/arch/riscv/include/asm/pgtable-bits.h b/arch/riscv/include/asm/pgtable-bits.h index 2ee41391292606..e9e95666f9bd40 100644 --- a/arch/riscv/include/asm/pgtable-bits.h +++ b/arch/riscv/include/asm/pgtable-bits.h @@ -24,6 +24,11 @@ #define _PAGE_DIRTY (1 << 7) /* Set by hardware on any write */ #define _PAGE_SOFT (1 << 8) /* Reserved for software */ +#define _PAGE_DMA_MASK __riscv_custom_pte.mask +#define _PAGE_DMA_CACHE __riscv_custom_pte.cache +#define _PAGE_DMA_IO __riscv_custom_pte.io +#define _PAGE_DMA_WC __riscv_custom_pte.wc + #define _PAGE_SPECIAL _PAGE_SOFT #define _PAGE_TABLE _PAGE_PRESENT @@ -35,10 +40,25 @@ #define _PAGE_PFN_SHIFT 10 +#ifndef __ASSEMBLY__ + +struct riscv_custom_pte { + unsigned long cache; + unsigned long mask; + unsigned long io; + unsigned long wc; +}; + +extern struct riscv_custom_pte __riscv_custom_pte; + /* Set of bits to preserve across pte_modify() */ #define _PAGE_CHG_MASK (~(unsigned long)(_PAGE_PRESENT | _PAGE_READ | \ _PAGE_WRITE | _PAGE_EXEC | \ - _PAGE_USER | _PAGE_GLOBAL)) + _PAGE_USER | _PAGE_GLOBAL | \ + _PAGE_DMA_MASK)) + +#endif + /* * when all of R/W/X are zero, the PTE is a pointer to the next level * of the page table; otherwise, it is a leaf PTE. diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 163e583edbdfb9..7ea7d810418f4f 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -115,7 +115,7 @@ #define USER_PTRS_PER_PGD (TASK_SIZE / PGDIR_SIZE) /* Page protection bits */ -#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER) +#define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER | _PAGE_DMA_CACHE) #define PAGE_NONE __pgprot(_PAGE_PROT_NONE) #define PAGE_READ __pgprot(_PAGE_BASE | _PAGE_READ) @@ -136,7 +136,8 @@ | _PAGE_PRESENT \ | _PAGE_ACCESSED \ | _PAGE_DIRTY \ - | _PAGE_GLOBAL) + | _PAGE_GLOBAL \ + | _PAGE_DMA_CACHE) #define PAGE_KERNEL __pgprot(_PAGE_KERNEL) #define PAGE_KERNEL_READ __pgprot(_PAGE_KERNEL & ~_PAGE_WRITE) @@ -146,11 +147,7 @@ #define PAGE_TABLE __pgprot(_PAGE_TABLE) -/* - * The RISC-V ISA doesn't yet specify how to query or modify PMAs, so we can't - * change the properties of memory regions. - */ -#define _PAGE_IOREMAP _PAGE_KERNEL +#define _PAGE_IOREMAP ((_PAGE_KERNEL & ~_PAGE_DMA_MASK) | _PAGE_DMA_IO) extern pgd_t swapper_pg_dir[]; diff --git a/arch/riscv/include/asm/soc.h b/arch/riscv/include/asm/soc.h index f494066051a2c1..fc587d7d295d4e 100644 --- a/arch/riscv/include/asm/soc.h +++ b/arch/riscv/include/asm/soc.h @@ -17,6 +17,7 @@ = { .compatible = compat, .data = fn } void soc_early_init(void); +void soc_setup_vm(void); extern unsigned long __soc_early_init_table_start; extern unsigned long __soc_early_init_table_end; diff --git a/arch/riscv/include/asm/vendorid_list.h b/arch/riscv/include/asm/vendorid_list.h index 9d934215b3c851..c2710f391a892f 100644 --- a/arch/riscv/include/asm/vendorid_list.h +++ b/arch/riscv/include/asm/vendorid_list.h @@ -6,5 +6,6 @@ #define ASM_VENDOR_LIST_H #define SIFIVE_VENDOR_ID 0x489 +#define THEAD_VENDOR_ID 0x401 #endif diff --git a/arch/riscv/kernel/soc.c b/arch/riscv/kernel/soc.c index a0516172a33c84..05fa76467e6911 100644 --- a/arch/riscv/kernel/soc.c +++ b/arch/riscv/kernel/soc.c @@ -3,8 +3,10 @@ * Copyright (C) 2020 Western Digital Corporation or its affiliates. */ #include +#include #include #include +#include #include /* @@ -26,3 +28,23 @@ void __init soc_early_init(void) } } } + +static void __init thead_init(void) +{ + __riscv_custom_pte.cache = 0x7000000000000000; + __riscv_custom_pte.mask = 0xf800000000000000; + __riscv_custom_pte.io = BIT(63); + __riscv_custom_pte.wc = 0; +} + +void __init soc_setup_vm(void) +{ + unsigned long vendor_id = + ((struct riscv_image_header *)(&_start))->res1; + + switch (vendor_id) { + case THEAD_VENDOR_ID: + thead_init(); + break; + } +}; diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index d1a3920ae5b791..0541b243bb9589 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -613,6 +613,7 @@ asmlinkage void __init setup_vm(uintptr_t dtb_pa) pmd_t fix_bmap_spmd, fix_bmap_epmd; #endif + soc_setup_vm(); setup_protection_map(); kernel_map.virt_addr = KERNEL_LINK_ADDR; @@ -971,3 +972,6 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node, return vmemmap_populate_basepages(start, end, node, NULL); } #endif + +struct riscv_custom_pte __riscv_custom_pte __ro_after_init; +EXPORT_SYMBOL(__riscv_custom_pte); From 01a3fe9c949e41d0cbc23d3f2085e18646b5985b Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 6 Jun 2021 09:04:05 +0000 Subject: [PATCH 017/120] riscv: cmo: Add dma-noncoherency support To support DMA device in a non-coherent interconnect SOC system, we need the below facilities: - Changing a virtual memory mapping region attributes from cacheable to noncache + strong order which used in DMA descriptors. - Add noncache + weakorder virtual memory attributes for dma mapping. - Syncing the cache with memory before DMA start and after DMA end with vendor custom CMO instructions. This patch enables linux kernel generic dma-noncoherency infrastructure and introduces new sbi_ecall API for dma_sync. @@ -27,6 +27,7 @@ enum sbi_ext_id { + SBI_EXT_DMA = 0xAB150401, Signed-off-by: Guo Ren Signed-off-by: Liu Shaohua Cc: Palmer Dabbelt Cc: Christoph Hellwig Cc: Anup Patel Cc: Arnd Bergmann Cc: Drew Fustini Cc: Wei Fu Cc: Wei Wu Cc: Chen-Yu Tsai Cc: Maxime Ripard --- arch/riscv/Kconfig | 5 +++ arch/riscv/include/asm/pgtable.h | 26 ++++++++++++++++ arch/riscv/include/asm/sbi.h | 22 +++++++++++++ arch/riscv/kernel/sbi.c | 19 ++++++++++++ arch/riscv/mm/Makefile | 1 + arch/riscv/mm/dma-mapping.c | 53 ++++++++++++++++++++++++++++++++ 6 files changed, 126 insertions(+) create mode 100644 arch/riscv/mm/dma-mapping.c diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index d6e4e6f155a81b..466379f0cfb7f1 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -20,6 +20,10 @@ config RISCV select ARCH_HAS_DEBUG_VM_PGTABLE select ARCH_HAS_DEBUG_VIRTUAL if MMU select ARCH_HAS_DEBUG_WX + select ARCH_HAS_DMA_PREP_COHERENT + select ARCH_HAS_SYNC_DMA_FOR_CPU + select ARCH_HAS_SYNC_DMA_FOR_DEVICE + select ARCH_HAS_DMA_WRITE_COMBINE select ARCH_HAS_FORTIFY_SOURCE select ARCH_HAS_GCOV_PROFILE_ALL select ARCH_HAS_GIGANTIC_PAGE @@ -44,6 +48,7 @@ config RISCV select CLINT_TIMER if !MMU select COMMON_CLK select CPU_PM if CPU_IDLE + select DMA_DIRECT_REMAP select EDAC_SUPPORT select GENERIC_ARCH_TOPOLOGY if SMP select GENERIC_ATOMIC64 if !64BIT diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 7ea7d810418f4f..4e58a4367d04cc 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -487,6 +487,32 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma, return ptep_test_and_clear_young(vma, address, ptep); } +#define pgprot_noncached pgprot_noncached +static inline pgprot_t pgprot_noncached(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_DMA_MASK; + prot |= _PAGE_DMA_IO; + + return __pgprot(prot); +} + +#define pgprot_writecombine pgprot_writecombine +static inline pgprot_t pgprot_writecombine(pgprot_t _prot) +{ + unsigned long prot = pgprot_val(_prot); + + prot &= ~_PAGE_DMA_MASK; + prot |= _PAGE_DMA_WC; + + return __pgprot(prot); +} + +#define __HAVE_PHYS_MEM_ACCESS_PROT +extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot); + /* * THP functions */ diff --git a/arch/riscv/include/asm/sbi.h b/arch/riscv/include/asm/sbi.h index ab9782f8da52e0..ba2e3f6109706e 100644 --- a/arch/riscv/include/asm/sbi.h +++ b/arch/riscv/include/asm/sbi.h @@ -28,6 +28,7 @@ enum sbi_ext_id { SBI_EXT_RFENCE = 0x52464E43, SBI_EXT_HSM = 0x48534D, SBI_EXT_SRST = 0x53525354, + SBI_EXT_DMA = 0xAB150401, }; enum sbi_ext_base_fid { @@ -103,6 +104,24 @@ enum sbi_srst_reset_reason { SBI_SRST_RESET_REASON_SYS_FAILURE, }; +enum sbi_ext_dma_fid { + SBI_DMA_SYNC = 0, +}; + +enum sbi_dma_sync_data_direction { + SBI_DMA_BIDIRECTIONAL = 0, + SBI_DMA_TO_DEVICE = 1, + SBI_DMA_FROM_DEVICE = 2, + SBI_DMA_NONE = 3, +}; + +enum sbi_hsm_hart_status { + SBI_HSM_HART_STATUS_STARTED = 0, + SBI_HSM_HART_STATUS_STOPPED, + SBI_HSM_HART_STATUS_START_PENDING, + SBI_HSM_HART_STATUS_STOP_PENDING, +}; + #define SBI_SPEC_VERSION_DEFAULT 0x1 #define SBI_SPEC_VERSION_MAJOR_SHIFT 24 #define SBI_SPEC_VERSION_MAJOR_MASK 0x7f @@ -161,6 +180,9 @@ int sbi_remote_hfence_vvma_asid(const unsigned long *hart_mask, unsigned long size, unsigned long asid); int sbi_probe_extension(int ext); +void sbi_dma_sync(unsigned long start, + unsigned long size, + enum sbi_dma_sync_data_direction dir); /* Check if current SBI specification version is 0.1 or not */ static inline int sbi_spec_is_0_1(void) diff --git a/arch/riscv/kernel/sbi.c b/arch/riscv/kernel/sbi.c index 9a84f0cb517511..1d0c51b3a43521 100644 --- a/arch/riscv/kernel/sbi.c +++ b/arch/riscv/kernel/sbi.c @@ -548,6 +548,25 @@ int sbi_probe_extension(int extid) } EXPORT_SYMBOL(sbi_probe_extension); +void sbi_dma_sync(unsigned long start, + unsigned long size, + enum sbi_dma_sync_data_direction dir) +{ +#if 0 + sbi_ecall(SBI_EXT_DMA, SBI_DMA_SYNC, start, size, dir, + 0, 0, 0); +#else + /* Just for try, it should be in sbi ecall and will be removed before merged */ + register unsigned long i asm("a0") = start & ~(L1_CACHE_BYTES - 1); + + for (; i < ALIGN(start + size, L1_CACHE_BYTES); i += L1_CACHE_BYTES) + __asm__ __volatile__(".long 0x02b5000b"); + + __asm__ __volatile__(".long 0x01b0000b"); +#endif +} +EXPORT_SYMBOL(sbi_dma_sync); + static long __sbi_base_ecall(int fid) { struct sbiret ret; diff --git a/arch/riscv/mm/Makefile b/arch/riscv/mm/Makefile index 2d33ec574bbb2f..467853517ed97c 100644 --- a/arch/riscv/mm/Makefile +++ b/arch/riscv/mm/Makefile @@ -17,6 +17,7 @@ obj-y += extable.o obj-$(CONFIG_MMU) += fault.o pageattr.o obj-y += cacheflush.o obj-y += context.o +obj-y += dma-mapping.o ifeq ($(CONFIG_MMU),y) obj-$(CONFIG_SMP) += tlbflush.o diff --git a/arch/riscv/mm/dma-mapping.c b/arch/riscv/mm/dma-mapping.c new file mode 100644 index 00000000000000..4afd9dc3261890 --- /dev/null +++ b/arch/riscv/mm/dma-mapping.c @@ -0,0 +1,53 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include + +void arch_dma_prep_coherent(struct page *page, size_t size) +{ + void *ptr = page_address(page); + + memset(ptr, 0, size); + sbi_dma_sync(page_to_phys(page), size, SBI_DMA_BIDIRECTIONAL); +} + +void arch_sync_dma_for_device(phys_addr_t paddr, size_t size, + enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + case DMA_FROM_DEVICE: + case DMA_BIDIRECTIONAL: + sbi_dma_sync(paddr, size, dir); + break; + default: + BUG(); + } +} + +void arch_sync_dma_for_cpu(phys_addr_t paddr, size_t size, + enum dma_data_direction dir) +{ + switch (dir) { + case DMA_TO_DEVICE: + return; + case DMA_FROM_DEVICE: + case DMA_BIDIRECTIONAL: + sbi_dma_sync(paddr, size, dir); + break; + default: + BUG(); + } +} + +pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, + unsigned long size, pgprot_t vma_prot) +{ + if (!pfn_valid(pfn)) + return pgprot_noncached(vma_prot); + else if (file->f_flags & O_SYNC) + return pgprot_writecombine(vma_prot); + + return vma_prot; +} +EXPORT_SYMBOL(phys_mem_access_prot); From 0100aa76dd7e60d76de2e532abc66f615a273229 Mon Sep 17 00:00:00 2001 From: Guo Ren Date: Sun, 6 Jun 2021 09:04:06 +0000 Subject: [PATCH 018/120] riscv: cmo: Add vendor custom icache sync It's a draft version to show you how T-HEAD C9xx work with the icache sync (We use hardware broadcast mechanism, and our icache is VIPT): - icache.i(v/p)a will broadcast all harts' icache invalidtion - sync.is will broadcast all harts' pipeline flush and ensure all broadcasts finished. This patch could improve the performance of OpenJDK on JIT and reduce flush_icache_all in linux. Epecially: static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, pte_t *ptep, pte_t pteval) { if (pte_present(pteval) && pte_exec(pteval)) flush_icache_pte(pteval); set_pte(ptep, pteval); } Different from sbi_dma_sync, it can't be hidden in SBI and we must set up a framework to hold all vendors' implementations in linux/arch/riscv. Signed-off-by: Guo Ren Signed-off-by: Liu Shaohua Cc: Anup Patel Cc: Atish Patra Cc: Palmer Dabbelt Cc: Chen-Yu Tsai Cc: Drew Fustini Cc: Maxime Ripard Cc: Palmer Dabbelt Cc: Wei Fu Cc: Wei Wu --- arch/riscv/include/asm/cacheflush.h | 48 ++++++++++++++++++++++++++- arch/riscv/kernel/vdso/flush_icache.S | 33 ++++++++++++++---- arch/riscv/mm/cacheflush.c | 3 +- 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h index 23ff7035099261..2e2dba17084d6a 100644 --- a/arch/riscv/include/asm/cacheflush.h +++ b/arch/riscv/include/asm/cacheflush.h @@ -22,11 +22,57 @@ static inline void flush_dcache_page(struct page *page) } #define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1 +#define ICACHE_IPA_X5 ".long 0x0382800b" +#define ICACHE_IVA_X5 ".long 0x0302800b" +#define SYNC_IS ".long 0x01b0000b" + +static inline void flush_icache_range(unsigned long start, unsigned long end) +{ + register unsigned long tmp asm("x5") = start & (~(L1_CACHE_BYTES-1)); + + for (; tmp < ALIGN(end, L1_CACHE_BYTES); tmp += L1_CACHE_BYTES) { + __asm__ __volatile__ ( + ICACHE_IVA_X5 + : + : "r" (tmp) + : "memory"); + } + + __asm__ __volatile__(SYNC_IS); + + return; +} + +static inline void flush_icache_range_phy(unsigned long start, unsigned long end) +{ + register unsigned long tmp asm("x5") = start & (~(L1_CACHE_BYTES-1)); + + for (; tmp < ALIGN(end, L1_CACHE_BYTES); tmp += L1_CACHE_BYTES) { + __asm__ __volatile__ ( + ICACHE_IPA_X5 + : + : "r" (tmp) + : "memory"); + } + + __asm__ __volatile__(SYNC_IS); + + return; +} + +static inline void __flush_icache_page(struct page *page) { + unsigned long start = PFN_PHYS(page_to_pfn(page)); + + flush_icache_range_phy(start, start + PAGE_SIZE); + + return; +} + /* * RISC-V doesn't have an instruction to flush parts of the instruction cache, * so instead we just flush the whole thing. */ -#define flush_icache_range(start, end) flush_icache_all() +#define flush_icache_range(start, end) flush_icache_range(start, end) #define flush_icache_user_page(vma, pg, addr, len) \ flush_icache_mm(vma->vm_mm, 0) diff --git a/arch/riscv/kernel/vdso/flush_icache.S b/arch/riscv/kernel/vdso/flush_icache.S index 82f97d67c23e9b..efb2d2e8a76864 100644 --- a/arch/riscv/kernel/vdso/flush_icache.S +++ b/arch/riscv/kernel/vdso/flush_icache.S @@ -5,18 +5,39 @@ #include #include +#include + +/* + * icache.ipa rs1 + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 11000 rs1 000 00000 0001011 + * + * icache.iva rs1 + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000001 10000 rs1 000 00000 0001011 + * + * sync.is + * | 31 - 25 | 24 - 20 | 19 - 15 | 14 - 12 | 11 - 7 | 6 - 0 | + * 0000000 11011 00000 000 00000 0001011 + */ +#define ICACHE_IPA_X5 .long 0x0382800b +#define ICACHE_IVA_X5 .long 0x0302800b +#define SYNC_IS .long 0x01b0000b .text /* int __vdso_flush_icache(void *start, void *end, unsigned long flags); */ ENTRY(__vdso_flush_icache) .cfi_startproc -#ifdef CONFIG_SMP - li a7, __NR_riscv_flush_icache - ecall -#else - fence.i + srli t0, a0, L1_CACHE_SHIFT + slli t0, t0, L1_CACHE_SHIFT + addi a1, a1, (L1_CACHE_BYTES - 1) + srli a1, a1, L1_CACHE_SHIFT + slli a1, a1, L1_CACHE_SHIFT +1: ICACHE_IVA_X5 + addi t0, t0, L1_CACHE_BYTES + bne t0, a1, 1b + SYNC_IS li a0, 0 -#endif ret .cfi_endproc ENDPROC(__vdso_flush_icache) diff --git a/arch/riscv/mm/cacheflush.c b/arch/riscv/mm/cacheflush.c index 094118663285d5..0fb8344f855d65 100644 --- a/arch/riscv/mm/cacheflush.c +++ b/arch/riscv/mm/cacheflush.c @@ -3,6 +3,7 @@ * Copyright (C) 2017 SiFive */ +#include #include #ifdef CONFIG_SMP @@ -84,6 +85,6 @@ void flush_icache_pte(pte_t pte) struct page *page = pte_page(pte); if (!test_and_set_bit(PG_dcache_clean, &page->flags)) - flush_icache_all(); + __flush_icache_page(page); } #endif /* CONFIG_MMU */ From b3f68000aa7713cd4a230f82a2393948a97d6e4f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 14:17:30 -0500 Subject: [PATCH 019/120] [HACK] Enable T-HEAD MMU extensions unconditionally Signed-off-by: Samuel Holland --- arch/riscv/kernel/soc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/kernel/soc.c b/arch/riscv/kernel/soc.c index 05fa76467e6911..8c9f33f921b416 100644 --- a/arch/riscv/kernel/soc.c +++ b/arch/riscv/kernel/soc.c @@ -44,6 +44,8 @@ void __init soc_setup_vm(void) switch (vendor_id) { case THEAD_VENDOR_ID: + // Do not rely on the bootloader... + default: thead_init(); break; } From d1e94c74248405303c216eb8d9f932e09e30cd30 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 21:46:50 -0500 Subject: [PATCH 020/120] riscv: cacheinfo: Remind myself to fix this Signed-off-by: Samuel Holland --- arch/riscv/kernel/cacheinfo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/kernel/cacheinfo.c b/arch/riscv/kernel/cacheinfo.c index d8678135704425..7d5024b6aa7e3a 100644 --- a/arch/riscv/kernel/cacheinfo.c +++ b/arch/riscv/kernel/cacheinfo.c @@ -94,6 +94,7 @@ static void fill_cacheinfo(struct cacheinfo **this_leaf, { unsigned int size, sets, line_size; + /* Buggy: may not init leaves, but num_leaves was set below. */ if (!of_property_read_u32(node, "cache-size", &size) && !of_property_read_u32(node, "cache-block-size", &line_size) && !of_property_read_u32(node, "cache-sets", &sets)) { From c193219cb92e42dec989bbe46c783d55d308d039 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 15:51:36 -0600 Subject: [PATCH 021/120] bus: sun50i-de2: Use devm_of_platform_populate Signed-off-by: Samuel Holland --- drivers/bus/sun50i-de2.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/bus/sun50i-de2.c b/drivers/bus/sun50i-de2.c index 672518741f8659..889a5334558c71 100644 --- a/drivers/bus/sun50i-de2.c +++ b/drivers/bus/sun50i-de2.c @@ -11,16 +11,16 @@ static int sun50i_de2_bus_probe(struct platform_device *pdev) { - struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; int ret; - ret = sunxi_sram_claim(&pdev->dev); - if (ret) { - dev_err(&pdev->dev, "Error couldn't map SRAM to device\n"); - return ret; - } + ret = sunxi_sram_claim(dev); + if (ret) + return dev_err_probe(dev, ret, "Error couldn't map SRAM to device\n"); - of_platform_populate(np, NULL, NULL, &pdev->dev); + ret = devm_of_platform_populate(&pdev->dev); + if (ret) + return ret; return 0; } @@ -28,6 +28,7 @@ static int sun50i_de2_bus_probe(struct platform_device *pdev) static int sun50i_de2_bus_remove(struct platform_device *pdev) { sunxi_sram_release(&pdev->dev); + return 0; } From 885ac1d905ed9d234f95f71e67f5ba9b06a352ba Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:52:16 -0500 Subject: [PATCH 022/120] dt-bindings: clk: sunxi-ccu: Add compatibles for D1 CCUs Signed-off-by: Samuel Holland --- .../devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml index c4b7243ddcf247..15ed64d35261b2 100644 --- a/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml +++ b/Documentation/devicetree/bindings/clock/allwinner,sun4i-a10-ccu.yaml @@ -34,6 +34,8 @@ properties: - allwinner,sun8i-v3-ccu - allwinner,sun8i-v3s-ccu - allwinner,sun9i-a80-ccu + - allwinner,sun20i-d1-ccu + - allwinner,sun20i-d1-r-ccu - allwinner,sun50i-a64-ccu - allwinner,sun50i-a64-r-ccu - allwinner,sun50i-a100-ccu @@ -79,6 +81,7 @@ if: enum: - allwinner,sun8i-a83t-r-ccu - allwinner,sun8i-h3-r-ccu + - allwinner,sun20i-d1-r-ccu - allwinner,sun50i-a64-r-ccu - allwinner,sun50i-a100-r-ccu - allwinner,sun50i-h6-r-ccu @@ -99,6 +102,7 @@ else: properties: compatible: enum: + - allwinner,sun20i-d1-ccu - allwinner,sun50i-a100-ccu - allwinner,sun50i-h6-ccu - allwinner,sun50i-h616-ccu From 21cd1007203f8d0c213de075e4926c86bc5e4bc2 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 21:22:23 -0500 Subject: [PATCH 023/120] clk: sunxi-ng: Add missing dependency for A83T CCU Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index cd46d8853876ce..e76e1676f0f036 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -71,6 +71,7 @@ config SUN8I_A33_CCU config SUN8I_A83T_CCU bool "Support for the Allwinner A83T CCU" default MACH_SUN8I + depends on MACH_SUN8I || COMPILE_TEST config SUN8I_H3_CCU bool "Support for the Allwinner H3 CCU" From 4c39efc9928baa6714b5e3539d6eb46acf05be08 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 01:08:23 -0500 Subject: [PATCH 024/120] clk: sunxi-ng: div: Add macros using CLK_HW_INIT_HWS Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/ccu_div.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_div.h b/drivers/clk/sunxi-ng/ccu_div.h index 6682fde6043ccd..938918eca2e8c7 100644 --- a/drivers/clk/sunxi-ng/ccu_div.h +++ b/drivers/clk/sunxi-ng/ccu_div.h @@ -166,6 +166,26 @@ struct ccu_div { SUNXI_CCU_M_WITH_GATE(_struct, _name, _parent, _reg, \ _mshift, _mwidth, 0, _flags) +#define SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \ + _mshift, _mwidth, _gate, \ + _flags) \ + struct ccu_div _struct = { \ + .enable = _gate, \ + .div = _SUNXI_CCU_DIV(_mshift, _mwidth), \ + .common = { \ + .reg = _reg, \ + .hw.init = CLK_HW_INIT_HWS(_name, \ + _parent, \ + &ccu_div_ops, \ + _flags), \ + }, \ + } + +#define SUNXI_CCU_M_HWS(_struct, _name, _parent, _reg, _mshift, \ + _mwidth, _flags) \ + SUNXI_CCU_M_HWS_WITH_GATE(_struct, _name, _parent, _reg, \ + _mshift, _mwidth, 0, _flags) + static inline struct ccu_div *hw_to_ccu_div(struct clk_hw *hw) { struct ccu_common *common = hw_to_ccu_common(hw); From 4718a73989eb9c850a3388ae6841e6d1779e327d Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 01:21:11 -0500 Subject: [PATCH 025/120] clk: sunxi-ng: Add macros for gates with fixed dividers Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/ccu_gate.h | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu_gate.h b/drivers/clk/sunxi-ng/ccu_gate.h index c386689a952b89..ae1331228873ec 100644 --- a/drivers/clk/sunxi-ng/ccu_gate.h +++ b/drivers/clk/sunxi-ng/ccu_gate.h @@ -53,7 +53,7 @@ struct ccu_gate { } /* - * The following two macros allow the re-use of the data structure + * The following macros allow the re-use of the data structure * holding the parent info. */ #define SUNXI_CCU_GATE_HWS(_struct, _name, _parent, _reg, _gate, _flags) \ @@ -68,6 +68,21 @@ struct ccu_gate { } \ } +#define SUNXI_CCU_GATE_HWS_WITH_PREDIV(_struct, _name, _parent, _reg, \ + _gate, _prediv, _flags) \ + struct ccu_gate _struct = { \ + .enable = _gate, \ + .common = { \ + .reg = _reg, \ + .prediv = _prediv, \ + .features = CCU_FEATURE_ALL_PREDIV, \ + .hw.init = CLK_HW_INIT_HWS(_name, \ + _parent, \ + &ccu_gate_ops, \ + _flags), \ + } \ + } + #define SUNXI_CCU_GATE_DATA(_struct, _name, _data, _reg, _gate, _flags) \ struct ccu_gate _struct = { \ .enable = _gate, \ From 9c03f58b50140e51085bb023a51537e046cc8987 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 01:08:47 -0500 Subject: [PATCH 026/120] clk: sunxi-ng: mux: Remove unused field Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/ccu_mux.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h index f165395effb5a5..e31efc509b3dab 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.h +++ b/drivers/clk/sunxi-ng/ccu_mux.h @@ -40,7 +40,6 @@ struct ccu_mux_internal { _SUNXI_CCU_MUX_TABLE(_shift, _width, NULL) struct ccu_mux { - u16 reg; u32 enable; struct ccu_mux_internal mux; From 4bf6056529691467ed606969d39880501e1bc068 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 20 May 2021 00:07:32 -0500 Subject: [PATCH 027/120] clk: sunxi-ng: Allow muxes to have keys Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/ccu_common.h | 1 + drivers/clk/sunxi-ng/ccu_mux.c | 7 +++++++ drivers/clk/sunxi-ng/ccu_mux.h | 14 ++++++++++++++ 3 files changed, 22 insertions(+) diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h index 04e7a12200a212..53d8ebc85ad7f5 100644 --- a/drivers/clk/sunxi-ng/ccu_common.h +++ b/drivers/clk/sunxi-ng/ccu_common.h @@ -17,6 +17,7 @@ #define CCU_FEATURE_LOCK_REG BIT(5) #define CCU_FEATURE_MMC_TIMING_SWITCH BIT(6) #define CCU_FEATURE_SIGMA_DELTA_MOD BIT(7) +#define CCU_FEATURE_KEY_FIELD BIT(8) /* MMC timing mode switch bit */ #define CCU_MMC_NEW_TIMING_MODE BIT(30) diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c index 7d75da9a1f2e54..55dee677958662 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.c +++ b/drivers/clk/sunxi-ng/ccu_mux.c @@ -12,6 +12,8 @@ #include "ccu_gate.h" #include "ccu_mux.h" +#define CCU_MUX_KEY_VALUE 0x16aa0000 + static u16 ccu_mux_get_prediv(struct ccu_common *common, struct ccu_mux_internal *cm, int parent_index) @@ -188,6 +190,11 @@ int ccu_mux_helper_set_parent(struct ccu_common *common, spin_lock_irqsave(common->lock, flags); reg = readl(common->base + common->reg); + + /* The key field always reads as zero. */ + if (common->features & CCU_FEATURE_KEY_FIELD) + reg |= CCU_MUX_KEY_VALUE; + reg &= ~GENMASK(cm->width + cm->shift - 1, cm->shift); writel(reg | (index << cm->shift), common->base + common->reg); diff --git a/drivers/clk/sunxi-ng/ccu_mux.h b/drivers/clk/sunxi-ng/ccu_mux.h index e31efc509b3dab..268ccaef715e95 100644 --- a/drivers/clk/sunxi-ng/ccu_mux.h +++ b/drivers/clk/sunxi-ng/ccu_mux.h @@ -72,6 +72,20 @@ struct ccu_mux { SUNXI_CCU_MUX_TABLE_WITH_GATE(_struct, _name, _parents, NULL, \ _reg, _shift, _width, 0, _flags) +#define SUNXI_CCU_MUX_HW_WITH_KEY(_struct, _name, _parents, _reg, \ + _shift, _width, _key, _flags) \ + struct ccu_mux _struct = { \ + .mux = _SUNXI_CCU_MUX(_shift, _width), \ + .common = { \ + .reg = _reg, \ + .features = CCU_FEATURE_KEY_FIELD, \ + .hw.init = CLK_HW_INIT_PARENTS_HW(_name, \ + _parents, \ + &ccu_mux_ops, \ + _flags), \ + } \ + } + static inline struct ccu_mux *hw_to_ccu_mux(struct clk_hw *hw) { struct ccu_common *common = hw_to_ccu_common(hw); From 9510ca9e95cb424ec0d88aa37af4c9113d6ea3b7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 20 May 2021 00:08:20 -0500 Subject: [PATCH 028/120] clk: sunxi-ng: Add support for newer sun50i RTCs Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/Kconfig | 5 + drivers/clk/sunxi-ng/Makefile | 1 + drivers/clk/sunxi-ng/ccu-sun50i-rtc.c | 384 +++++++++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun50i-rtc.h | 15 + include/dt-bindings/clock/sun50i-rtc.h | 14 + 5 files changed, 419 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-rtc.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun50i-rtc.h create mode 100644 include/dt-bindings/clock/sun50i-rtc.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index e76e1676f0f036..efa01c26dbace8 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -42,6 +42,11 @@ config SUN50I_H6_R_CCU default ARM64 && ARCH_SUNXI depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST +config SUN50I_RTC_CCU + bool "Support for the Allwinner H6/H616/R329/D1 RTC" + default ARCH_SUNXI || SOC_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST + config SUN4I_A10_CCU bool "Support for the Allwinner A10/A20 CCU" default MACH_SUN4I diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 96c324306d97fa..19ffe443301f0f 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o obj-$(CONFIG_SUN50I_H6_CCU) += ccu-sun50i-h6.o obj-$(CONFIG_SUN50I_H616_CCU) += ccu-sun50i-h616.o obj-$(CONFIG_SUN50I_H6_R_CCU) += ccu-sun50i-h6-r.o +obj-$(CONFIG_SUN50I_RTC_CCU) += ccu-sun50i-rtc.o obj-$(CONFIG_SUN4I_A10_CCU) += ccu-sun4i-a10.o obj-$(CONFIG_SUN5I_CCU) += ccu-sun5i.o obj-$(CONFIG_SUN6I_A31_CCU) += ccu-sun6i-a31.o diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun50i-rtc.c new file mode 100644 index 00000000000000..a2b468e5cacbf9 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-rtc.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: GPL-2.0-only + +#include +#include + +#include "../clk.h" + +#include "ccu_common.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mux.h" + +#include "ccu-sun50i-rtc.h" + +#define LOSC_FREQ 32768 +#define LOSC_FREQ_SHIFT 15 + +#define LOSC_CTRL_KEY 0x16aa0000 + +#define IOSC_32K_CLK_DIV_REG 0x8 +#define IOSC_32K_CLK_DIV GENMASK(4, 0) +#define IOSC_32K_PRE_DIV 32 + +#define IOSC_CLK_CALI_REG 0xc +#define IOSC_CLK_CALI_DIV_ONES 22 +#define IOSC_CLK_CALI_EN BIT(1) +#define IOSC_CLK_CALI_SRC_SEL BIT(0) + +#define DCXO_CTRL_REG 0x160 +#define DCXO_CTRL_CLK16M_RC_EN BIT(0) + +bool have_ext_osc32k; +bool have_iosc_calib; + +static int ccu_iosc_enable(struct clk_hw *hw) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + + return ccu_gate_helper_enable(cm, DCXO_CTRL_CLK16M_RC_EN); +} + +static void ccu_iosc_disable(struct clk_hw *hw) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + + return ccu_gate_helper_disable(cm, DCXO_CTRL_CLK16M_RC_EN); +} + +static int ccu_iosc_is_enabled(struct clk_hw *hw) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + + return ccu_gate_helper_is_enabled(cm, DCXO_CTRL_CLK16M_RC_EN); +} + +static unsigned long ccu_iosc_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + + if (have_iosc_calib) { + u32 reg = readl(cm->base + IOSC_CLK_CALI_REG); + + /* + * Recover the IOSC frequency by shifting the ones place of + * (fixed-point divider * 32768) into bit zero. + */ + if (reg & IOSC_CLK_CALI_EN) + return reg >> (IOSC_CLK_CALI_DIV_ONES - LOSC_FREQ_SHIFT); + } + + return 16000000; +} + +static unsigned long ccu_iosc_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_accuracy) +{ + return 300000000; +} + +static const struct clk_ops ccu_iosc_ops = { + .enable = ccu_iosc_enable, + .disable = ccu_iosc_disable, + .is_enabled = ccu_iosc_is_enabled, + .recalc_rate = ccu_iosc_recalc_rate, + .recalc_accuracy = ccu_iosc_recalc_accuracy, +}; + +static struct ccu_common iosc_clk = { + .reg = DCXO_CTRL_REG, + .hw.init = CLK_HW_INIT_NO_PARENT("iosc", &ccu_iosc_ops, + CLK_GET_RATE_NOCACHE), +}; + +static int ccu_iosc_32k_enable(struct clk_hw *hw) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + unsigned long flags; + u32 reg; + + if (!have_iosc_calib) + return 0; + + spin_lock_irqsave(cm->lock, flags); + + reg = readl(cm->base + IOSC_CLK_CALI_REG); + writel(reg | IOSC_CLK_CALI_EN | IOSC_CLK_CALI_SRC_SEL, + cm->base + IOSC_CLK_CALI_REG); + + spin_unlock_irqrestore(cm->lock, flags); + + return 0; +} + +static void ccu_iosc_32k_disable(struct clk_hw *hw) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + unsigned long flags; + u32 reg; + + if (!have_iosc_calib) + return; + + spin_lock_irqsave(cm->lock, flags); + + reg = readl(cm->base + IOSC_CLK_CALI_REG); + writel(reg & ~(IOSC_CLK_CALI_EN | IOSC_CLK_CALI_SRC_SEL), + cm->base + IOSC_CLK_CALI_REG); + + spin_unlock_irqrestore(cm->lock, flags); +} + +static unsigned long ccu_iosc_32k_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + u32 reg; + + if (have_iosc_calib) { + reg = readl(cm->base + IOSC_CLK_CALI_REG); + + if (reg & IOSC_CLK_CALI_SRC_SEL) + return LOSC_FREQ; + } + + reg = readl(cm->base + IOSC_32K_CLK_DIV_REG) & IOSC_32K_CLK_DIV; + + return parent_rate / IOSC_32K_PRE_DIV / (reg + 1); +} + +static unsigned long ccu_iosc_32k_recalc_accuracy(struct clk_hw *hw, + unsigned long parent_accuracy) +{ + struct ccu_common *cm = hw_to_ccu_common(hw); + + if (have_iosc_calib) { + u32 reg = readl(cm->base + IOSC_CLK_CALI_REG); + + if (reg & IOSC_CLK_CALI_SRC_SEL) + return 0; + } + + return parent_accuracy; +} + +static const struct clk_ops ccu_iosc_32k_ops = { + .enable = ccu_iosc_32k_enable, + .disable = ccu_iosc_32k_disable, + .recalc_rate = ccu_iosc_32k_recalc_rate, + .recalc_accuracy = ccu_iosc_32k_recalc_accuracy, +}; + +static struct ccu_common iosc_32k_clk = { + .hw.init = CLK_HW_INIT_HW("iosc-32k", &iosc_clk.hw, + &ccu_iosc_32k_ops, 0), +}; + +static const struct clk_hw *ext_osc32k[] = { NULL }; +static SUNXI_CCU_GATE_HWS(ext_osc32k_gate_clk, "ext-osc32k-gate", + ext_osc32k, 0x0, BIT(4), 0); + +static const struct clk_hw *osc32k_parents[] = { &iosc_32k_clk.hw, + &ext_osc32k_gate_clk.common.hw }; +static SUNXI_CCU_MUX_HW_WITH_KEY(osc32k_clk, "osc32k", osc32k_parents, + 0x0, 0, 1, LOSC_CTRL_KEY, 0); + +static struct clk_fixed_rate dcxo24M_clk = { + .fixed_rate = 24000000, + .hw.init = CLK_HW_INIT_NO_PARENT("dcxo24M", &clk_fixed_rate_ops, 0), +}; + +static struct ccu_gate dcxo24M_32k_clk = { + .enable = BIT(16), + .common = { + .reg = 0x60, + .prediv = 750, + .features = CCU_FEATURE_ALL_PREDIV, + .hw.init = CLK_HW_INIT_HW("dcxo24M-32k", + &dcxo24M_clk.hw, + &ccu_gate_ops, + 0), + }, +}; + +static CLK_FIXED_FACTOR_HW(rtc_32k_clk, "rtc-32k", + &osc32k_clk.common.hw, 1, 1, 0); + +static const struct clk_hw *rtc_32k_parents[] = { &osc32k_clk.common.hw, + &dcxo24M_32k_clk.common.hw }; +static SUNXI_CCU_MUX_HW_WITH_KEY(rtc_32k_mux_clk, "rtc-32k", rtc_32k_parents, + 0x0, 1, 1, LOSC_CTRL_KEY, 0); + +static CLK_FIXED_FACTOR(rtc_1k_clk, "rtc-1k", + "rtc-32k", 32, 1, 0); + +static const char *rtc_32k_fanout_parents[] = { "osc32k", + "pll-periph0-32k", + "dcxo24M-32k" }; +static SUNXI_CCU_MUX_WITH_GATE(rtc_32k_fanout_clk, "rtc-32k-fanout", + rtc_32k_fanout_parents, 0x60, 1, 2, BIT(0), 0); + +static SUNXI_CCU_M_WITH_GATE(rtc_spi_clk, "rtc-spi", "r-ahb", + 0x310, 0, 5, BIT(31), 0); + +static struct ccu_common *sun50i_h6_rtc_ccu_clks[] = { + &iosc_clk, + &iosc_32k_clk, + &ext_osc32k_gate_clk.common, + &osc32k_clk.common, + &dcxo24M_32k_clk.common, + &rtc_32k_mux_clk.common, +}; + +static struct ccu_common *sun50i_h616_rtc_ccu_clks[] = { + &iosc_clk, + &iosc_32k_clk, + &osc32k_clk.common, + &dcxo24M_32k_clk.common, + &rtc_32k_fanout_clk.common, +}; + +static struct ccu_common *sun50i_r329_rtc_ccu_clks[] = { + &iosc_clk, + &iosc_32k_clk, + &ext_osc32k_gate_clk.common, + &osc32k_clk.common, + &dcxo24M_32k_clk.common, + &rtc_32k_mux_clk.common, + &rtc_32k_fanout_clk.common, + &rtc_spi_clk.common, +}; + +static struct clk_hw_onecell_data sun50i_h6_rtc_ccu_hw_clks = { + .num = CLK_NUMBER, + .hws = { + [CLK_OSC32K] = &osc32k_clk.common.hw, + [CLK_RTC_32K_FANOUT] = NULL, + [CLK_IOSC] = &iosc_clk.hw, + [CLK_DCXO24M] = &dcxo24M_clk.hw, + + [CLK_IOSC_32K] = &iosc_32k_clk.hw, + [CLK_EXT_OSC32K_GATE] = &ext_osc32k_gate_clk.common.hw, + [CLK_DCXO24M_32K] = &dcxo24M_32k_clk.common.hw, + [CLK_RTC_32K] = &rtc_32k_mux_clk.common.hw, + [CLK_RTC_1K] = &rtc_1k_clk.hw, + [CLK_RTC_SPI] = NULL, + }, +}; + +static struct clk_hw_onecell_data sun50i_h616_rtc_ccu_hw_clks = { + .num = CLK_NUMBER, + .hws = { + [CLK_OSC32K] = &osc32k_clk.common.hw, + [CLK_RTC_32K_FANOUT] = &rtc_32k_fanout_clk.common.hw, + [CLK_IOSC] = &iosc_clk.hw, + [CLK_DCXO24M] = &dcxo24M_clk.hw, + + [CLK_IOSC_32K] = &iosc_32k_clk.hw, + [CLK_EXT_OSC32K_GATE] = NULL, + [CLK_DCXO24M_32K] = &dcxo24M_32k_clk.common.hw, + [CLK_RTC_32K] = &rtc_32k_clk.hw, + [CLK_RTC_1K] = &rtc_1k_clk.hw, + [CLK_RTC_SPI] = NULL, + }, +}; + +static struct clk_hw_onecell_data sun50i_r329_rtc_ccu_hw_clks = { + .num = CLK_NUMBER, + .hws = { + [CLK_OSC32K] = &osc32k_clk.common.hw, + [CLK_RTC_32K_FANOUT] = &rtc_32k_fanout_clk.common.hw, + [CLK_IOSC] = &iosc_clk.hw, + [CLK_DCXO24M] = &dcxo24M_clk.hw, + + [CLK_IOSC_32K] = &iosc_32k_clk.hw, + [CLK_EXT_OSC32K_GATE] = &ext_osc32k_gate_clk.common.hw, + [CLK_DCXO24M_32K] = &dcxo24M_32k_clk.common.hw, + [CLK_RTC_32K] = &rtc_32k_mux_clk.common.hw, + [CLK_RTC_1K] = &rtc_1k_clk.hw, + [CLK_RTC_SPI] = &rtc_spi_clk.common.hw, + }, +}; + +static const struct sunxi_ccu_desc sun50i_h6_rtc_ccu_desc = { + .ccu_clks = sun50i_h6_rtc_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h6_rtc_ccu_clks), + + .hw_clks = &sun50i_h6_rtc_ccu_hw_clks, +}; + +static const struct sunxi_ccu_desc sun50i_h616_rtc_ccu_desc = { + .ccu_clks = sun50i_h616_rtc_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_h616_rtc_ccu_clks), + + .hw_clks = &sun50i_h616_rtc_ccu_hw_clks, +}; + +static const struct sunxi_ccu_desc sun50i_r329_rtc_ccu_desc = { + .ccu_clks = sun50i_r329_rtc_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun50i_r329_rtc_ccu_clks), + + .hw_clks = &sun50i_r329_rtc_ccu_hw_clks, +}; + +static void __init sunxi_rtc_ccu_init(struct device_node *node, + const struct sunxi_ccu_desc *desc) +{ + void __iomem *reg; + + reg = of_iomap(node, 0); + if (IS_ERR(reg)) { + pr_err("%pOF: Could not map the clock registers\n", node); + return; + } + + if (have_ext_osc32k) { + rtc_32k_fanout_parents[1] = "ext-osc32k-gate"; + *ext_osc32k = of_clk_get_hw(node, 0, "ext-osc"); + if (IS_ERR(*ext_osc32k)) { + struct clk_init_data *init = (struct clk_init_data *) + ext_osc32k_gate_clk.common.hw.init; + + init->num_parents = 0; + } + } else { + struct clk_init_data *init = (struct clk_init_data *) + osc32k_clk.common.hw.init; + + init->num_parents = 1; + } + + sunxi_ccu_probe(node, reg, desc); +} + +static void __init sun50i_h6_rtc_ccu_setup(struct device_node *node) +{ + have_ext_osc32k = 1; + have_iosc_calib = 1; + + sunxi_rtc_ccu_init(node, &sun50i_h6_rtc_ccu_desc); +} +CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_ccu, "allwinner,sun50i-h6-rtc", + sun50i_h6_rtc_ccu_setup); + +static void __init sun50i_h616_rtc_ccu_setup(struct device_node *node) +{ + have_ext_osc32k = 0; + have_iosc_calib = 1; + + sunxi_rtc_ccu_init(node, &sun50i_h616_rtc_ccu_desc); +} +CLK_OF_DECLARE_DRIVER(sun50i_h616_rtc_ccu, "allwinner,sun50i-h616-rtc", + sun50i_h616_rtc_ccu_setup); + +static void __init sun50i_r329_rtc_ccu_setup(struct device_node *node) +{ + have_ext_osc32k = 1; + have_iosc_calib = 0; + + sunxi_rtc_ccu_init(node, &sun50i_r329_rtc_ccu_desc); +} +CLK_OF_DECLARE_DRIVER(sun50i_r329_rtc_ccu, "allwinner,sun50i-r329-rtc", + sun50i_r329_rtc_ccu_setup); diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-rtc.h b/drivers/clk/sunxi-ng/ccu-sun50i-rtc.h new file mode 100644 index 00000000000000..537a73938c17d8 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun50i-rtc.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _CCU_SUN50I_RTC_H +#define _CCU_SUN50I_RTC_H + +#include + +#define CLK_IOSC_32K 4 +#define CLK_EXT_OSC32K_GATE 5 +#define CLK_DCXO24M_32K 6 +#define CLK_RTC_32K 7 + +#define CLK_NUMBER (CLK_RTC_SPI + 1) + +#endif /* _CCU_SUN50I_RTC_H */ diff --git a/include/dt-bindings/clock/sun50i-rtc.h b/include/dt-bindings/clock/sun50i-rtc.h new file mode 100644 index 00000000000000..80058778ee1776 --- /dev/null +++ b/include/dt-bindings/clock/sun50i-rtc.h @@ -0,0 +1,14 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef _DT_BINDINGS_CLK_SUN50I_RTC_CCU_H_ +#define _DT_BINDINGS_CLK_SUN50I_RTC_CCU_H_ + +#define CLK_OSC32K 0 +#define CLK_RTC_32K_FANOUT 1 +#define CLK_IOSC 2 +#define CLK_DCXO24M 3 + +#define CLK_RTC_1K 8 +#define CLK_RTC_SPI 9 + +#endif /* _DT_BINDINGS_CLK_SUN50I_RTC_CCU_H_ */ From f4fea1bdb586adb8c9a73e1db458fb5acd2b006b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Thu, 20 May 2021 00:09:46 -0500 Subject: [PATCH 029/120] clk: sunxi-ng: Add support for the D1 SoC clocks Signed-off-by: Samuel Holland --- drivers/clk/sunxi-ng/Kconfig | 10 + drivers/clk/sunxi-ng/Makefile | 2 + drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c | 129 ++ drivers/clk/sunxi-ng/ccu-sun20i-d1-r.h | 18 + drivers/clk/sunxi-ng/ccu-sun20i-d1.c | 1284 +++++++++++++++++++ drivers/clk/sunxi-ng/ccu-sun20i-d1.h | 15 + include/dt-bindings/clock/sun20i-d1-ccu.h | 159 +++ include/dt-bindings/clock/sun20i-d1-r-ccu.h | 18 + include/dt-bindings/reset/sun20i-d1-ccu.h | 77 ++ include/dt-bindings/reset/sun20i-d1-r-ccu.h | 17 + 10 files changed, 1729 insertions(+) create mode 100644 drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun20i-d1-r.h create mode 100644 drivers/clk/sunxi-ng/ccu-sun20i-d1.c create mode 100644 drivers/clk/sunxi-ng/ccu-sun20i-d1.h create mode 100644 include/dt-bindings/clock/sun20i-d1-ccu.h create mode 100644 include/dt-bindings/clock/sun20i-d1-r-ccu.h create mode 100644 include/dt-bindings/reset/sun20i-d1-ccu.h create mode 100644 include/dt-bindings/reset/sun20i-d1-r-ccu.h diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index efa01c26dbace8..9ec2ffcf783021 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -12,6 +12,16 @@ config SUNIV_F1C100S_CCU default MACH_SUNIV depends on MACH_SUNIV || COMPILE_TEST +config SUN20I_D1_CCU + bool "Support for the Allwinner D1 CCU" + default SOC_SUNXI + depends on SOC_SUNXI || COMPILE_TEST + +config SUN20I_D1_R_CCU + bool "Support for the Allwinner D1 PRCM CCU" + default SOC_SUNXI + depends on SOC_SUNXI || COMPILE_TEST + config SUN50I_A64_CCU bool "Support for the Allwinner A64 CCU" default ARM64 && ARCH_SUNXI diff --git a/drivers/clk/sunxi-ng/Makefile b/drivers/clk/sunxi-ng/Makefile index 19ffe443301f0f..e80e58e825eeb9 100644 --- a/drivers/clk/sunxi-ng/Makefile +++ b/drivers/clk/sunxi-ng/Makefile @@ -22,6 +22,8 @@ obj-y += ccu_mp.o # SoC support obj-$(CONFIG_SUNIV_F1C100S_CCU) += ccu-suniv-f1c100s.o +obj-$(CONFIG_SUN20I_D1_CCU) += ccu-sun20i-d1.o +obj-$(CONFIG_SUN20I_D1_R_CCU) += ccu-sun20i-d1-r.o obj-$(CONFIG_SUN50I_A64_CCU) += ccu-sun50i-a64.o obj-$(CONFIG_SUN50I_A100_CCU) += ccu-sun50i-a100.o obj-$(CONFIG_SUN50I_A100_R_CCU) += ccu-sun50i-a100-r.o diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c new file mode 100644 index 00000000000000..d23d3d32e69737 --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 huangzhenwei@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#include +#include + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_gate.h" +#include "ccu_mp.h" + +#include "ccu-sun20i-d1-r.h" + +static const char * const r_ahb_apb0_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-periph0-div3" }; +static SUNXI_CCU_MP_WITH_MUX(r_ahb_clk, "r-ahb", + r_ahb_apb0_parents, 0x000, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + 0); +static const struct clk_hw *r_ahb_hw = &r_ahb_clk.common.hw; + +static SUNXI_CCU_MP_WITH_MUX(r_apb0_clk, "r-apb0", + r_ahb_apb0_parents, 0x00c, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + 0); +static const struct clk_hw *r_apb0_hw = &r_apb0_clk.common.hw; + +static SUNXI_CCU_GATE_HWS(bus_r_timer_clk, "bus-r-timer", &r_apb0_hw, + 0x11c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_r_twd_clk, "bus-r-twd", &r_apb0_hw, + 0x12c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_r_ppu_clk, "bus-r-ppu", &r_apb0_hw, + 0x1ac, BIT(0), 0); + +static const char * const r_ir_rx_parents[] = { "osc32k", "dcxo24M" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(r_ir_rx_clk, "r-ir-rx", + r_ir_rx_parents, 0x1c0, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_r_ir_rx_clk, "bus-r-ir-rx", &r_apb0_hw, + 0x1cc, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_r_rtc_clk, "bus-r-rtc", &r_ahb_hw, + 0x20c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_r_cpucfg_clk, "bus-r-cpucfg", &r_apb0_hw, + 0x22c, BIT(0), 0); + +static struct ccu_common *sun20i_d1_r_ccu_clks[] = { + &r_ahb_clk.common, + &r_apb0_clk.common, + &bus_r_timer_clk.common, + &bus_r_twd_clk.common, + &bus_r_ppu_clk.common, + &r_ir_rx_clk.common, + &bus_r_ir_rx_clk.common, + &bus_r_rtc_clk.common, + &bus_r_cpucfg_clk.common, +}; + +static struct clk_hw_onecell_data sun20i_d1_r_hw_clks = { + .num = CLK_NUMBER, + .hws = { + [CLK_R_AHB] = &r_ahb_clk.common.hw, + [CLK_R_APB0] = &r_apb0_clk.common.hw, + [CLK_BUS_R_TIMER] = &bus_r_timer_clk.common.hw, + [CLK_BUS_R_TWD] = &bus_r_twd_clk.common.hw, + [CLK_BUS_R_PPU] = &bus_r_ppu_clk.common.hw, + [CLK_R_IR_RX] = &r_ir_rx_clk.common.hw, + [CLK_BUS_R_IR_RX] = &bus_r_ir_rx_clk.common.hw, + [CLK_BUS_R_RTC] = &bus_r_rtc_clk.common.hw, + [CLK_BUS_R_CPUCFG] = &bus_r_cpucfg_clk.common.hw, + }, +}; + +static struct ccu_reset_map sun20i_d1_r_ccu_resets[] = { + [RST_BUS_R_TIMER] = { 0x11c, BIT(16) }, + [RST_BUS_R_TWD] = { 0x12c, BIT(16) }, + [RST_BUS_R_PPU] = { 0x1ac, BIT(16) }, + [RST_BUS_R_IR_RX] = { 0x1cc, BIT(16) }, + [RST_BUS_R_RTC] = { 0x20c, BIT(16) }, + [RST_BUS_R_CPUCFG] = { 0x22c, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun20i_d1_r_ccu_desc = { + .ccu_clks = sun20i_d1_r_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun20i_d1_r_ccu_clks), + + .hw_clks = &sun20i_d1_r_hw_clks, + + .resets = sun20i_d1_r_ccu_resets, + .num_resets = ARRAY_SIZE(sun20i_d1_r_ccu_resets), +}; + +static int sun20i_d1_r_ccu_probe(struct platform_device *pdev) +{ + void __iomem *reg; + + reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + return sunxi_ccu_probe(pdev->dev.of_node, reg, &sun20i_d1_r_ccu_desc); +} + +static const struct of_device_id sun20i_d1_r_ccu_ids[] = { + { .compatible = "allwinner,sun20i-d1-r-ccu" }, + { } +}; + +static struct platform_driver sun20i_d1_r_ccu_driver = { + .probe = sun20i_d1_r_ccu_probe, + .driver = { + .name = "sun20i-d1-r-ccu", + .of_match_table = sun20i_d1_r_ccu_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(sun20i_d1_r_ccu_driver); diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.h b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.h new file mode 100644 index 00000000000000..38e5b7d982273a --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 frank@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#ifndef _CCU_SUN20I_D1_R_H +#define _CCU_SUN20I_D1_R_H + +#include +#include + +#define CLK_R_AHB 0 +#define CLK_R_APB0 1 + +#define CLK_NUMBER (CLK_BUS_R_CPUCFG + 1) + +#endif /* _CCU_SUN20I_D1_R_H */ diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c new file mode 100644 index 00000000000000..af72208a080b9e --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c @@ -0,0 +1,1284 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (c) 2020 huangzhenwei@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#include +#include +#include + +#include "../clk.h" + +#include "ccu_common.h" +#include "ccu_reset.h" + +#include "ccu_div.h" +#include "ccu_gate.h" +#include "ccu_mp.h" +#include "ccu_mult.h" +#include "ccu_nk.h" +#include "ccu_nkm.h" +#include "ccu_nkmp.h" +#include "ccu_nm.h" + +#include "ccu-sun20i-d1.h" + +static const struct clk_hw *dcxo24M_hws[] = { NULL }; + +static CLK_FIXED_FACTOR_HWS(dcxo12M, "dcxo12M", + dcxo24M_hws, 2, 1, 0); + +/* + * For the CPU PLL, the output divider is described as "only for testing" + * in the user manual. So it's not modelled and forced to 0. + */ +#define SUN20I_D1_PLL_CPUX_REG 0x000 +static struct ccu_mult pll_cpux_clk = { + .enable = BIT(27), + .lock = BIT(28), + .mult = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .common = { + .reg = 0x000, + .hw.init = CLK_HW_INIT_HWS("pll-cpux", dcxo24M_hws, + &ccu_mult_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */ +#define SUN20I_D1_PLL_DDR0_REG 0x010 +static struct ccu_nkmp pll_ddr0_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x010, + .hw.init = CLK_HW_INIT_HWS("pll-ddr0", dcxo24M_hws, + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +#define SUN20I_D1_PLL_PERIPH0_REG 0x020 +static struct ccu_nm pll_periph0_4x_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .common = { + .reg = 0x020, + .hw.init = CLK_HW_INIT_HWS("pll-periph0-4x", dcxo24M_hws, + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const struct clk_hw *pll_periph0_4x_hws[] = { + &pll_periph0_4x_clk.common.hw +}; +static SUNXI_CCU_M_HWS(pll_periph0_2x_clk, "pll-periph0-2x", + pll_periph0_4x_hws, 0x020, 16, 3, 0); +static SUNXI_CCU_M_HWS(pll_periph0_800M_clk, "pll-periph0-800M", + pll_periph0_4x_hws, 0x020, 20, 3, 0); + +static const struct clk_hw *pll_periph0_2x_hws[] = { + &pll_periph0_2x_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_periph0_clk, "pll-periph0", + pll_periph0_2x_hws, 2, 1, 0); + +static const struct clk_hw *pll_periph0_hws[] = { &pll_periph0_clk.hw }; +static CLK_FIXED_FACTOR_HWS(pll_periph0_div3_clk, "pll-periph0-div3", + pll_periph0_2x_hws, 6, 1, 0); + +/* + * For Video PLLs, the output divider is described as "only for testing" + * in the user manual. So it's not modelled and forced to 0. + */ +#define SUN20I_D1_PLL_VIDEO0_REG 0x040 +static struct ccu_nm pll_video0_4x_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .common = { + .reg = 0x040, + .hw.init = CLK_HW_INIT_HWS("pll-video0-4x", dcxo24M_hws, + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const struct clk_hw *pll_video0_4x_hws[] = { + &pll_video0_4x_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_video0_2x_clk, "pll-video0-2x", + pll_video0_4x_hws, 2, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_video0_clk, "pll-video0", + pll_video0_4x_hws, 4, 1, CLK_SET_RATE_PARENT); + +#define SUN20I_D1_PLL_VIDEO1_REG 0x048 +static struct ccu_nm pll_video1_4x_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .common = { + .reg = 0x048, + .hw.init = CLK_HW_INIT_HWS("pll-video1-4x", dcxo24M_hws, + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const struct clk_hw *pll_video1_4x_hws[] = { + &pll_video1_4x_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_video1_2x_clk, "pll-video1-2x", + pll_video1_4x_hws, 2, 1, CLK_SET_RATE_PARENT); +static CLK_FIXED_FACTOR_HWS(pll_video1_clk, "pll-video1", + pll_video1_4x_hws, 4, 1, CLK_SET_RATE_PARENT); + +#define SUN20I_D1_PLL_VE_REG 0x058 +static struct ccu_nkmp pll_ve_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), /* input divider */ + .p = _SUNXI_CCU_DIV(0, 1), /* output divider */ + .common = { + .reg = 0x058, + .hw.init = CLK_HW_INIT_HWS("pll-ve", dcxo24M_hws, + &ccu_nkmp_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +/* + * PLL_AUDIO0 has m0, m1 dividers in addition to the usual N, M factors. + * Since we only need one frequency from this PLL (22.5792 x 4 == 90.3168 MHz), + * ignore them for now. Enforce the default for them, which is m1 = 0, m0 = 0. + * The M factor must be an even number to produce a 50% duty cycle output. + */ +#define SUN20I_D1_PLL_AUDIO0_REG 0x078 +static struct ccu_sdm_setting pll_audio0_sdm_table[] = { + { .rate = 90316800, .pattern = 0xc001288d, .m = 6, .n = 22 }, +}; + +static struct ccu_nm pll_audio0_4x_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(16, 6), + .sdm = _SUNXI_CCU_SDM(pll_audio0_sdm_table, BIT(24), + 0x178, BIT(31)), + .common = { + .reg = 0x078, + .features = CCU_FEATURE_SIGMA_DELTA_MOD, + .hw.init = CLK_HW_INIT_HWS("pll-audio0-4x", dcxo24M_hws, + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const struct clk_hw *pll_audio0_4x_hws[] = { + &pll_audio0_4x_clk.common.hw +}; +static CLK_FIXED_FACTOR_HWS(pll_audio0_2x_clk, "pll-audio0-2x", + pll_audio0_4x_hws, 2, 1, 0); +static CLK_FIXED_FACTOR_HWS(pll_audio0_clk, "pll-audio0", + pll_audio0_4x_hws, 4, 1, 0); + +/* + * PLL_AUDIO1 doesn't need Fractional-N. The output is usually 614.4 MHz for + * audio. The ADC or DAC should divide the PLL output further to 24.576 MHz. + */ +#define SUN20I_D1_PLL_AUDIO1_REG 0x080 +static struct ccu_nm pll_audio1_clk = { + .enable = BIT(27), + .lock = BIT(28), + .n = _SUNXI_CCU_MULT_MIN(8, 8, 12), + .m = _SUNXI_CCU_DIV(1, 1), + .common = { + .reg = 0x080, + .hw.init = CLK_HW_INIT_HWS("pll-audio1", dcxo24M_hws, + &ccu_nm_ops, + CLK_SET_RATE_UNGATE), + }, +}; + +static const struct clk_hw *pll_audio1_hws[] = { + &pll_audio1_clk.common.hw +}; +static SUNXI_CCU_M_HWS(pll_audio1_div2_clk, "pll-audio1-div2", + pll_audio1_hws, 0x080, 16, 3, 0); +static SUNXI_CCU_M_HWS(pll_audio1_div5_clk, "pll-audio1-div5", + pll_audio1_hws, 0x080, 20, 3, 0); + +/* + * The CPUX gate is not modelled - it is in a separate register (0x504) + * and has a special key field. The clock does not need to be ungated anyway. + */ +static const char * const cpux_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-cpux", + "pll-periph0", "pll-periph0-2x", + "pll-periph0-800M" }; +static SUNXI_CCU_MUX(cpux_clk, "cpux", cpux_parents, + 0x500, 24, 3, CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); + +static const struct clk_hw *cpux_hws[] = { &cpux_clk.common.hw }; +static SUNXI_CCU_M_HWS(cpux_axi_clk, "cpux-axi", + cpux_hws, 0x500, 0, 2, 0); +static SUNXI_CCU_M_HWS(cpux_apb_clk, "cpux-apb", + cpux_hws, 0x500, 8, 2, 0); + +static const char * const psi_ahb_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(psi_ahb_clk, "psi-ahb", + psi_ahb_parents, + 0x510, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const char * const apb0_apb1_parents[] = { "dcxo24M", "osc32k", + "psi-ahb", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX(apb0_clk, "apb0", apb0_apb1_parents, 0x520, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static SUNXI_CCU_MP_WITH_MUX(apb1_clk, "apb1", apb0_apb1_parents, 0x524, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + 0); + +static const struct clk_hw *psi_ahb_hws[] = { &psi_ahb_clk.common.hw }; +static const struct clk_hw *apb0_hws[] = { &apb0_clk.common.hw }; +static const struct clk_hw *apb1_hws[] = { &apb1_clk.common.hw }; + +static const char * const de_di_g2d_parents[] = { "pll-periph0-2x", "pll-video0-4x", + "pll-video1-4x", "pll-audio1-div2" }; +static SUNXI_CCU_M_WITH_MUX_GATE(de_clk, "de", de_di_g2d_parents, 0x600, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE_HWS(bus_de_clk, "bus-de", psi_ahb_hws, + 0x60c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(di_clk, "di", de_di_g2d_parents, 0x620, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE_HWS(bus_di_clk, "bus-di", psi_ahb_hws, + 0x62c, BIT(0), 0); + +static SUNXI_CCU_M_WITH_MUX_GATE(g2d_clk, "g2d", de_di_g2d_parents, 0x630, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_g2d_clk, "bus-g2d", psi_ahb_hws, + 0x63c, BIT(0), 0); + +static const char * const ce_parents[] = { "dcxo24M", "pll-periph0-2x", + "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ce_clk, "ce", ce_parents, 0x680, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_ce_clk, "bus-ce", psi_ahb_hws, + 0x68c, BIT(0), 0); + +static const char * const ve_parents[] = { "pll-ve", "pll-periph0-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(ve_clk, "ve", ve_parents, 0x690, + 0, 5, /* M */ + 24, 1, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE_HWS(bus_ve_clk, "bus-ve", psi_ahb_hws, + 0x69c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_dma_clk, "bus-dma", psi_ahb_hws, + 0x70c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_msgbox0_clk, "bus-msgbox0", psi_ahb_hws, + 0x71c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_msgbox1_clk, "bus-msgbox1", psi_ahb_hws, + 0x71c, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(bus_msgbox2_clk, "bus-msgbox2", psi_ahb_hws, + 0x71c, BIT(2), 0); + +static SUNXI_CCU_GATE_HWS(bus_spinlock_clk, "bus-spinlock", psi_ahb_hws, + 0x72c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_hstimer_clk, "bus-hstimer", psi_ahb_hws, + 0x73c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(avs_clk, "avs", dcxo24M_hws, + 0x740, BIT(31), 0); + +static SUNXI_CCU_GATE_HWS(bus_dbg_clk, "bus-dbg", psi_ahb_hws, + 0x78c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_pwm_clk, "bus-pwm", apb0_hws, + 0x7ac, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_iommu_clk, "bus-iommu", apb0_hws, + 0x7bc, BIT(0), 0); + +static const char * const dram_parents[] = { "pll-ddr0", "pll-audio1-div2", + "pll-periph0-2x", "pll-periph0-800M" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(dram_clk, "dram", dram_parents, 0x800, + 0, 2, /* M */ + 8, 2, /* P */ + 24, 2, /* mux */ + BIT(31), CLK_IS_CRITICAL); + +static CLK_FIXED_FACTOR_HW(mbus_clk, "mbus", + &dram_clk.common.hw, 4, 1, 0); + +static const struct clk_hw *mbus_hws[] = { &mbus_clk.hw }; + +static SUNXI_CCU_GATE_HWS(mbus_dma_clk, "mbus-dma", mbus_hws, + 0x804, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(mbus_ve_clk, "mbus-ve", mbus_hws, + 0x804, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(mbus_ce_clk, "mbus-ce", mbus_hws, + 0x804, BIT(2), 0); +static SUNXI_CCU_GATE_HWS(mbus_tvin_clk, "mbus-tvin", mbus_hws, + 0x804, BIT(7), 0); +static SUNXI_CCU_GATE_HWS(mbus_csi_clk, "mbus-csi", mbus_hws, + 0x804, BIT(8), 0); +static SUNXI_CCU_GATE_HWS(mbus_g2d_clk, "mbus-g2d", mbus_hws, + 0x804, BIT(10), 0); +static SUNXI_CCU_GATE_HWS(mbus_riscv_clk, "mbus-riscv", mbus_hws, + 0x804, BIT(11), 0); + +static SUNXI_CCU_GATE_HWS(bus_dram_clk, "bus-dram", psi_ahb_hws, + 0x80c, BIT(0), CLK_IS_CRITICAL); + +static const char * const mmc0_mmc1_parents[] = { "dcxo24M", "pll-periph0", + "pll-periph0-2x", "pll-audio1-div2" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc0_clk, "mmc0", mmc0_mmc1_parents, 0x830, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc1_clk, "mmc1", mmc0_mmc1_parents, 0x834, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const mmc2_parents[] = { "dcxo24M", "pll-periph0", + "pll-periph0-2x", "pll-periph0-800M", + "pll-audio1-div2" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(mmc2_clk, "mmc2", mmc2_parents, 0x838, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_mmc0_clk, "bus-mmc0", psi_ahb_hws, + 0x84c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_mmc1_clk, "bus-mmc1", psi_ahb_hws, + 0x84c, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(bus_mmc2_clk, "bus-mmc2", psi_ahb_hws, + 0x84c, BIT(2), 0); + +static SUNXI_CCU_GATE_HWS(bus_uart0_clk, "bus-uart0", apb1_hws, + 0x90c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_uart1_clk, "bus-uart1", apb1_hws, + 0x90c, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(bus_uart2_clk, "bus-uart2", apb1_hws, + 0x90c, BIT(2), 0); +static SUNXI_CCU_GATE_HWS(bus_uart3_clk, "bus-uart3", apb1_hws, + 0x90c, BIT(3), 0); +static SUNXI_CCU_GATE_HWS(bus_uart4_clk, "bus-uart4", apb1_hws, + 0x90c, BIT(4), 0); +static SUNXI_CCU_GATE_HWS(bus_uart5_clk, "bus-uart5", apb1_hws, + 0x90c, BIT(5), 0); + +static SUNXI_CCU_GATE_HWS(bus_i2c0_clk, "bus-i2c0", apb1_hws, + 0x91c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_i2c1_clk, "bus-i2c1", apb1_hws, + 0x91c, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(bus_i2c2_clk, "bus-i2c2", apb1_hws, + 0x91c, BIT(2), 0); +static SUNXI_CCU_GATE_HWS(bus_i2c3_clk, "bus-i2c3", apb1_hws, + 0x91c, BIT(3), 0); + +static const char * const spi_parents[] = { "dcxo24M", "pll-periph0", + "pll-periph0-2x", "pll-audio1-div2", + "pll-audio1-div5" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(spi0_clk, "spi0", spi_parents, 0x940, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spi1_clk, "spi1", spi_parents, 0x944, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_spi0_clk, "bus-spi0", psi_ahb_hws, + 0x96c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_spi1_clk, "bus-spi1", psi_ahb_hws, + 0x96c, BIT(1), 0); + +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(emac_25M_clk, "emac-25M", pll_periph0_hws, + 0x970, BIT(31) | BIT(30), 24, 0); + +static SUNXI_CCU_GATE_HWS(bus_emac_clk, "bus-emac", psi_ahb_hws, + 0x97c, BIT(0), 0); + +static const char * const ir_tx_parents[] = { "dcxo24M", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ir_tx_clk, "ir-tx", ir_tx_parents, 0x9c0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_ir_tx_clk, "bus-ir-tx", apb0_hws, + 0x9cc, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_gpadc_clk, "bus-gpadc", apb0_hws, + 0x9ec, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_ths_clk, "bus-ths", apb0_hws, + 0x9fc, BIT(0), 0); + +static const char * const i2s_spdif_tx_parents[] = { "pll-audio0", "pll-audio0-4x", + "pll-audio1-div2", "pll-audio1-div5" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s0_clk, "i2s0", i2s_spdif_tx_parents, 0xa10, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s1_clk, "i2s1", i2s_spdif_tx_parents, 0xa14, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s2_clk, "i2s2", i2s_spdif_tx_parents, 0xa18, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const i2s2_asrc_parents[] = { "pll-audio0-4x", "pll-periph0", + "pll-audio1-div2", "pll-audio1-div5" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(i2s2_asrc_clk, "i2s2-asrc", + i2s2_asrc_parents, 0xa1c, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_i2s0_clk, "bus-i2s0", apb0_hws, + 0xa20, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_i2s1_clk, "bus-i2s1", apb0_hws, + 0xa20, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(bus_i2s2_clk, "bus-i2s2", apb0_hws, + 0xa20, BIT(2), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_tx_clk, "spdif-tx", + i2s_spdif_tx_parents, 0xa24, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const spdif_rx_parents[] = { "pll-periph0", "pll-audio1-div2", + "pll-audio1-div5" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(spdif_rx_clk, "spdif-rx", + spdif_rx_parents, 0xa28, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_spdif_clk, "bus-spdif", apb0_hws, + 0xa2c, BIT(0), 0); + +static const char * const dmic_codec_parents[] = { "pll-audio0", "pll-audio1-div2", + "pll-audio1-div5" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(dmic_clk, "dmic", dmic_codec_parents, 0xa40, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_dmic_clk, "bus-dmic", apb0_hws, + 0xa4c, BIT(0), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(audio_dac_clk, "audio-dac", + dmic_codec_parents, 0xa50, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(audio_adc_clk, "audio-adc", + dmic_codec_parents, 0xa54, + 0, 5, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_audio_clk, "bus-audio", apb0_hws, + 0xa5c, BIT(0), 0); + +/* This is a 2x multiplier from dcxo24M synchronized by pll-periph0. */ +static CLK_FIXED_FACTOR_HWS(usb_48M_clk, "usb-48M", + pll_periph0_hws, 25, 2, 0); + +static CLK_FIXED_FACTOR_HW(usb_12M_clk, "usb-12M", + &usb_48M_clk.hw, 4, 1, 0); + +static const char * const usb_ohci_parents[] = { "usb-12M", "dcxo12M", + "osc32k" }; +static SUNXI_CCU_MUX_WITH_GATE(usb_ohci0_clk, "usb-ohci0", + usb_ohci_parents, 0xa70, + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_MUX_WITH_GATE(usb_ohci1_clk, "usb-ohci1", + usb_ohci_parents, 0xa74, + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_ohci0_clk, "bus-ohci0", psi_ahb_hws, + 0xa8c, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_ohci1_clk, "bus-ohci1", psi_ahb_hws, + 0xa8c, BIT(1), 0); +static SUNXI_CCU_GATE_HWS(bus_ehci0_clk, "bus-ehci0", psi_ahb_hws, + 0xa8c, BIT(4), 0); +static SUNXI_CCU_GATE_HWS(bus_ehci1_clk, "bus-ehci1", psi_ahb_hws, + 0xa8c, BIT(5), 0); +static SUNXI_CCU_GATE_HWS(bus_otg_clk, "bus-otg", psi_ahb_hws, + 0xa8c, BIT(8), 0); + +static SUNXI_CCU_GATE_HWS(bus_lradc_clk, "bus-lradc", apb0_hws, + 0xa9c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_dpss_top_clk, "bus-dpss-top", psi_ahb_hws, + 0xabc, BIT(0), 0); + +static SUNXI_CCU_GATE(hdmi_24M_clk, "hdmi-24M", "dcxo24M", + 0xb04, BIT(31), 0); + +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(hdmi_cec_32k_clk, "hdmi-cec-32k", + pll_periph0_2x_hws, + 0xb10, BIT(30), 36621, 0); + +static const char * const hdmi_cec_parents[] = { "osc32k", "hdmi-cec-32k" }; +static SUNXI_CCU_MUX_WITH_GATE(hdmi_cec_clk, "hdmi-cec", + hdmi_cec_parents, 0xb10, + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_hdmi_clk, "bus-hdmi", psi_ahb_hws, + 0xb1c, BIT(0), 0); + +static const char * const mipi_dsi_parents[] = { "dcxo24M", "pll-periph0", + "pll-video0-2x", "pll-video1-2x", + "pll-audio1-div2" }; +static SUNXI_CCU_M_WITH_MUX_GATE(mipi_dsi_clk, "mipi-dsi", + mipi_dsi_parents, + 0xb24, + 0, 4, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE_HWS(bus_mipi_dsi_clk, "bus-mipi-dsi", psi_ahb_hws, + 0xb4c, BIT(0), 0); + +static const char * const tcon_tve_parents[] = { "pll-video0", "pll-video0-4x", + "pll-video1", "pll-video1-4x", + "pll-periph0-2x", "pll-audio1-div2" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_lcd0_clk, "tcon-lcd0", + tcon_tve_parents, 0xb60, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE_HWS(bus_tcon_lcd0_clk, "bus-tcon-lcd0", psi_ahb_hws, + 0xb7c, BIT(0), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(tcon_tv_clk, "tcon-tv", + tcon_tve_parents, 0xb80, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + CLK_SET_RATE_PARENT); + +static SUNXI_CCU_GATE_HWS(bus_tcon_tv_clk, "bus-tcon-tv", psi_ahb_hws, + 0xb9c, BIT(0), 0); + +static SUNXI_CCU_MP_WITH_MUX_GATE(tve_clk, "tve", tcon_tve_parents, 0xbb0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_tve_top_clk, "bus-tve-top", psi_ahb_hws, + 0xbbc, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_tve_clk, "bus-tve", psi_ahb_hws, + 0xbbc, BIT(1), 0); + +static const char * const tvd_parents[] = { "dcxo24M", "pll-video0", + "pll-video1", "pll-periph0" }; +static SUNXI_CCU_M_WITH_MUX_GATE(tvd_clk, "tvd", tvd_parents, 0xbc0, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_tvd_top_clk, "bus-tvd-top", psi_ahb_hws, + 0xbdc, BIT(0), 0); +static SUNXI_CCU_GATE_HWS(bus_tvd_clk, "bus-tvd", psi_ahb_hws, + 0xbdc, BIT(1), 0); + +static const char * const ledc_parents[] = { "dcxo24M", "pll-periph0" }; +static SUNXI_CCU_MP_WITH_MUX_GATE(ledc_clk, "ledc", ledc_parents, 0xbf0, + 0, 4, /* M */ + 8, 2, /* P */ + 24, 1, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_ledc_clk, "bus-ledc", psi_ahb_hws, + 0xbfc, BIT(0), 0); + +static const char * const csi_top_parents[] = { "pll-periph0-2x", "pll-video0-2x", + "pll-video1-2x" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_top_clk, "csi-top", + csi_top_parents, 0xc04, + 0, 4, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static const char * const csi_mclk_parents[] = { "dcxo24M", "pll-periph0", + "pll-video0", "pll-video1", + "pll-audio1-div2", "pll-audio1-div5" }; +static SUNXI_CCU_M_WITH_MUX_GATE(csi_mclk_clk, "csi-mclk", + csi_mclk_parents, 0xc08, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_csi_clk, "bus-csi", psi_ahb_hws, + 0xc1c, BIT(0), 0); + +static const char * const tpadc_parents[] = { "dcxo24M", "pll-audio0" }; +static SUNXI_CCU_MUX_WITH_GATE(tpadc_clk, "tpadc", tpadc_parents, 0xc50, + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_tpadc_clk, "bus-tpadc", apb0_hws, + 0xc5c, BIT(0), 0); + +static SUNXI_CCU_GATE_HWS(bus_tzma_clk, "bus-tzma", apb0_hws, + 0xc6c, BIT(0), 0); + +static const char * const dsp_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-periph0-2x", + "pll-audio1-div2" }; +static SUNXI_CCU_M_WITH_MUX_GATE(dsp_clk, "dsp", dsp_parents, 0xc70, + 0, 5, /* M */ + 24, 3, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_GATE_HWS(bus_dsp_cfg_clk, "bus-dsp-cfg", psi_ahb_hws, + 0xc7c, BIT(1), 0); + +/* + * The RISC-V gate is not modelled - it is in a separate register (0xd04) + * and has a special key field. The clock cannot be gated anyway. + */ +static const char * const riscv_parents[] = { "dcxo24M", "osc32k", + "iosc", "pll-periph0-800M", + "pll-periph0", "pll-cpux", + "pll-audio1-div2" }; +static SUNXI_CCU_M_WITH_MUX(riscv_clk, "riscv", riscv_parents, 0xd00, + 0, 5, /* M */ + 24, 3, /* mux */ + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL); + +/* The riscv-axi clk must be divided by at least 2. */ +static struct clk_div_table riscv_axi_table[] = { + { .val = 1, .div = 2 }, + { .val = 2, .div = 3 }, + { .val = 3, .div = 4 }, + { /* Sentinel */ } +}; +static SUNXI_CCU_DIV_TABLE(riscv_axi_clk, "riscv-axi", + "riscv", 0xd00, 8, 2, riscv_axi_table, 0); + +static SUNXI_CCU_GATE_HWS(bus_riscv_cfg_clk, "bus-riscv-cfg", psi_ahb_hws, + 0xd0c, BIT(0), CLK_IS_CRITICAL); + +static SUNXI_CCU_GATE_HWS(fanout_24M_clk, "fanout-24M", + dcxo24M_hws, 0xf30, BIT(0), 0); +static SUNXI_CCU_GATE_HW (fanout_12M_clk, "fanout-12M", + &dcxo12M.hw, 0xf30, BIT(1), 0); +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_16M_clk, "fanout-16M", + pll_periph0_2x_hws, + 0xf30, BIT(2), 75, 0); +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_25M_clk, "fanout-25M", + pll_periph0_hws, + 0xf30, BIT(3), 24, 0); +static SUNXI_CCU_GATE_HWS_WITH_PREDIV(fanout_32k_clk, "fanout-32k", + pll_periph0_2x_hws, + 0xf30, BIT(4), 36621, 0); + +/* This clock has a second divider that is not modelled and forced to 0. */ +#define SUN20I_D1_FANOUT_27M_REG 0xf34 +static const char * const fanout_27M_parents[] = { "pll-video0", "pll-video1" }; +static SUNXI_CCU_M_WITH_MUX_GATE(fanout_27M_clk, "fanout-27M", + fanout_27M_parents, 0xf34, + 0, 5, /* M */ + 24, 2, /* mux */ + BIT(31), /* gate */ + 0); + +static SUNXI_CCU_M_HWS_WITH_GATE(fanout_pclk, "fanout-pclk", + apb0_hws, 0xf38, + 0, 5, /* M */ + BIT(31), /* gate */ + 0); + +static const char * const fanout_parents[] = { "fanout-32k", "fanout-12M", + "fanout-16M", "fanout-24M", + "fanout-25M", "fanout-27M", + "fanout-pclk" }; +static SUNXI_CCU_MUX_WITH_GATE(fanout0_clk, "fanout0", + fanout_parents, 0xf3c, + 0, 3, /* mux */ + BIT(21), /* gate */ + 0); +static SUNXI_CCU_MUX_WITH_GATE(fanout1_clk, "fanout1", + fanout_parents, 0xf3c, + 3, 3, /* mux */ + BIT(22), /* gate */ + 0); +static SUNXI_CCU_MUX_WITH_GATE(fanout2_clk, "fanout2", + fanout_parents, 0xf3c, + 6, 3, /* mux */ + BIT(23), /* gate */ + 0); + +static struct ccu_common *sun20i_d1_ccu_clks[] = { + &pll_cpux_clk.common, + &pll_ddr0_clk.common, + &pll_periph0_4x_clk.common, + &pll_periph0_2x_clk.common, + &pll_periph0_800M_clk.common, + &pll_video0_4x_clk.common, + &pll_video1_4x_clk.common, + &pll_ve_clk.common, + &pll_audio0_4x_clk.common, + &pll_audio1_clk.common, + &pll_audio1_div2_clk.common, + &pll_audio1_div5_clk.common, + &cpux_clk.common, + &cpux_axi_clk.common, + &cpux_apb_clk.common, + &psi_ahb_clk.common, + &apb0_clk.common, + &apb1_clk.common, + &de_clk.common, + &bus_de_clk.common, + &di_clk.common, + &bus_di_clk.common, + &g2d_clk.common, + &bus_g2d_clk.common, + &ce_clk.common, + &bus_ce_clk.common, + &ve_clk.common, + &bus_ve_clk.common, + &bus_dma_clk.common, + &bus_msgbox0_clk.common, + &bus_msgbox1_clk.common, + &bus_msgbox2_clk.common, + &bus_spinlock_clk.common, + &bus_hstimer_clk.common, + &avs_clk.common, + &bus_dbg_clk.common, + &bus_pwm_clk.common, + &bus_iommu_clk.common, + &dram_clk.common, + &mbus_dma_clk.common, + &mbus_ve_clk.common, + &mbus_ce_clk.common, + &mbus_tvin_clk.common, + &mbus_csi_clk.common, + &mbus_g2d_clk.common, + &mbus_riscv_clk.common, + &bus_dram_clk.common, + &mmc0_clk.common, + &mmc1_clk.common, + &mmc2_clk.common, + &bus_mmc0_clk.common, + &bus_mmc1_clk.common, + &bus_mmc2_clk.common, + &bus_uart0_clk.common, + &bus_uart1_clk.common, + &bus_uart2_clk.common, + &bus_uart3_clk.common, + &bus_uart4_clk.common, + &bus_uart5_clk.common, + &bus_i2c0_clk.common, + &bus_i2c1_clk.common, + &bus_i2c2_clk.common, + &bus_i2c3_clk.common, + &spi0_clk.common, + &spi1_clk.common, + &bus_spi0_clk.common, + &bus_spi1_clk.common, + &emac_25M_clk.common, + &bus_emac_clk.common, + &ir_tx_clk.common, + &bus_ir_tx_clk.common, + &bus_gpadc_clk.common, + &bus_ths_clk.common, + &i2s0_clk.common, + &i2s1_clk.common, + &i2s2_clk.common, + &i2s2_asrc_clk.common, + &bus_i2s0_clk.common, + &bus_i2s1_clk.common, + &bus_i2s2_clk.common, + &spdif_tx_clk.common, + &spdif_rx_clk.common, + &bus_spdif_clk.common, + &dmic_clk.common, + &bus_dmic_clk.common, + &audio_dac_clk.common, + &audio_adc_clk.common, + &bus_audio_clk.common, + &usb_ohci0_clk.common, + &usb_ohci1_clk.common, + &bus_ohci0_clk.common, + &bus_ohci1_clk.common, + &bus_ehci0_clk.common, + &bus_ehci1_clk.common, + &bus_otg_clk.common, + &bus_lradc_clk.common, + &bus_dpss_top_clk.common, + &hdmi_24M_clk.common, + &hdmi_cec_32k_clk.common, + &hdmi_cec_clk.common, + &bus_hdmi_clk.common, + &mipi_dsi_clk.common, + &bus_mipi_dsi_clk.common, + &tcon_lcd0_clk.common, + &bus_tcon_lcd0_clk.common, + &tcon_tv_clk.common, + &bus_tcon_tv_clk.common, + &tve_clk.common, + &bus_tve_top_clk.common, + &bus_tve_clk.common, + &tvd_clk.common, + &bus_tvd_top_clk.common, + &bus_tvd_clk.common, + &ledc_clk.common, + &bus_ledc_clk.common, + &csi_top_clk.common, + &csi_mclk_clk.common, + &bus_csi_clk.common, + &tpadc_clk.common, + &bus_tpadc_clk.common, + &bus_tzma_clk.common, + &dsp_clk.common, + &bus_dsp_cfg_clk.common, + &riscv_clk.common, + &riscv_axi_clk.common, + &bus_riscv_cfg_clk.common, + &fanout_24M_clk.common, + &fanout_12M_clk.common, + &fanout_16M_clk.common, + &fanout_25M_clk.common, + &fanout_32k_clk.common, + &fanout_27M_clk.common, + &fanout_pclk.common, + &fanout0_clk.common, + &fanout1_clk.common, + &fanout2_clk.common, +}; + +static struct clk_hw_onecell_data sun20i_d1_hw_clks = { + .num = CLK_NUMBER, + .hws = { + [CLK_DCXO12M] = &dcxo12M.hw, + [CLK_PLL_CPUX] = &pll_cpux_clk.common.hw, + [CLK_PLL_DDR0] = &pll_ddr0_clk.common.hw, + [CLK_PLL_PERIPH0_4X] = &pll_periph0_4x_clk.common.hw, + [CLK_PLL_PERIPH0_2X] = &pll_periph0_2x_clk.common.hw, + [CLK_PLL_PERIPH0_800M] = &pll_periph0_800M_clk.common.hw, + [CLK_PLL_PERIPH0] = &pll_periph0_clk.hw, + [CLK_PLL_PERIPH0_DIV3] = &pll_periph0_div3_clk.hw, + [CLK_PLL_VIDEO0_4X] = &pll_video0_4x_clk.common.hw, + [CLK_PLL_VIDEO0_2X] = &pll_video0_2x_clk.hw, + [CLK_PLL_VIDEO0] = &pll_video0_clk.hw, + [CLK_PLL_VIDEO1_4X] = &pll_video1_4x_clk.common.hw, + [CLK_PLL_VIDEO1_2X] = &pll_video1_2x_clk.hw, + [CLK_PLL_VIDEO1] = &pll_video1_clk.hw, + [CLK_PLL_VE] = &pll_ve_clk.common.hw, + [CLK_PLL_AUDIO0_4X] = &pll_audio0_4x_clk.common.hw, + [CLK_PLL_AUDIO0_2X] = &pll_audio0_2x_clk.hw, + [CLK_PLL_AUDIO0] = &pll_audio0_clk.hw, + [CLK_PLL_AUDIO1] = &pll_audio1_clk.common.hw, + [CLK_PLL_AUDIO1_DIV2] = &pll_audio1_div2_clk.common.hw, + [CLK_PLL_AUDIO1_DIV5] = &pll_audio1_div5_clk.common.hw, + [CLK_CPUX] = &cpux_clk.common.hw, + [CLK_CPUX_AXI] = &cpux_axi_clk.common.hw, + [CLK_CPUX_APB] = &cpux_apb_clk.common.hw, + [CLK_PSI_AHB] = &psi_ahb_clk.common.hw, + [CLK_APB0] = &apb0_clk.common.hw, + [CLK_APB1] = &apb1_clk.common.hw, + [CLK_MBUS] = &mbus_clk.hw, + [CLK_DE] = &de_clk.common.hw, + [CLK_BUS_DE] = &bus_de_clk.common.hw, + [CLK_DI] = &di_clk.common.hw, + [CLK_BUS_DI] = &bus_di_clk.common.hw, + [CLK_G2D] = &g2d_clk.common.hw, + [CLK_BUS_G2D] = &bus_g2d_clk.common.hw, + [CLK_CE] = &ce_clk.common.hw, + [CLK_BUS_CE] = &bus_ce_clk.common.hw, + [CLK_VE] = &ve_clk.common.hw, + [CLK_BUS_VE] = &bus_ve_clk.common.hw, + [CLK_BUS_DMA] = &bus_dma_clk.common.hw, + [CLK_BUS_MSGBOX0] = &bus_msgbox0_clk.common.hw, + [CLK_BUS_MSGBOX1] = &bus_msgbox1_clk.common.hw, + [CLK_BUS_MSGBOX2] = &bus_msgbox2_clk.common.hw, + [CLK_BUS_SPINLOCK] = &bus_spinlock_clk.common.hw, + [CLK_BUS_HSTIMER] = &bus_hstimer_clk.common.hw, + [CLK_AVS] = &avs_clk.common.hw, + [CLK_BUS_DBG] = &bus_dbg_clk.common.hw, + [CLK_BUS_PWM] = &bus_pwm_clk.common.hw, + [CLK_BUS_IOMMU] = &bus_iommu_clk.common.hw, + [CLK_DRAM] = &dram_clk.common.hw, + [CLK_MBUS_DMA] = &mbus_dma_clk.common.hw, + [CLK_MBUS_VE] = &mbus_ve_clk.common.hw, + [CLK_MBUS_CE] = &mbus_ce_clk.common.hw, + [CLK_MBUS_TVIN] = &mbus_tvin_clk.common.hw, + [CLK_MBUS_CSI] = &mbus_csi_clk.common.hw, + [CLK_MBUS_G2D] = &mbus_g2d_clk.common.hw, + [CLK_MBUS_RISCV] = &mbus_riscv_clk.common.hw, + [CLK_BUS_DRAM] = &bus_dram_clk.common.hw, + [CLK_MMC0] = &mmc0_clk.common.hw, + [CLK_MMC1] = &mmc1_clk.common.hw, + [CLK_MMC2] = &mmc2_clk.common.hw, + [CLK_BUS_MMC0] = &bus_mmc0_clk.common.hw, + [CLK_BUS_MMC1] = &bus_mmc1_clk.common.hw, + [CLK_BUS_MMC2] = &bus_mmc2_clk.common.hw, + [CLK_BUS_UART0] = &bus_uart0_clk.common.hw, + [CLK_BUS_UART1] = &bus_uart1_clk.common.hw, + [CLK_BUS_UART2] = &bus_uart2_clk.common.hw, + [CLK_BUS_UART3] = &bus_uart3_clk.common.hw, + [CLK_BUS_UART4] = &bus_uart4_clk.common.hw, + [CLK_BUS_UART5] = &bus_uart5_clk.common.hw, + [CLK_BUS_I2C0] = &bus_i2c0_clk.common.hw, + [CLK_BUS_I2C1] = &bus_i2c1_clk.common.hw, + [CLK_BUS_I2C2] = &bus_i2c2_clk.common.hw, + [CLK_BUS_I2C3] = &bus_i2c3_clk.common.hw, + [CLK_SPI0] = &spi0_clk.common.hw, + [CLK_SPI1] = &spi1_clk.common.hw, + [CLK_BUS_SPI0] = &bus_spi0_clk.common.hw, + [CLK_BUS_SPI1] = &bus_spi1_clk.common.hw, + [CLK_EMAC_25M] = &emac_25M_clk.common.hw, + [CLK_BUS_EMAC] = &bus_emac_clk.common.hw, + [CLK_IR_TX] = &ir_tx_clk.common.hw, + [CLK_BUS_IR_TX] = &bus_ir_tx_clk.common.hw, + [CLK_BUS_GPADC] = &bus_gpadc_clk.common.hw, + [CLK_BUS_THS] = &bus_ths_clk.common.hw, + [CLK_I2S0] = &i2s0_clk.common.hw, + [CLK_I2S1] = &i2s1_clk.common.hw, + [CLK_I2S2] = &i2s2_clk.common.hw, + [CLK_I2S2_ASRC] = &i2s2_asrc_clk.common.hw, + [CLK_BUS_I2S0] = &bus_i2s0_clk.common.hw, + [CLK_BUS_I2S1] = &bus_i2s1_clk.common.hw, + [CLK_BUS_I2S2] = &bus_i2s2_clk.common.hw, + [CLK_SPDIF_TX] = &spdif_tx_clk.common.hw, + [CLK_SPDIF_RX] = &spdif_rx_clk.common.hw, + [CLK_BUS_SPDIF] = &bus_spdif_clk.common.hw, + [CLK_DMIC] = &dmic_clk.common.hw, + [CLK_BUS_DMIC] = &bus_dmic_clk.common.hw, + [CLK_AUDIO_DAC] = &audio_dac_clk.common.hw, + [CLK_AUDIO_ADC] = &audio_adc_clk.common.hw, + [CLK_BUS_AUDIO] = &bus_audio_clk.common.hw, + [CLK_USB_48M] = &usb_48M_clk.hw, + [CLK_USB_12M] = &usb_12M_clk.hw, + [CLK_USB_OHCI0] = &usb_ohci0_clk.common.hw, + [CLK_USB_OHCI1] = &usb_ohci1_clk.common.hw, + [CLK_BUS_OHCI0] = &bus_ohci0_clk.common.hw, + [CLK_BUS_OHCI1] = &bus_ohci1_clk.common.hw, + [CLK_BUS_EHCI0] = &bus_ehci0_clk.common.hw, + [CLK_BUS_EHCI1] = &bus_ehci1_clk.common.hw, + [CLK_BUS_OTG] = &bus_otg_clk.common.hw, + [CLK_BUS_LRADC] = &bus_lradc_clk.common.hw, + [CLK_BUS_DPSS_TOP] = &bus_dpss_top_clk.common.hw, + [CLK_HDMI_24M] = &hdmi_24M_clk.common.hw, + [CLK_HDMI_CEC_32K] = &hdmi_cec_32k_clk.common.hw, + [CLK_HDMI_CEC] = &hdmi_cec_clk.common.hw, + [CLK_BUS_HDMI] = &bus_hdmi_clk.common.hw, + [CLK_MIPI_DSI] = &mipi_dsi_clk.common.hw, + [CLK_BUS_MIPI_DSI] = &bus_mipi_dsi_clk.common.hw, + [CLK_TCON_LCD0] = &tcon_lcd0_clk.common.hw, + [CLK_BUS_TCON_LCD0] = &bus_tcon_lcd0_clk.common.hw, + [CLK_TCON_TV] = &tcon_tv_clk.common.hw, + [CLK_BUS_TCON_TV] = &bus_tcon_tv_clk.common.hw, + [CLK_TVE] = &tve_clk.common.hw, + [CLK_BUS_TVE_TOP] = &bus_tve_top_clk.common.hw, + [CLK_BUS_TVE] = &bus_tve_clk.common.hw, + [CLK_TVD] = &tvd_clk.common.hw, + [CLK_BUS_TVD_TOP] = &bus_tvd_top_clk.common.hw, + [CLK_BUS_TVD] = &bus_tvd_clk.common.hw, + [CLK_LEDC] = &ledc_clk.common.hw, + [CLK_BUS_LEDC] = &bus_ledc_clk.common.hw, + [CLK_CSI_TOP] = &csi_top_clk.common.hw, + [CLK_CSI_MCLK] = &csi_mclk_clk.common.hw, + [CLK_BUS_CSI] = &bus_csi_clk.common.hw, + [CLK_TPADC] = &tpadc_clk.common.hw, + [CLK_BUS_TPADC] = &bus_tpadc_clk.common.hw, + [CLK_BUS_TZMA] = &bus_tzma_clk.common.hw, + [CLK_DSP] = &dsp_clk.common.hw, + [CLK_BUS_DSP_CFG] = &bus_dsp_cfg_clk.common.hw, + [CLK_RISCV] = &riscv_clk.common.hw, + [CLK_RISCV_AXI] = &riscv_axi_clk.common.hw, + [CLK_BUS_RISCV_CFG] = &bus_riscv_cfg_clk.common.hw, + [CLK_FANOUT_24M] = &fanout_24M_clk.common.hw, + [CLK_FANOUT_12M] = &fanout_12M_clk.common.hw, + [CLK_FANOUT_16M] = &fanout_16M_clk.common.hw, + [CLK_FANOUT_25M] = &fanout_25M_clk.common.hw, + [CLK_FANOUT_32K] = &fanout_32k_clk.common.hw, + [CLK_FANOUT_27M] = &fanout_27M_clk.common.hw, + [CLK_FANOUT_PCLK] = &fanout_pclk.common.hw, + [CLK_FANOUT0] = &fanout0_clk.common.hw, + [CLK_FANOUT1] = &fanout1_clk.common.hw, + [CLK_FANOUT2] = &fanout2_clk.common.hw, + }, +}; + +static struct ccu_reset_map sun20i_d1_ccu_resets[] = { + [RST_MBUS] = { 0x540, BIT(30) }, + [RST_BUS_DE] = { 0x60c, BIT(16) }, + [RST_BUS_DI] = { 0x62c, BIT(16) }, + [RST_BUS_G2D] = { 0x63c, BIT(16) }, + [RST_BUS_CE] = { 0x68c, BIT(16) }, + [RST_BUS_VE] = { 0x69c, BIT(16) }, + [RST_BUS_DMA] = { 0x70c, BIT(16) }, + [RST_BUS_MSGBOX0] = { 0x71c, BIT(16) }, + [RST_BUS_MSGBOX1] = { 0x71c, BIT(17) }, + [RST_BUS_MSGBOX2] = { 0x71c, BIT(18) }, + [RST_BUS_SPINLOCK] = { 0x72c, BIT(16) }, + [RST_BUS_HSTIMER] = { 0x73c, BIT(16) }, + [RST_BUS_DBG] = { 0x78c, BIT(16) }, + [RST_BUS_PWM] = { 0x7ac, BIT(16) }, + [RST_BUS_DRAM] = { 0x80c, BIT(16) }, + [RST_BUS_MMC0] = { 0x84c, BIT(16) }, + [RST_BUS_MMC1] = { 0x84c, BIT(17) }, + [RST_BUS_MMC2] = { 0x84c, BIT(18) }, + [RST_BUS_UART0] = { 0x90c, BIT(16) }, + [RST_BUS_UART1] = { 0x90c, BIT(17) }, + [RST_BUS_UART2] = { 0x90c, BIT(18) }, + [RST_BUS_UART3] = { 0x90c, BIT(19) }, + [RST_BUS_UART4] = { 0x90c, BIT(20) }, + [RST_BUS_UART5] = { 0x90c, BIT(21) }, + [RST_BUS_I2C0] = { 0x91c, BIT(16) }, + [RST_BUS_I2C1] = { 0x91c, BIT(17) }, + [RST_BUS_I2C2] = { 0x91c, BIT(18) }, + [RST_BUS_I2C3] = { 0x91c, BIT(19) }, + [RST_BUS_SPI0] = { 0x96c, BIT(16) }, + [RST_BUS_SPI1] = { 0x96c, BIT(17) }, + [RST_BUS_EMAC] = { 0x97c, BIT(16) }, + [RST_BUS_IR_TX] = { 0x9cc, BIT(16) }, + [RST_BUS_GPADC] = { 0x9ec, BIT(16) }, + [RST_BUS_THS] = { 0x9fc, BIT(16) }, + [RST_BUS_I2S0] = { 0xa20, BIT(16) }, + [RST_BUS_I2S1] = { 0xa20, BIT(17) }, + [RST_BUS_I2S2] = { 0xa20, BIT(18) }, + [RST_BUS_SPDIF] = { 0xa2c, BIT(16) }, + [RST_BUS_DMIC] = { 0xa4c, BIT(16) }, + [RST_BUS_AUDIO] = { 0xa5c, BIT(16) }, + [RST_USB_PHY0] = { 0xa70, BIT(30) }, + [RST_USB_PHY1] = { 0xa74, BIT(30) }, + [RST_BUS_OHCI0] = { 0xa8c, BIT(16) }, + [RST_BUS_OHCI1] = { 0xa8c, BIT(17) }, + [RST_BUS_EHCI0] = { 0xa8c, BIT(20) }, + [RST_BUS_EHCI1] = { 0xa8c, BIT(21) }, + [RST_BUS_OTG] = { 0xa8c, BIT(24) }, + [RST_BUS_LRADC] = { 0xa9c, BIT(16) }, + [RST_BUS_DPSS_TOP] = { 0xabc, BIT(16) }, + [RST_BUS_HDMI_MAIN] = { 0xb1c, BIT(16) }, + [RST_BUS_HDMI_SUB] = { 0xb1c, BIT(17) }, + [RST_BUS_MIPI_DSI] = { 0xb4c, BIT(16) }, + [RST_BUS_TCON_LCD0] = { 0xb7c, BIT(16) }, + [RST_BUS_TCON_TV] = { 0xb9c, BIT(16) }, + [RST_BUS_LVDS0] = { 0xbac, BIT(16) }, + [RST_BUS_TVE_TOP] = { 0xbbc, BIT(16) }, + [RST_BUS_TVE] = { 0xbbc, BIT(17) }, + [RST_BUS_TVD_TOP] = { 0xbdc, BIT(16) }, + [RST_BUS_TVD] = { 0xbdc, BIT(17) }, + [RST_BUS_LEDC] = { 0xbfc, BIT(16) }, + [RST_BUS_CSI] = { 0xc1c, BIT(16) }, + [RST_BUS_TPADC] = { 0xc5c, BIT(16) }, + [RST_DSP] = { 0xc7c, BIT(16) }, + [RST_BUS_DSP_CFG] = { 0xc7c, BIT(17) }, + [RST_BUS_DSP_DBG] = { 0xc7c, BIT(18) }, + [RST_BUS_RISCV_CFG] = { 0xd0c, BIT(16) }, +}; + +static const struct sunxi_ccu_desc sun20i_d1_ccu_desc = { + .ccu_clks = sun20i_d1_ccu_clks, + .num_ccu_clks = ARRAY_SIZE(sun20i_d1_ccu_clks), + + .hw_clks = &sun20i_d1_hw_clks, + + .resets = sun20i_d1_ccu_resets, + .num_resets = ARRAY_SIZE(sun20i_d1_ccu_resets), +}; + +static const u32 pll_regs[] = { + SUN20I_D1_PLL_CPUX_REG, + SUN20I_D1_PLL_DDR0_REG, + SUN20I_D1_PLL_PERIPH0_REG, + SUN20I_D1_PLL_VIDEO0_REG, + SUN20I_D1_PLL_VIDEO1_REG, + SUN20I_D1_PLL_VE_REG, + SUN20I_D1_PLL_AUDIO0_REG, + SUN20I_D1_PLL_AUDIO1_REG, +}; + +static const u32 pll_video_regs[] = { + SUN20I_D1_PLL_VIDEO0_REG, + SUN20I_D1_PLL_VIDEO1_REG, +}; + +static struct ccu_mux_nb sun20i_d1_riscv_nb = { + .common = &riscv_clk.common, + .cm = &riscv_clk.mux, + .delay_us = 1, + .bypass_index = 4, /* index of pll-periph0 */ +}; + +static int sun20i_d1_ccu_probe(struct platform_device *pdev) +{ + void __iomem *reg; + u32 val; + int i, ret; + + reg = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + *dcxo24M_hws = of_clk_get_hw(pdev->dev.of_node, 0, NULL); + + /* Enable the enable, LDO, and lock bits on all PLLs. */ + for (i = 0; i < ARRAY_SIZE(pll_regs); i++) { + val = readl(reg + pll_regs[i]); + val |= BIT(31) | BIT(30) | BIT(29); + writel(val, reg + pll_regs[i]); + } + + /* Force PLL_CPUX factor M to 0. */ + val = readl(reg + SUN20I_D1_PLL_CPUX_REG); + val &= ~GENMASK(1, 0); + writel(val, reg + SUN20I_D1_PLL_CPUX_REG); + + /* + * Force the output divider of video PLLs to 0. + * + * See the comment before pll-video0 definition for the reason. + */ + for (i = 0; i < ARRAY_SIZE(pll_video_regs); i++) { + val = readl(reg + pll_video_regs[i]); + val &= ~BIT(0); + writel(val, reg + pll_video_regs[i]); + } + + /* Enforce m1 = 0, m0 = 0 for PLL_AUDIO0 */ + val = readl(reg + SUN20I_D1_PLL_AUDIO0_REG); + val &= ~BIT(1) | BIT(0); + writel(val, reg + SUN20I_D1_PLL_AUDIO0_REG); + + /* Force fanout-27M factor N to 0. */ + val = readl(reg + SUN20I_D1_FANOUT_27M_REG); + val &= ~GENMASK(9, 8); + writel(val, reg + SUN20I_D1_FANOUT_27M_REG); + + ret = sunxi_ccu_probe(pdev->dev.of_node, reg, &sun20i_d1_ccu_desc); + if (ret) + return ret; + + /* Reparent CPU during PLL CPUX rate changes */ + ccu_mux_notifier_register(pll_cpux_clk.common.hw.clk, + &sun20i_d1_riscv_nb); + + return 0; +} + +static const struct of_device_id sun20i_d1_ccu_ids[] = { + { .compatible = "allwinner,sun20i-d1-ccu" }, + { } +}; + +static struct platform_driver sun20i_d1_ccu_driver = { + .probe = sun20i_d1_ccu_probe, + .driver = { + .name = "sun20i-d1-ccu", + .of_match_table = sun20i_d1_ccu_ids, + .suppress_bind_attrs = true, + }, +}; +builtin_platform_driver(sun20i_d1_ccu_driver); diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.h b/drivers/clk/sunxi-ng/ccu-sun20i-d1.h new file mode 100644 index 00000000000000..e303176f0d4e9e --- /dev/null +++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.h @@ -0,0 +1,15 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 frank@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#ifndef _CCU_SUN20I_D1_H_ +#define _CCU_SUN20I_D1_H_ + +#include +#include + +#define CLK_NUMBER (CLK_FANOUT2 + 1) + +#endif /* _CCU_SUN20I_D1_H_ */ diff --git a/include/dt-bindings/clock/sun20i-d1-ccu.h b/include/dt-bindings/clock/sun20i-d1-ccu.h new file mode 100644 index 00000000000000..dd08c8d9e6ba8f --- /dev/null +++ b/include/dt-bindings/clock/sun20i-d1-ccu.h @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +/* + * Copyright (C) 2020 huangzhenwei@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#ifndef _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ +#define _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ + +#define CLK_DCXO12M 0 +#define CLK_PLL_CPUX 1 +#define CLK_PLL_DDR0 2 +#define CLK_PLL_PERIPH0_4X 3 +#define CLK_PLL_PERIPH0_2X 4 +#define CLK_PLL_PERIPH0_800M 5 +#define CLK_PLL_PERIPH0 6 +#define CLK_PLL_PERIPH0_DIV3 7 +#define CLK_PLL_VIDEO0_4X 8 +#define CLK_PLL_VIDEO0_2X 9 +#define CLK_PLL_VIDEO0 10 +#define CLK_PLL_VIDEO1_4X 11 +#define CLK_PLL_VIDEO1_2X 12 +#define CLK_PLL_VIDEO1 13 +#define CLK_PLL_VE 14 +#define CLK_PLL_AUDIO0_4X 15 +#define CLK_PLL_AUDIO0_2X 16 +#define CLK_PLL_AUDIO0 17 +#define CLK_PLL_AUDIO1 18 +#define CLK_PLL_AUDIO1_DIV2 19 +#define CLK_PLL_AUDIO1_DIV5 20 +#define CLK_CPUX 21 +#define CLK_CPUX_AXI 22 +#define CLK_CPUX_APB 23 +#define CLK_PSI_AHB 24 +#define CLK_APB0 25 +#define CLK_APB1 26 +#define CLK_MBUS 27 +#define CLK_DE 28 +#define CLK_BUS_DE 29 +#define CLK_DI 30 +#define CLK_BUS_DI 31 +#define CLK_G2D 32 +#define CLK_BUS_G2D 33 +#define CLK_CE 34 +#define CLK_BUS_CE 35 +#define CLK_VE 36 +#define CLK_BUS_VE 37 +#define CLK_BUS_DMA 38 +#define CLK_BUS_MSGBOX0 39 +#define CLK_BUS_MSGBOX1 40 +#define CLK_BUS_MSGBOX2 41 +#define CLK_BUS_SPINLOCK 42 +#define CLK_BUS_HSTIMER 43 +#define CLK_AVS 44 +#define CLK_BUS_DBG 45 +#define CLK_BUS_PWM 46 +#define CLK_BUS_IOMMU 47 +#define CLK_DRAM 48 +#define CLK_MBUS_DMA 49 +#define CLK_MBUS_VE 50 +#define CLK_MBUS_CE 51 +#define CLK_MBUS_TVIN 52 +#define CLK_MBUS_CSI 53 +#define CLK_MBUS_G2D 54 +#define CLK_MBUS_RISCV 55 +#define CLK_BUS_DRAM 56 +#define CLK_MMC0 57 +#define CLK_MMC1 58 +#define CLK_MMC2 59 +#define CLK_BUS_MMC0 60 +#define CLK_BUS_MMC1 61 +#define CLK_BUS_MMC2 62 +#define CLK_BUS_UART0 63 +#define CLK_BUS_UART1 64 +#define CLK_BUS_UART2 65 +#define CLK_BUS_UART3 66 +#define CLK_BUS_UART4 67 +#define CLK_BUS_UART5 68 +#define CLK_BUS_I2C0 69 +#define CLK_BUS_I2C1 70 +#define CLK_BUS_I2C2 71 +#define CLK_BUS_I2C3 72 +#define CLK_SPI0 73 +#define CLK_SPI1 74 +#define CLK_BUS_SPI0 75 +#define CLK_BUS_SPI1 76 +#define CLK_EMAC_25M 77 +#define CLK_BUS_EMAC 78 +#define CLK_IR_TX 79 +#define CLK_BUS_IR_TX 80 +#define CLK_BUS_GPADC 81 +#define CLK_BUS_THS 82 +#define CLK_I2S0 83 +#define CLK_I2S1 84 +#define CLK_I2S2 85 +#define CLK_I2S2_ASRC 86 +#define CLK_BUS_I2S0 87 +#define CLK_BUS_I2S1 88 +#define CLK_BUS_I2S2 89 +#define CLK_SPDIF_TX 90 +#define CLK_SPDIF_RX 91 +#define CLK_BUS_SPDIF 92 +#define CLK_DMIC 93 +#define CLK_BUS_DMIC 94 +#define CLK_AUDIO_DAC 95 +#define CLK_AUDIO_ADC 96 +#define CLK_BUS_AUDIO 97 +#define CLK_USB_48M 98 +#define CLK_USB_12M 99 +#define CLK_USB_OHCI0 100 +#define CLK_USB_OHCI1 101 +#define CLK_BUS_OHCI0 102 +#define CLK_BUS_OHCI1 103 +#define CLK_BUS_EHCI0 104 +#define CLK_BUS_EHCI1 105 +#define CLK_BUS_OTG 106 +#define CLK_BUS_LRADC 107 +#define CLK_BUS_DPSS_TOP 108 +#define CLK_HDMI_24M 109 +#define CLK_HDMI_CEC_32K 110 +#define CLK_HDMI_CEC 111 +#define CLK_BUS_HDMI 112 +#define CLK_MIPI_DSI 113 +#define CLK_BUS_MIPI_DSI 114 +#define CLK_TCON_LCD0 115 +#define CLK_BUS_TCON_LCD0 116 +#define CLK_TCON_TV 117 +#define CLK_BUS_TCON_TV 118 +#define CLK_TVE 119 +#define CLK_BUS_TVE_TOP 120 +#define CLK_BUS_TVE 121 +#define CLK_TVD 122 +#define CLK_BUS_TVD_TOP 123 +#define CLK_BUS_TVD 124 +#define CLK_LEDC 125 +#define CLK_BUS_LEDC 126 +#define CLK_CSI_TOP 127 +#define CLK_CSI_MCLK 128 +#define CLK_BUS_CSI 129 +#define CLK_TPADC 130 +#define CLK_BUS_TPADC 131 +#define CLK_BUS_TZMA 132 +#define CLK_DSP 133 +#define CLK_BUS_DSP_CFG 134 +#define CLK_RISCV 135 +#define CLK_RISCV_AXI 136 +#define CLK_BUS_RISCV_CFG 137 +#define CLK_FANOUT_24M 138 +#define CLK_FANOUT_12M 139 +#define CLK_FANOUT_16M 140 +#define CLK_FANOUT_25M 141 +#define CLK_FANOUT_32K 142 +#define CLK_FANOUT_27M 143 +#define CLK_FANOUT_PCLK 144 +#define CLK_FANOUT0 145 +#define CLK_FANOUT1 146 +#define CLK_FANOUT2 147 + +#endif /* _DT_BINDINGS_CLK_SUN20I_D1_CCU_H_ */ diff --git a/include/dt-bindings/clock/sun20i-d1-r-ccu.h b/include/dt-bindings/clock/sun20i-d1-r-ccu.h new file mode 100644 index 00000000000000..c1b449fa7b6cbb --- /dev/null +++ b/include/dt-bindings/clock/sun20i-d1-r-ccu.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2020 huangzhenwei@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#ifndef _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ +#define _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ + +#define CLK_BUS_R_TIMER 2 +#define CLK_BUS_R_TWD 3 +#define CLK_BUS_R_PPU 4 +#define CLK_R_IR_RX 5 +#define CLK_BUS_R_IR_RX 6 +#define CLK_BUS_R_RTC 7 +#define CLK_BUS_R_CPUCFG 8 + +#endif /* _DT_BINDINGS_CLK_SUN20I_D1_R_CCU_H_ */ diff --git a/include/dt-bindings/reset/sun20i-d1-ccu.h b/include/dt-bindings/reset/sun20i-d1-ccu.h new file mode 100644 index 00000000000000..5965b156e65821 --- /dev/null +++ b/include/dt-bindings/reset/sun20i-d1-ccu.h @@ -0,0 +1,77 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +/* + * Copyright (c) 2020 huangzhenwei@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#ifndef _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ +#define _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ + +#define RST_MBUS 0 +#define RST_BUS_DE 1 +#define RST_BUS_DI 2 +#define RST_BUS_G2D 3 +#define RST_BUS_CE 4 +#define RST_BUS_VE 5 +#define RST_BUS_DMA 6 +#define RST_BUS_MSGBOX0 7 +#define RST_BUS_MSGBOX1 8 +#define RST_BUS_MSGBOX2 9 +#define RST_BUS_SPINLOCK 10 +#define RST_BUS_HSTIMER 11 +#define RST_BUS_DBG 12 +#define RST_BUS_PWM 13 +#define RST_BUS_DRAM 14 +#define RST_BUS_MMC0 15 +#define RST_BUS_MMC1 16 +#define RST_BUS_MMC2 17 +#define RST_BUS_UART0 18 +#define RST_BUS_UART1 19 +#define RST_BUS_UART2 20 +#define RST_BUS_UART3 21 +#define RST_BUS_UART4 22 +#define RST_BUS_UART5 23 +#define RST_BUS_I2C0 24 +#define RST_BUS_I2C1 25 +#define RST_BUS_I2C2 26 +#define RST_BUS_I2C3 27 +#define RST_BUS_SPI0 28 +#define RST_BUS_SPI1 29 +#define RST_BUS_EMAC 30 +#define RST_BUS_IR_TX 31 +#define RST_BUS_GPADC 32 +#define RST_BUS_THS 33 +#define RST_BUS_I2S0 34 +#define RST_BUS_I2S1 35 +#define RST_BUS_I2S2 36 +#define RST_BUS_SPDIF 37 +#define RST_BUS_DMIC 38 +#define RST_BUS_AUDIO 39 +#define RST_USB_PHY0 40 +#define RST_USB_PHY1 41 +#define RST_BUS_OHCI0 42 +#define RST_BUS_OHCI1 43 +#define RST_BUS_EHCI0 44 +#define RST_BUS_EHCI1 45 +#define RST_BUS_OTG 46 +#define RST_BUS_LRADC 47 +#define RST_BUS_DPSS_TOP 48 +#define RST_BUS_HDMI_SUB 49 +#define RST_BUS_HDMI_MAIN 50 +#define RST_BUS_MIPI_DSI 51 +#define RST_BUS_TCON_LCD0 52 +#define RST_BUS_TCON_TV 53 +#define RST_BUS_LVDS0 54 +#define RST_BUS_TVE 55 +#define RST_BUS_TVE_TOP 56 +#define RST_BUS_TVD 57 +#define RST_BUS_TVD_TOP 58 +#define RST_BUS_LEDC 59 +#define RST_BUS_CSI 60 +#define RST_BUS_TPADC 61 +#define RST_DSP 62 +#define RST_BUS_DSP_CFG 63 +#define RST_BUS_DSP_DBG 64 +#define RST_BUS_RISCV_CFG 65 + +#endif /* _DT_BINDINGS_RST_SUN20I_D1_CCU_H_ */ diff --git a/include/dt-bindings/reset/sun20i-d1-r-ccu.h b/include/dt-bindings/reset/sun20i-d1-r-ccu.h new file mode 100644 index 00000000000000..cfb8491fed2e49 --- /dev/null +++ b/include/dt-bindings/reset/sun20i-d1-r-ccu.h @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */ +/* + * Copyright (C) 2020 huangzhenwei@allwinnertech.com + * Copyright (C) 2021 Samuel Holland + */ + +#ifndef _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ +#define _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ + +#define RST_BUS_R_TIMER 0 +#define RST_BUS_R_TWD 1 +#define RST_BUS_R_PPU 2 +#define RST_BUS_R_IR_RX 3 +#define RST_BUS_R_RTC 4 +#define RST_BUS_R_CPUCFG 5 + +#endif /* _DT_BINDINGS_RST_SUN20I_D1_R_CCU_H_ */ From d989270862891899c3207e0a6d993b61d7af04ef Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:54:21 -0500 Subject: [PATCH 030/120] clocksource: riscv: Prefer it over MMIO clocksources Signed-off-by: Samuel Holland --- drivers/clocksource/timer-riscv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clocksource/timer-riscv.c b/drivers/clocksource/timer-riscv.c index c51c5ed15aa75b..a035bdf6fc5804 100644 --- a/drivers/clocksource/timer-riscv.c +++ b/drivers/clocksource/timer-riscv.c @@ -54,7 +54,7 @@ static u64 notrace riscv_sched_clock(void) static struct clocksource riscv_clocksource = { .name = "riscv_clocksource", - .rating = 300, + .rating = 400, .mask = CLOCKSOURCE_MASK(64), .flags = CLOCK_SOURCE_IS_CONTINUOUS, .read = riscv_clocksource_rdtime, From cea41b65b757d1ef11f60704140b84004dfa7828 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 15:02:27 -0500 Subject: [PATCH 031/120] [STUB] riscv: Enable cpufreq Signed-off-by: Samuel Holland --- arch/riscv/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 466379f0cfb7f1..adb30fe10fa96e 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -576,6 +576,8 @@ endmenu menu "CPU Power Management" +source "drivers/cpufreq/Kconfig" + source "drivers/cpuidle/Kconfig" endmenu From 195547d954ce84e1d3b70091a45d705dc312bfb2 Mon Sep 17 00:00:00 2001 From: Shuosheng Huang Date: Tue, 8 Dec 2020 15:19:28 +0800 Subject: [PATCH 032/120] cpufreq: sun50i: add efuse_xlate to get efuse version. It's better to use efuse_xlate to extract the differentiated part regarding different SoC. Signed-off-by: Shuosheng Huang Signed-off-by: Samuel Holland --- drivers/cpufreq/sun50i-cpufreq-nvmem.c | 84 ++++++++++++++++---------- 1 file changed, 52 insertions(+), 32 deletions(-) diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c index 2deed8d8773fa6..e29ada03873d91 100644 --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -19,24 +19,51 @@ #define MAX_NAME_LEN 7 -#define NVMEM_MASK 0x7 -#define NVMEM_SHIFT 5 +#define SUN50I_H6_NVMEM_MASK 0x7 +#define SUN50I_H6_NVMEM_SHIFT 5 + +struct sunxi_cpufreq_soc_data { + int (*efuse_xlate)(struct nvmem_cell *speedbin_nvmem); +}; static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; +static int sun50i_h6_efuse_xlate(struct nvmem_cell *speedbin_nvmem) +{ + size_t len; + u32 *speedbin; + u32 efuse_value; + + speedbin = nvmem_cell_read(speedbin_nvmem, &len); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + + efuse_value = (*speedbin >> SUN50I_H6_NVMEM_SHIFT) & SUN50I_H6_NVMEM_MASK; + kfree(speedbin); + + /* + * We treat unexpected efuse values as if the SoC was from + * the slowest bin. Expected efuse values are 1-3, slowest + * to fastest. + */ + if (efuse_value >= 1 && efuse_value <= 3) + return efuse_value - 1; + else + return 0; +} + /** * sun50i_cpufreq_get_efuse() - Determine speed grade from efuse value - * @versions: Set to the value parsed from efuse + * @soc_data: pointer to sunxi_cpufreq_soc_data context * - * Returns 0 if success. + * Returns speed grade (OPP voltage index) if successful. */ -static int sun50i_cpufreq_get_efuse(u32 *versions) +static int sun50i_cpufreq_get_efuse(const struct sunxi_cpufreq_soc_data *soc_data) { struct nvmem_cell *speedbin_nvmem; struct device_node *np; struct device *cpu_dev; - u32 *speedbin, efuse_value; - size_t len; + int speed; int ret; cpu_dev = get_cpu_device(0); @@ -63,43 +90,33 @@ static int sun50i_cpufreq_get_efuse(u32 *versions) return PTR_ERR(speedbin_nvmem); } - speedbin = nvmem_cell_read(speedbin_nvmem, &len); + speed = soc_data->efuse_xlate(speedbin_nvmem); nvmem_cell_put(speedbin_nvmem); - if (IS_ERR(speedbin)) - return PTR_ERR(speedbin); - - efuse_value = (*speedbin >> NVMEM_SHIFT) & NVMEM_MASK; - /* - * We treat unexpected efuse values as if the SoC was from - * the slowest bin. Expected efuse values are 1-3, slowest - * to fastest. - */ - if (efuse_value >= 1 && efuse_value <= 3) - *versions = efuse_value - 1; - else - *versions = 0; - - kfree(speedbin); - return 0; + return speed; }; static int sun50i_cpufreq_nvmem_probe(struct platform_device *pdev) { + const struct of_device_id *match; struct opp_table **opp_tables; char name[MAX_NAME_LEN]; unsigned int cpu; - u32 speed = 0; + int speed = 0; int ret; + match = dev_get_platdata(&pdev->dev); + if (!match) + return -EINVAL; + opp_tables = kcalloc(num_possible_cpus(), sizeof(*opp_tables), GFP_KERNEL); if (!opp_tables) return -ENOMEM; - ret = sun50i_cpufreq_get_efuse(&speed); - if (ret) - return ret; + speed = sun50i_cpufreq_get_efuse(match->data); + if (speed < 0) + return speed; snprintf(name, MAX_NAME_LEN, "speed%d", speed); @@ -163,8 +180,12 @@ static struct platform_driver sun50i_cpufreq_driver = { }, }; +static const struct sunxi_cpufreq_soc_data sun50i_h6_data = { + .efuse_xlate = sun50i_h6_efuse_xlate, +}; + static const struct of_device_id sun50i_cpufreq_match_list[] = { - { .compatible = "allwinner,sun50i-h6" }, + { .compatible = "allwinner,sun50i-h6", .data = &sun50i_h6_data }, {} }; MODULE_DEVICE_TABLE(of, sun50i_cpufreq_match_list); @@ -199,9 +220,8 @@ static int __init sun50i_cpufreq_init(void) if (unlikely(ret < 0)) return ret; - sun50i_cpufreq_pdev = - platform_device_register_simple("sun50i-cpufreq-nvmem", - -1, NULL, 0); + sun50i_cpufreq_pdev = platform_device_register_data(NULL, + "sun50i-cpufreq-nvmem", -1, match, sizeof(*match)); ret = PTR_ERR_OR_ZERO(sun50i_cpufreq_pdev); if (ret == 0) return 0; From 338d56d231a67384825e6be30569439b2e33f855 Mon Sep 17 00:00:00 2001 From: Shuosheng Huang Date: Tue, 8 Dec 2020 15:19:53 +0800 Subject: [PATCH 033/120] cpufreq: sun50i: add A100 cpufreq support Add nvmem based cpufreq for Allwinner A100 SoC, which is similar to H6. Signed-off-by: Shuosheng Huang Signed-off-by: Samuel Holland --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 + drivers/cpufreq/sun50i-cpufreq-nvmem.c | 31 ++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index bef7528aecd313..c4d456ae6f6dbe 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -101,6 +101,7 @@ static const struct of_device_id allowlist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blocklist[] __initconst = { + { .compatible = "allwinner,sun50i-a100", }, { .compatible = "allwinner,sun50i-h6", }, { .compatible = "arm,vexpress", }, diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c index e29ada03873d91..3534133c3c9c36 100644 --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -19,6 +19,9 @@ #define MAX_NAME_LEN 7 +#define SUN50I_A100_NVMEM_MASK 0xf +#define SUN50I_A100_NVMEM_SHIFT 12 + #define SUN50I_H6_NVMEM_MASK 0x7 #define SUN50I_H6_NVMEM_SHIFT 5 @@ -28,6 +31,29 @@ struct sunxi_cpufreq_soc_data { static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; +static int sun50i_a100_efuse_xlate(struct nvmem_cell *speedbin_nvmem) +{ + size_t len; + u16 *speedbin; + u16 efuse_value; + + speedbin = nvmem_cell_read(speedbin_nvmem, &len); + if (IS_ERR(speedbin)) + return PTR_ERR(speedbin); + + efuse_value = (*speedbin >> SUN50I_A100_NVMEM_SHIFT) & SUN50I_A100_NVMEM_MASK; + kfree(speedbin); + + switch (efuse_value) { + case 0b100: + return 2; + case 0b010: + return 1; + default: + return 0; + } +} + static int sun50i_h6_efuse_xlate(struct nvmem_cell *speedbin_nvmem) { size_t len; @@ -180,11 +206,16 @@ static struct platform_driver sun50i_cpufreq_driver = { }, }; +static const struct sunxi_cpufreq_soc_data sun50i_a100_data = { + .efuse_xlate = sun50i_a100_efuse_xlate, +}; + static const struct sunxi_cpufreq_soc_data sun50i_h6_data = { .efuse_xlate = sun50i_h6_efuse_xlate, }; static const struct of_device_id sun50i_cpufreq_match_list[] = { + { .compatible = "allwinner,sun50i-a100", .data = &sun50i_a100_data }, { .compatible = "allwinner,sun50i-h6", .data = &sun50i_h6_data }, {} }; From a6ffa7942973d30cd633e27c33286ff6c73c24ed Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 21:18:52 -0500 Subject: [PATCH 034/120] cpufreq: sun50i: Move out of ARM-specific section Signed-off-by: Samuel Holland --- arch/arm64/configs/defconfig | 2 +- drivers/cpufreq/Kconfig | 12 ++++++++++++ drivers/cpufreq/Kconfig.arm | 12 ------------ drivers/cpufreq/Makefile | 2 +- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index f423d08b9a71b2..b621d89d5fc9b0 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -90,7 +90,6 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m CONFIG_CPU_FREQ_GOV_SCHEDUTIL=y CONFIG_CPUFREQ_DT=y CONFIG_ACPI_CPPC_CPUFREQ=m -CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM=m CONFIG_ARM_ARMADA_37XX_CPUFREQ=y CONFIG_ARM_SCPI_CPUFREQ=y CONFIG_ARM_IMX_CPUFREQ_DT=m @@ -100,6 +99,7 @@ CONFIG_ARM_RASPBERRYPI_CPUFREQ=m CONFIG_ARM_SCMI_CPUFREQ=y CONFIG_ARM_TEGRA186_CPUFREQ=y CONFIG_QORIQ_CPUFREQ=y +CONFIG_SUN50I_CPUFREQ_NVMEM=m CONFIG_ARM_SCMI_PROTOCOL=y CONFIG_ARM_SCPI_PROTOCOL=y CONFIG_RASPBERRYPI_FIRMWARE=y diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig index c3038cdc686500..82eb823ce58502 100644 --- a/drivers/cpufreq/Kconfig +++ b/drivers/cpufreq/Kconfig @@ -321,5 +321,17 @@ config QORIQ_CPUFREQ This adds the CPUFreq driver support for Freescale QorIQ SoCs which are capable of changing the CPU's frequency dynamically. +config SUN50I_CPUFREQ_NVMEM + tristate "Allwinner nvmem based SUN50I CPUFreq driver" + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST + depends on NVMEM_SUNXI_SID + select PM_OPP + help + This adds the nvmem based CPUFreq driver for Allwinner + sun20i/sun50i SoCs. + + To compile this driver as a module, choose M here: the + module will be called sun50i-cpufreq-nvmem. + endif endmenu diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm index a5c5f70acfc9ef..f042bc4ce43f31 100644 --- a/drivers/cpufreq/Kconfig.arm +++ b/drivers/cpufreq/Kconfig.arm @@ -29,18 +29,6 @@ config ACPI_CPPC_CPUFREQ_FIE If in doubt, say N. -config ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM - tristate "Allwinner nvmem based SUN50I CPUFreq driver" - depends on ARCH_SUNXI - depends on NVMEM_SUNXI_SID - select PM_OPP - help - This adds the nvmem based CPUFreq driver for Allwinner - h6 SoC. - - To compile this driver as a module, choose M here: the - module will be called sun50i-cpufreq-nvmem. - config ARM_ARMADA_37XX_CPUFREQ tristate "Armada 37xx CPUFreq support" depends on ARCH_MVEBU && CPUFREQ_DT diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index 27d3bd7ea9d4e7..434abcddb38382 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -77,7 +77,6 @@ obj-$(CONFIG_ARM_SCMI_CPUFREQ) += scmi-cpufreq.o obj-$(CONFIG_ARM_SCPI_CPUFREQ) += scpi-cpufreq.o obj-$(CONFIG_ARM_SPEAR_CPUFREQ) += spear-cpufreq.o obj-$(CONFIG_ARM_STI_CPUFREQ) += sti-cpufreq.o -obj-$(CONFIG_ARM_ALLWINNER_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o obj-$(CONFIG_ARM_TEGRA20_CPUFREQ) += tegra20-cpufreq.o obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) += tegra124-cpufreq.o obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o @@ -107,3 +106,4 @@ obj-$(CONFIG_LOONGSON1_CPUFREQ) += loongson1-cpufreq.o obj-$(CONFIG_SH_CPU_FREQ) += sh-cpufreq.o obj-$(CONFIG_SPARC_US2E_CPUFREQ) += sparc-us2e-cpufreq.o obj-$(CONFIG_SPARC_US3_CPUFREQ) += sparc-us3-cpufreq.o +obj-$(CONFIG_SUN50I_CPUFREQ_NVMEM) += sun50i-cpufreq-nvmem.o From 68d5f6cd5c5f0153dc1ecb17fa86cff91cc15dd2 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 22:10:05 -0500 Subject: [PATCH 035/120] [STUB] cpufreq: sun50i: Add D1 cpufreq support Signed-off-by: Samuel Holland --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 + drivers/cpufreq/sun50i-cpufreq-nvmem.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index c4d456ae6f6dbe..3219b8046802c3 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -101,6 +101,7 @@ static const struct of_device_id allowlist[] __initconst = { * platforms using "operating-points-v2" property. */ static const struct of_device_id blocklist[] __initconst = { + { .compatible = "allwinner,sun20i-d1", }, { .compatible = "allwinner,sun50i-a100", }, { .compatible = "allwinner,sun50i-h6", }, diff --git a/drivers/cpufreq/sun50i-cpufreq-nvmem.c b/drivers/cpufreq/sun50i-cpufreq-nvmem.c index 3534133c3c9c36..7eaf91f0e5de75 100644 --- a/drivers/cpufreq/sun50i-cpufreq-nvmem.c +++ b/drivers/cpufreq/sun50i-cpufreq-nvmem.c @@ -31,6 +31,11 @@ struct sunxi_cpufreq_soc_data { static struct platform_device *cpufreq_dt_pdev, *sun50i_cpufreq_pdev; +static int sun20i_d1_efuse_xlate(struct nvmem_cell *speedbin_nvmem) +{ + return 0; +} + static int sun50i_a100_efuse_xlate(struct nvmem_cell *speedbin_nvmem) { size_t len; @@ -206,6 +211,10 @@ static struct platform_driver sun50i_cpufreq_driver = { }, }; +static const struct sunxi_cpufreq_soc_data sun20i_d1_data = { + .efuse_xlate = sun20i_d1_efuse_xlate, +}; + static const struct sunxi_cpufreq_soc_data sun50i_a100_data = { .efuse_xlate = sun50i_a100_efuse_xlate, }; @@ -215,6 +224,7 @@ static const struct sunxi_cpufreq_soc_data sun50i_h6_data = { }; static const struct of_device_id sun50i_cpufreq_match_list[] = { + { .compatible = "allwinner,sun20i-d1", .data = &sun20i_d1_data }, { .compatible = "allwinner,sun50i-a100", .data = &sun50i_a100_data }, { .compatible = "allwinner,sun50i-h6", .data = &sun50i_h6_data }, {} From 3cccee50fd93bcb8bcd76e2bc3c87bb78813316d Mon Sep 17 00:00:00 2001 From: Corentin Labbe Date: Mon, 14 Jun 2021 20:54:01 +0200 Subject: [PATCH 036/120] crypto: sun8i-ce: add support for sun20i-d1 The Allwinner D1 SoC has a crypto engine compatible with sun8i-ce. Add support for it. Signed-off-by: Corentin Labbe Signed-off-by: Samuel Holland --- .../bindings/crypto/allwinner,sun8i-ce.yaml | 6 +++++- .../crypto/allwinner/sun8i-ce/sun8i-ce-core.c | 21 +++++++++++++++++++ drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml b/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml index 00648f9d9278c7..d43a8aad868073 100644 --- a/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml +++ b/Documentation/devicetree/bindings/crypto/allwinner,sun8i-ce.yaml @@ -14,6 +14,7 @@ properties: enum: - allwinner,sun8i-h3-crypto - allwinner,sun8i-r40-crypto + - allwinner,sun20i-d1-crypto - allwinner,sun50i-a64-crypto - allwinner,sun50i-h5-crypto - allwinner,sun50i-h6-crypto @@ -44,7 +45,10 @@ properties: if: properties: compatible: - const: allwinner,sun50i-h6-crypto + contains: + enum: + - allwinner,sun20i-d1-crypto + - allwinner,sun50i-h6-crypto then: properties: clocks: diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c index 00194d1d9ae69b..d8623c7e0d1d68 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce-core.c @@ -106,6 +106,24 @@ static const struct ce_variant ce_a64_variant = { .trng = CE_ID_NOTSUPP, }; +static const struct ce_variant ce_d1_variant = { + .alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES, + }, + .alg_hash = { CE_ALG_MD5, CE_ALG_SHA1, CE_ALG_SHA224, CE_ALG_SHA256, + CE_ALG_SHA384, CE_ALG_SHA512 + }, + .op_mode = { CE_OP_ECB, CE_OP_CBC + }, + .ce_clks = { + { "bus", 0, 200000000 }, + { "mod", 300000000, 0 }, + { "ram", 0, 400000000 }, + }, + .esr = ESR_D1, + .prng = CE_ALG_PRNG, + .trng = CE_ALG_TRNG, +}; + static const struct ce_variant ce_r40_variant = { .alg_cipher = { CE_ALG_AES, CE_ALG_DES, CE_ALG_3DES, }, @@ -192,6 +210,7 @@ int sun8i_ce_run_task(struct sun8i_ce_dev *ce, int flow, const char *name) dev_err(ce->dev, "CE ERROR: keysram access error for AES\n"); break; case ESR_A64: + case ESR_D1: case ESR_H5: case ESR_R40: v >>= (flow * 4); @@ -990,6 +1009,8 @@ static const struct of_device_id sun8i_ce_crypto_of_match_table[] = { .data = &ce_h3_variant }, { .compatible = "allwinner,sun8i-r40-crypto", .data = &ce_r40_variant }, + { .compatible = "allwinner,sun20i-d1-crypto", + .data = &ce_d1_variant }, { .compatible = "allwinner,sun50i-a64-crypto", .data = &ce_a64_variant }, { .compatible = "allwinner,sun50i-h5-crypto", diff --git a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h index cec781d5063c15..624a5926f21f19 100644 --- a/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h +++ b/drivers/crypto/allwinner/sun8i-ce/sun8i-ce.h @@ -94,6 +94,7 @@ #define ESR_R40 2 #define ESR_H5 3 #define ESR_H6 4 +#define ESR_D1 5 #define PRNG_DATA_SIZE (160 / 8) #define PRNG_SEED_SIZE DIV_ROUND_UP(175, 8) From 7d6ba1dfa5b8d3227ddaf902b20ca4461d642e7f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 12 Jun 2021 07:56:20 -0500 Subject: [PATCH 037/120] dt-bindings: dma: Add Allwinner D1 compatible Signed-off-by: Samuel Holland --- .../devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml index b6e1ebfaf36669..7d600eb3c5ef30 100644 --- a/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml +++ b/Documentation/devicetree/bindings/dma/allwinner,sun50i-a64-dma.yaml @@ -20,6 +20,7 @@ properties: compatible: oneOf: + - const: allwinner,sun20i-d1-dma - const: allwinner,sun50i-a64-dma - const: allwinner,sun50i-a100-dma - const: allwinner,sun50i-h6-dma @@ -58,6 +59,7 @@ if: properties: compatible: enum: + - allwinner,sun20i-d1-dma - allwinner,sun50i-a100-dma - allwinner,sun50i-h6-dma From 1d8c2dd07655e23a755f2a1472651914baa9bf7f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 14:44:12 -0500 Subject: [PATCH 038/120] dmaengine: sun6i: Add support for 34-bit physical addresses Signed-off-by: Samuel Holland --- drivers/dma/sun6i-dma.c | 39 ++++++++++++++++++++++++++++++++++----- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 5cadd4d2b82460..dbd4a145eed9fd 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -90,6 +90,14 @@ #define DMA_CHAN_CUR_PARA 0x1c +/* + * LLI address mangling + * + * The LLI link physical address is also mangled, but we avoid dealing + * with that by allocating LLIs from the DMA32 zone. + */ +#define SET_SRC_HIGH_ADDR(x) ((((x) >> 32) & 0x3U) << 16) +#define SET_DST_HIGH_ADDR(x) ((((x) >> 32) & 0x3U) << 18) /* * Various hardware related defines @@ -132,6 +140,7 @@ struct sun6i_dma_config { u32 dst_burst_lengths; u32 src_addr_widths; u32 dst_addr_widths; + bool has_high_addr; bool has_mbus_clk; }; @@ -223,6 +232,12 @@ to_sun6i_desc(struct dma_async_tx_descriptor *tx) return container_of(tx, struct sun6i_desc, vd.tx); } +static inline bool sun6i_dma_has_high_addr(struct sun6i_dma_dev *sdev) +{ + return IS_ENABLED(CONFIG_ARCH_DMA_ADDR_T_64BIT) && + sdev->cfg->has_high_addr; +} + static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev) { dev_dbg(sdev->slave.dev, "Common register:\n" @@ -648,7 +663,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( if (!txd) return NULL; - v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); + v_lli = dma_pool_alloc(sdev->pool, GFP_DMA32|GFP_NOWAIT, &p_lli); if (!v_lli) { dev_err(sdev->slave.dev, "Failed to alloc lli memory\n"); goto err_txd_free; @@ -658,6 +673,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( v_lli->dst = dest; v_lli->len = len; v_lli->para = NORMAL_WAIT; + if (sun6i_dma_has_high_addr(sdev)) + v_lli->para |= SET_SRC_HIGH_ADDR(src) | + SET_DST_HIGH_ADDR(dest); burst = convert_burst(8); width = convert_buswidth(DMA_SLAVE_BUSWIDTH_4_BYTES); @@ -708,7 +726,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( return NULL; for_each_sg(sgl, sg, sg_len, i) { - v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); + v_lli = dma_pool_alloc(sdev->pool, GFP_DMA32|GFP_NOWAIT, &p_lli); if (!v_lli) goto err_lli_free; @@ -718,6 +736,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( if (dir == DMA_MEM_TO_DEV) { v_lli->src = sg_dma_address(sg); v_lli->dst = sconfig->dst_addr; + if (sun6i_dma_has_high_addr(sdev)) + v_lli->para |= SET_SRC_HIGH_ADDR(sg_dma_address(sg)) | + SET_DST_HIGH_ADDR(sconfig->dst_addr); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port); sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE); @@ -731,6 +752,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( } else { v_lli->src = sconfig->src_addr; v_lli->dst = sg_dma_address(sg); + if (sun6i_dma_has_high_addr(sdev)) + v_lli->para |= SET_SRC_HIGH_ADDR(sconfig->src_addr) | + SET_DST_HIGH_ADDR(sg_dma_address(sg)); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM); sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE); @@ -787,7 +811,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( return NULL; for (i = 0; i < periods; i++) { - v_lli = dma_pool_alloc(sdev->pool, GFP_NOWAIT, &p_lli); + v_lli = dma_pool_alloc(sdev->pool, GFP_DMA32|GFP_NOWAIT, &p_lli); if (!v_lli) { dev_err(sdev->slave.dev, "Failed to alloc lli memory\n"); goto err_lli_free; @@ -799,12 +823,18 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( if (dir == DMA_MEM_TO_DEV) { v_lli->src = buf_addr + period_len * i; v_lli->dst = sconfig->dst_addr; + if (sun6i_dma_has_high_addr(sdev)) + v_lli->para |= SET_SRC_HIGH_ADDR(buf_addr + period_len * i) | + SET_DST_HIGH_ADDR(sconfig->dst_addr); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port); sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE); } else { v_lli->src = sconfig->src_addr; v_lli->dst = buf_addr + period_len * i; + if (sun6i_dma_has_high_addr(sdev)) + v_lli->para |= SET_SRC_HIGH_ADDR(sconfig->src_addr) | + SET_DST_HIGH_ADDR(buf_addr + period_len * i); v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM); sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE); @@ -1174,8 +1204,6 @@ static struct sun6i_dma_config sun50i_a64_dma_cfg = { }; /* - * TODO: Add support for more than 4g physical addressing. - * * The A100 binding uses the number of dma channels from the * device tree node. */ @@ -1194,6 +1222,7 @@ static struct sun6i_dma_config sun50i_a100_dma_cfg = { BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) | BIT(DMA_SLAVE_BUSWIDTH_8_BYTES), + .has_high_addr = true, .has_mbus_clk = true, }; From 5d7149ff040bd52f740d5775d909d69cd11352f4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 14:50:51 -0500 Subject: [PATCH 039/120] dmaengine: sun6i: Stop using virt_to_phys Signed-off-by: Samuel Holland --- drivers/dma/sun6i-dma.c | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index dbd4a145eed9fd..8c7cce643cdc7c 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -256,9 +256,7 @@ static inline void sun6i_dma_dump_com_regs(struct sun6i_dma_dev *sdev) static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev, struct sun6i_pchan *pchan) { - phys_addr_t reg = virt_to_phys(pchan->base); - - dev_dbg(sdev->slave.dev, "Chan %d reg: %pa\n" + dev_dbg(sdev->slave.dev, "Chan %d reg: 0x%lx\n" "\t___en(%04x): \t0x%08x\n" "\tpause(%04x): \t0x%08x\n" "\tstart(%04x): \t0x%08x\n" @@ -267,7 +265,7 @@ static inline void sun6i_dma_dump_chan_regs(struct sun6i_dma_dev *sdev, "\t__dst(%04x): \t0x%08x\n" "\tcount(%04x): \t0x%08x\n" "\t_para(%04x): \t0x%08x\n\n", - pchan->idx, ®, + pchan->idx, pchan->base - sdev->base, DMA_CHAN_ENABLE, readl(pchan->base + DMA_CHAN_ENABLE), DMA_CHAN_PAUSE, @@ -400,17 +398,16 @@ static void *sun6i_dma_lli_add(struct sun6i_dma_lli *prev, } static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan, - struct sun6i_dma_lli *lli) + struct sun6i_dma_lli *v_lli, + dma_addr_t p_lli) { - phys_addr_t p_lli = virt_to_phys(lli); - dev_dbg(chan2dev(&vchan->vc.chan), - "\n\tdesc: p - %pa v - 0x%p\n" + "\n\tdesc:\tp - %pad v - 0x%p\n" "\t\tc - 0x%08x s - 0x%08x d - 0x%08x\n" "\t\tl - 0x%08x p - 0x%08x n - 0x%08x\n", - &p_lli, lli, - lli->cfg, lli->src, lli->dst, - lli->len, lli->para, lli->p_lli_next); + &p_lli, v_lli, + v_lli->cfg, v_lli->src, v_lli->dst, + v_lli->len, v_lli->para, v_lli->p_lli_next); } static void sun6i_dma_free_desc(struct virt_dma_desc *vd) @@ -460,7 +457,7 @@ static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) pchan->desc = to_sun6i_desc(&desc->tx); pchan->done = NULL; - sun6i_dma_dump_lli(vchan, pchan->desc->v_lli); + sun6i_dma_dump_lli(vchan, pchan->desc->v_lli, pchan->desc->p_lli); irq_reg = pchan->idx / DMA_IRQ_CHAN_NR; irq_offset = pchan->idx % DMA_IRQ_CHAN_NR; @@ -688,7 +685,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( sun6i_dma_lli_add(NULL, v_lli, p_lli, txd); - sun6i_dma_dump_lli(vchan, v_lli); + sun6i_dma_dump_lli(vchan, v_lli, p_lli); return vchan_tx_prep(&vchan->vc, &txd->vd, flags); @@ -770,14 +767,16 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( } dev_dbg(chan2dev(chan), "First: %pad\n", &txd->p_lli); - for (prev = txd->v_lli; prev; prev = prev->v_lli_next) - sun6i_dma_dump_lli(vchan, prev); + for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; + p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) + sun6i_dma_dump_lli(vchan, v_lli, p_lli); return vchan_tx_prep(&vchan->vc, &txd->vd, flags); err_lli_free: - for (prev = txd->v_lli; prev; prev = prev->v_lli_next) - dma_pool_free(sdev->pool, prev, virt_to_phys(prev)); + for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; + p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) + dma_pool_free(sdev->pool, v_lli, p_lli); kfree(txd); return NULL; } @@ -850,8 +849,9 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( return vchan_tx_prep(&vchan->vc, &txd->vd, flags); err_lli_free: - for (prev = txd->v_lli; prev; prev = prev->v_lli_next) - dma_pool_free(sdev->pool, prev, virt_to_phys(prev)); + for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; + p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) + dma_pool_free(sdev->pool, v_lli, p_lli); kfree(txd); return NULL; } From 2fbfb06c0e2a84693ecde5a6707dba109588e17e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 14:51:23 -0500 Subject: [PATCH 040/120] dmaengine: sun6i: Changes from BSP Signed-off-by: Samuel Holland --- drivers/dma/sun6i-dma.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 8c7cce643cdc7c..52d9c4ef58f8df 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -938,6 +938,7 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan) vchan_get_all_descriptors(&vchan->vc, &head); if (pchan) { + writel(DMA_CHAN_PAUSE_PAUSE, pchan->base + DMA_CHAN_PAUSE); writel(DMA_CHAN_ENABLE_STOP, pchan->base + DMA_CHAN_ENABLE); writel(DMA_CHAN_PAUSE_RESUME, pchan->base + DMA_CHAN_PAUSE); @@ -954,6 +955,13 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan) return 0; } +static void sun6i_dma_synchronize(struct dma_chan *chan) +{ + struct sun6i_vchan *vchan = to_sun6i_vchan(chan); + + vchan_synchronize(&vchan->vc); +} + static enum dma_status sun6i_dma_tx_status(struct dma_chan *chan, dma_cookie_t cookie, struct dma_tx_state *state) @@ -1356,6 +1364,7 @@ static int sun6i_dma_probe(struct platform_device *pdev) sdc->slave.device_pause = sun6i_dma_pause; sdc->slave.device_resume = sun6i_dma_resume; sdc->slave.device_terminate_all = sun6i_dma_terminate_all; + sdc->slave.device_synchronize = sun6i_dma_synchronize; sdc->slave.src_addr_widths = sdc->cfg->src_addr_widths; sdc->slave.dst_addr_widths = sdc->cfg->dst_addr_widths; sdc->slave.directions = BIT(DMA_DEV_TO_MEM) | @@ -1414,9 +1423,9 @@ static int sun6i_dma_probe(struct platform_device *pdev) vchan_init(&vchan->vc, &sdc->slave); } - ret = reset_control_deassert(sdc->rstc); + ret = reset_control_reset(sdc->rstc); if (ret) { - dev_err(&pdev->dev, "Couldn't deassert the device from reset\n"); + dev_err(&pdev->dev, "Couldn't reset the device\n"); goto err_chan_free; } From 1a3ca84fab40732bcdb58e1836f817b459887f5f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 12 Jun 2021 08:04:28 -0500 Subject: [PATCH 041/120] dmaengine: sun6i: Add support for D1 DMA Signed-off-by: Samuel Holland --- drivers/dma/sun6i-dma.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index 52d9c4ef58f8df..0387a06c077453 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -1285,6 +1285,7 @@ static const struct of_device_id sun6i_dma_match[] = { { .compatible = "allwinner,sun8i-a83t-dma", .data = &sun8i_a83t_dma_cfg }, { .compatible = "allwinner,sun8i-h3-dma", .data = &sun8i_h3_dma_cfg }, { .compatible = "allwinner,sun8i-v3s-dma", .data = &sun8i_v3s_dma_cfg }, + { .compatible = "allwinner,sun20i-d1-dma", .data = &sun50i_a100_dma_cfg }, { .compatible = "allwinner,sun50i-a64-dma", .data = &sun50i_a64_dma_cfg }, { .compatible = "allwinner,sun50i-a100-dma", .data = &sun50i_a100_dma_cfg }, { .compatible = "allwinner,sun50i-h6-dma", .data = &sun50i_h6_dma_cfg }, From 3a1011def6e008069523a3dfb5c22f94746b6338 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:41:44 -0500 Subject: [PATCH 042/120] hwspinlock: sun6i: Update driver to match binding Signed-off-by: Samuel Holland --- drivers/hwspinlock/sun6i_hwspinlock.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/hwspinlock/sun6i_hwspinlock.c b/drivers/hwspinlock/sun6i_hwspinlock.c index c2d314588046eb..28780be54e68c4 100644 --- a/drivers/hwspinlock/sun6i_hwspinlock.c +++ b/drivers/hwspinlock/sun6i_hwspinlock.c @@ -96,7 +96,7 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev) u32 num_banks; int err, i; - io_base = devm_platform_ioremap_resource(pdev, SPINLOCK_BASE_ID); + io_base = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(io_base)) return PTR_ERR(io_base); @@ -104,14 +104,12 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev) if (!priv) return -ENOMEM; - priv->ahb_clk = devm_clk_get(&pdev->dev, "ahb"); - if (IS_ERR(priv->ahb_clk)) { - err = PTR_ERR(priv->ahb_clk); - dev_err(&pdev->dev, "unable to get AHB clock (%d)\n", err); - return err; - } + priv->ahb_clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(priv->ahb_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(priv->ahb_clk), + "unable to get AHB clock\n"); - priv->reset = devm_reset_control_get(&pdev->dev, "ahb"); + priv->reset = devm_reset_control_get(&pdev->dev, NULL); if (IS_ERR(priv->reset)) return dev_err_probe(&pdev->dev, PTR_ERR(priv->reset), "unable to get reset control\n"); From fc70767a2c601e68a4e3dc2d842ba0a872527e31 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:42:19 -0500 Subject: [PATCH 043/120] hwspinlock: sun6i: Register layout is known Signed-off-by: Samuel Holland --- drivers/hwspinlock/sun6i_hwspinlock.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/drivers/hwspinlock/sun6i_hwspinlock.c b/drivers/hwspinlock/sun6i_hwspinlock.c index 28780be54e68c4..2e6c88eb9ba19b 100644 --- a/drivers/hwspinlock/sun6i_hwspinlock.c +++ b/drivers/hwspinlock/sun6i_hwspinlock.c @@ -127,22 +127,16 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev) } /* - * bit 28 and 29 represents the hwspinlock setup - * - * every datasheet (A64, A80, A83T, H3, H5, H6 ...) says the default value is 0x1 and 0x1 - * to 0x4 represent 32, 64, 128 and 256 locks - * but later datasheets (H5, H6) say 00, 01, 10, 11 represent 32, 64, 128 and 256 locks, - * but that would mean H5 and H6 have 64 locks, while their datasheets talk about 32 locks - * all the time, not a single mentioning of 64 locks - * the 0x4 value is also not representable by 2 bits alone, so some datasheets are not - * correct - * one thing have all in common, default value of the sysstatus register is 0x10000000, - * which results in bit 28 being set - * this is the reason 0x1 is considered being 32 locks and bit 30 is taken into account - * verified on H2+ (datasheet 0x1 = 32 locks) and H5 (datasheet 01 = 64 locks) + * Bits 28 and 29 represent the hwspinlock setup. + * 0x0 == 0x4 -> 256 spinlocks. + * All known hardware has 0x1 -> 32 spinlocks. + * The H5 and H6 datasheets incorrectly list the values off by one. */ num_banks = readl(io_base + SPINLOCK_SYSSTATUS_REG) >> 28; switch (num_banks) { + case 0: + num_banks = 4; + fallthrough; case 1 ... 4: priv->nlocks = 1 << (4 + num_banks); break; From d06bc35e2242920a4fc1587637f109e7ac0b6faa Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:42:27 -0500 Subject: [PATCH 044/120] hwspinlock: sun6i: Fix debugfs leak Signed-off-by: Samuel Holland --- drivers/hwspinlock/sun6i_hwspinlock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hwspinlock/sun6i_hwspinlock.c b/drivers/hwspinlock/sun6i_hwspinlock.c index 2e6c88eb9ba19b..1af796a2e1a124 100644 --- a/drivers/hwspinlock/sun6i_hwspinlock.c +++ b/drivers/hwspinlock/sun6i_hwspinlock.c @@ -160,13 +160,11 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev) /* failure of debugfs is considered non-fatal */ sun6i_hwspinlock_debugfs_init(priv); - if (IS_ERR(priv->debugfs)) - priv->debugfs = NULL; err = devm_add_action_or_reset(&pdev->dev, sun6i_hwspinlock_disable, priv); if (err) { dev_err(&pdev->dev, "failed to add hwspinlock disable action\n"); - goto bank_fail; + goto action_fail; } platform_set_drvdata(pdev, priv); @@ -174,6 +172,8 @@ static int sun6i_hwspinlock_probe(struct platform_device *pdev) return devm_hwspin_lock_register(&pdev->dev, priv->bank, &sun6i_hwspinlock_ops, SPINLOCK_BASE_ID, priv->nlocks); +action_fail: + debugfs_remove_recursive(priv->debugfs); bank_fail: clk_disable_unprepare(priv->ahb_clk); clk_fail: From c1acad086195382cec3eee501f92b2cecaf1636b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 09:30:03 -0500 Subject: [PATCH 045/120] dt-bindings: input: Add D1 support to LRADC keys Signed-off-by: Samuel Holland --- .../input/allwinner,sun4i-a10-lradc-keys.yaml | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml index cffd02028d02a2..d8df7dae7a359a 100644 --- a/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml +++ b/Documentation/devicetree/bindings/input/allwinner,sun4i-a10-lradc-keys.yaml @@ -15,6 +15,7 @@ properties: oneOf: - const: allwinner,sun4i-a10-lradc-keys - const: allwinner,sun8i-a83t-r-lradc + - const: allwinner,sun20i-d1-lradc - items: - const: allwinner,sun50i-a64-lradc - const: allwinner,sun8i-a83t-r-lradc @@ -22,6 +23,12 @@ properties: reg: maxItems: 1 + clocks: + maxItems: 1 + + resets: + maxItems: 1 + interrupts: maxItems: 1 @@ -66,6 +73,17 @@ required: - interrupts - vref-supply +if: + properties: + compatible: + enum: + - allwinner,sun20i-d1-lradc + +then: + required: + - clocks + - resets + additionalProperties: false examples: From aeddd11f946a6fa894dfc8ea6e84b0f6ab28f71b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 09:30:39 -0500 Subject: [PATCH 046/120] Input: sun4i-lradc-keys: Add clock/reset support for D1 Signed-off-by: Samuel Holland --- drivers/input/keyboard/sun4i-lradc-keys.c | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c index 4a796bed48acc1..50fc1805282990 100644 --- a/drivers/input/keyboard/sun4i-lradc-keys.c +++ b/drivers/input/keyboard/sun4i-lradc-keys.c @@ -14,6 +14,7 @@ * there are no boards known to use channel 1. */ +#include #include #include #include @@ -23,6 +24,7 @@ #include #include #include +#include #include #define LRADC_CTRL 0x00 @@ -83,6 +85,8 @@ struct sun4i_lradc_data { struct device *dev; struct input_dev *input; void __iomem *base; + struct clk *clk; + struct reset_control *reset; struct regulator *vref_supply; struct sun4i_lradc_keymap *chan0_map; const struct lradc_variant *variant; @@ -140,6 +144,14 @@ static int sun4i_lradc_open(struct input_dev *dev) if (error) return error; + error = reset_control_deassert(lradc->reset); + if (error) + goto err_disable_reg; + + error = clk_prepare_enable(lradc->clk); + if (error) + goto err_assert_reset; + lradc->vref = regulator_get_voltage(lradc->vref_supply) * lradc->variant->divisor_numerator / lradc->variant->divisor_denominator; @@ -153,6 +165,13 @@ static int sun4i_lradc_open(struct input_dev *dev) writel(CHAN0_KEYUP_IRQ | CHAN0_KEYDOWN_IRQ, lradc->base + LRADC_INTC); return 0; + +err_assert_reset: + reset_control_assert(lradc->reset); +err_disable_reg: + regulator_disable(lradc->vref_supply); + + return error; } static void sun4i_lradc_close(struct input_dev *dev) @@ -164,6 +183,8 @@ static void sun4i_lradc_close(struct input_dev *dev) SAMPLE_RATE(2), lradc->base + LRADC_CTRL); writel(0, lradc->base + LRADC_INTC); + clk_disable_unprepare(lradc->clk); + reset_control_assert(lradc->reset); regulator_disable(lradc->vref_supply); } @@ -243,6 +264,14 @@ static int sun4i_lradc_probe(struct platform_device *pdev) return -EINVAL; } + lradc->clk = devm_clk_get_optional(dev, NULL); + if (IS_ERR(lradc->clk)) + return PTR_ERR(lradc->clk); + + lradc->reset = devm_reset_control_get_optional_exclusive(dev, NULL); + if (IS_ERR(lradc->reset)) + return PTR_ERR(lradc->reset); + lradc->vref_supply = devm_regulator_get(dev, "vref"); if (IS_ERR(lradc->vref_supply)) return PTR_ERR(lradc->vref_supply); From 5806ca165f97cafbe2baa430411ea2b2ccc83d78 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 09:31:10 -0500 Subject: [PATCH 047/120] Input: sun4i-lradc-keys: Add support for D1 Signed-off-by: Samuel Holland --- drivers/input/keyboard/sun4i-lradc-keys.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/input/keyboard/sun4i-lradc-keys.c b/drivers/input/keyboard/sun4i-lradc-keys.c index 50fc1805282990..22d4b79fcc62fe 100644 --- a/drivers/input/keyboard/sun4i-lradc-keys.c +++ b/drivers/input/keyboard/sun4i-lradc-keys.c @@ -319,6 +319,8 @@ static const struct of_device_id sun4i_lradc_of_match[] = { .data = &lradc_variant_a10 }, { .compatible = "allwinner,sun8i-a83t-r-lradc", .data = &r_lradc_variant_a83t }, + { .compatible = "allwinner,sun20i-d1-lradc", + .data = &r_lradc_variant_a83t }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sun4i_lradc_of_match); From 5da41e97b92d79ec151073adf4014d8838ad983b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:20:38 -0500 Subject: [PATCH 048/120] dt-bindings: iommu: Add compatible for D1 IOMMU Signed-off-by: Samuel Holland --- .../bindings/iommu/allwinner,sun50i-h6-iommu.yaml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml index 5e125cf2a88b45..613fc4197cc6ca 100644 --- a/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml +++ b/Documentation/devicetree/bindings/iommu/allwinner,sun50i-h6-iommu.yaml @@ -17,7 +17,9 @@ properties: The content of the cell is the master ID. compatible: - const: allwinner,sun50i-h6-iommu + oneOf: + const: allwinner,sun20i-d1-iommu + const: allwinner,sun50i-h6-iommu reg: maxItems: 1 @@ -37,7 +39,16 @@ required: - reg - interrupts - clocks - - resets + +if: + properties: + compatible: + enum: + - allwinner,sun50i-h6-iommu + +then: + required: + - resets additionalProperties: false From d796e5f2d3ec07fc764695daf8b8002c2d499cf6 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:21:00 -0500 Subject: [PATCH 049/120] [WIP] iommu/sun50i: Add support for D1 IOMMU Signed-off-by: Samuel Holland --- drivers/iommu/sun50i-iommu.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c index 181bb1c3437c0e..4595a5c09ade82 100644 --- a/drivers/iommu/sun50i-iommu.c +++ b/drivers/iommu/sun50i-iommu.c @@ -48,15 +48,20 @@ #define IOMMU_TLB_FLUSH_MACRO_TLB BIT(16) #define IOMMU_TLB_FLUSH_MICRO_TLB(i) (BIT(i) & GENMASK(5, 0)) +#define IOMMU_TLB_IVLD_MODE_SEL_REG 0x084 +#define IOMMU_TLB_IVLD_START_ADDR_REG 0x088 +#define IOMMU_TLB_IVLD_END_ADDR_REG 0x08c #define IOMMU_TLB_IVLD_ADDR_REG 0x090 #define IOMMU_TLB_IVLD_ADDR_MASK_REG 0x094 #define IOMMU_TLB_IVLD_ENABLE_REG 0x098 #define IOMMU_TLB_IVLD_ENABLE_ENABLE BIT(0) #define IOMMU_PC_IVLD_ADDR_REG 0x0a0 +#define IOMMU_PC_IVLD_START_ADDR_REG 0x0a4 #define IOMMU_PC_IVLD_ENABLE_REG 0x0a8 #define IOMMU_PC_IVLD_ENABLE_ENABLE BIT(0) +#define IOMMU_PC_IVLD_END_ADDR_REG 0x0ac #define IOMMU_DM_AUT_CTRL_REG(d) (0x0b0 + ((d) / 2) * 4) #define IOMMU_DM_AUT_CTRL_RD_UNAVAIL(d, m) (1 << (((d & 1) * 16) + ((m) * 2))) #define IOMMU_DM_AUT_CTRL_WR_UNAVAIL(d, m) (1 << (((d & 1) * 16) + ((m) * 2) + 1)) @@ -72,6 +77,19 @@ #define IOMMU_L1PG_INT_REG 0x0180 #define IOMMU_L2PG_INT_REG 0x0184 +#define IOMMU_VA_REG 0x0190 +#define IOMMU_VA_DATA_REG 0x0194 +#define IOMMU_VA_CONFIG_REG 0x0198 +#define IOMMU_PMU_ENABLE_REG 0x0200 +#define IOMMU_PMU_CLR_REG 0x0210 +#define IOMMU_PMU_ACCESS_LOW_REG(i) (0x230 + (i) * 16) +#define IOMMU_PMU_ACCESS_HIGH_REG(i) (0x234 + (i) * 16) +#define IOMMU_PMU_HIT_LOW_REG(i) (0x238 + (i) * 16) +#define IOMMU_PMU_HIT_HIGH_REG(i) (0x23c + (i) * 16) +#define IOMMU_PMU_TL_LOW_REG(i) (0x300 + (i) * 16) +#define IOMMU_PMU_TL_HIGH_REG(i) (0x304 + (i) * 16) +#define IOMMU_PMU_ML_REG(i) (0x308 + (i) * 16) + #define IOMMU_INT_INVALID_L2PG BIT(17) #define IOMMU_INT_INVALID_L1PG BIT(16) #define IOMMU_INT_MASTER_PERMISSION(m) BIT(m) @@ -956,7 +974,7 @@ static int sun50i_iommu_probe(struct platform_device *pdev) goto err_free_group; } - iommu->reset = devm_reset_control_get(&pdev->dev, NULL); + iommu->reset = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL); if (IS_ERR(iommu->reset)) { dev_err(&pdev->dev, "Couldn't get our reset line.\n"); ret = PTR_ERR(iommu->reset); @@ -997,6 +1015,7 @@ static int sun50i_iommu_probe(struct platform_device *pdev) } static const struct of_device_id sun50i_iommu_dt[] = { + { .compatible = "allwinner,sun20i-d1-iommu", }, { .compatible = "allwinner,sun50i-h6-iommu", }, { /* sentinel */ }, }; From 6038cb9213080565ed0da6f32661203d2a4f1287 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:58:08 -0500 Subject: [PATCH 050/120] irqchip/sun20i: Add an Allwinner D1 stacked driver Signed-off-by: Samuel Holland --- drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-sun20i.c | 155 +++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) create mode 100644 drivers/irqchip/irq-sun20i.c diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index f88cbf36a9d28d..e672b3560ac8f6 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -25,6 +25,7 @@ obj-$(CONFIG_ORION_IRQCHIP) += irq-orion.o obj-$(CONFIG_OMAP_IRQCHIP) += irq-omap-intc.o obj-$(CONFIG_ARCH_SUNXI) += irq-sun4i.o obj-$(CONFIG_ARCH_SUNXI) += irq-sun6i-r.o +obj-$(CONFIG_SOC_SUNXI) += irq-sun20i.o obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi-nmi.o obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o obj-$(CONFIG_ARM_GIC) += irq-gic.o irq-gic-common.o diff --git a/drivers/irqchip/irq-sun20i.c b/drivers/irqchip/irq-sun20i.c new file mode 100644 index 00000000000000..ce54c6f95d6cf0 --- /dev/null +++ b/drivers/irqchip/irq-sun20i.c @@ -0,0 +1,155 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Allwinner sun20i (D1) wakeup irqchip driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SUN20I_HWIRQ_OFFSET 16 +#define SUN20I_NR_HWIRQS 160 + +#define SUN20I_HWIRQ_BIT(hwirq) ((hwirq) % 32) +#define SUN20I_HWIRQ_REG(hwirq) ((hwirq) / 32) + +#define SUN20I_WAKEUP_EN_REG 0x0020 +#define SUN20I_WAKEUP_MASK_REG(n) (0x0024 + 4 * (n)) +#define SUN20I_IRQ_MODE_REG(n) (0x0060 + 4 * (n)) + +static void __iomem *base; + +static int sun20i_intc_irq_set_type(struct irq_data *data, unsigned int type) +{ + u32 reg = SUN20I_IRQ_MODE_REG(SUN20I_HWIRQ_REG(data->hwirq)); + u32 bit = BIT(SUN20I_HWIRQ_BIT(data->hwirq)); + u32 val; + + val = readl(base + reg); + + switch (type) { + case IRQ_TYPE_EDGE_RISING: + val |= bit; + break; + case IRQ_TYPE_LEVEL_HIGH: + val &= ~bit; + break; + default: + return -EINVAL; + } + + writel_relaxed(val, base + reg); + + return 0; +} + +static int sun20i_intc_irq_set_wake(struct irq_data *data, unsigned int on) +{ + u32 reg = SUN20I_WAKEUP_MASK_REG(SUN20I_HWIRQ_REG(data->hwirq)); + u32 bit = BIT(SUN20I_HWIRQ_BIT(data->hwirq)); + u32 val; + + val = readl(base + reg); + + if (on) + val |= bit; + else + val &= ~bit; + + writel_relaxed(val, base + reg); + + return 0; +} + +static struct irq_chip sun20i_intc_wakeup_chip = { + .name = "sun20i-intc", + .irq_mask = irq_chip_mask_parent, + .irq_unmask = irq_chip_unmask_parent, + .irq_eoi = irq_chip_eoi_parent, + .irq_set_affinity = irq_chip_set_affinity_parent, + .irq_set_type = sun20i_intc_irq_set_type, + .irq_set_wake = sun20i_intc_irq_set_wake, +}; + +static int sun20i_intc_domain_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + if (fwspec->param_count < 2) + return -EINVAL; + if (fwspec->param[0] < SUN20I_HWIRQ_OFFSET) + return -EINVAL; + + *hwirq = fwspec->param[0] - SUN20I_HWIRQ_OFFSET; + *type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK; + + return 0; +} + +static int sun20i_intc_domain_alloc(struct irq_domain *domain, + unsigned int virq, + unsigned int nr_irqs, void *arg) +{ + struct irq_fwspec *fwspec = arg; + unsigned long hwirq; + unsigned int type; + int i, ret; + + ret = sun20i_intc_domain_translate(domain, fwspec, &hwirq, &type); + if (ret) + return ret; + if (hwirq + nr_irqs > SUN20I_NR_HWIRQS) + return -EINVAL; + + ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, fwspec); + if (ret) + return ret; + + for (i = 0; i < nr_irqs; ++i, ++hwirq, ++virq) + irq_domain_set_hwirq_and_chip(domain, virq, hwirq, + &sun20i_intc_wakeup_chip, 0); + + return 0; +} + +static const struct irq_domain_ops sun20i_intc_domain_ops = { + .translate = sun20i_intc_domain_translate, + .alloc = sun20i_intc_domain_alloc, + .free = irq_domain_free_irqs_common, +}; + +static int __init sun20i_intc_init(struct device_node *node, + struct device_node *parent) +{ + struct irq_domain *domain, *parent_domain; + + parent_domain = irq_find_host(parent); + if (!parent_domain) { + pr_err("%pOF: Failed to obtain parent domain\n", node); + return -ENXIO; + } + + base = of_io_request_and_map(node, 0, NULL); + if (IS_ERR(base)) { + pr_err("%pOF: Failed to map MMIO region\n", node); + return PTR_ERR(base); + } + + domain = irq_domain_add_hierarchy(parent_domain, 0, 0, node, + &sun20i_intc_domain_ops, NULL); + if (!domain) { + pr_err("%pOF: Failed to allocate domain\n", node); + iounmap(base); + return -ENOMEM; + } + + return 0; +} +IRQCHIP_DECLARE(sun20i_intc, "allwinner,sun20i-d1-intc", sun20i_intc_init); From a7088e01a6e96bcae31fba03dbe8c5c0dfbdf83c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 26 Jun 2021 11:02:49 -0500 Subject: [PATCH 051/120] leds-sun20i: New driver for the sun20i internal LED controller Signed-off-by: Samuel Holland --- drivers/leds/Kconfig | 7 + drivers/leds/Makefile | 1 + drivers/leds/leds-sun20i.c | 562 +++++++++++++++++++++++++++++++++++++ 3 files changed, 570 insertions(+) create mode 100644 drivers/leds/leds-sun20i.c diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index bdf16180f5ffe0..ee2a4e75e630db 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig @@ -928,6 +928,13 @@ config LEDS_ACER_A500 This option enables support for the Power Button LED of Acer Iconia Tab A500. +config LEDS_SUN20I + tristate "LED support for sun20i built-in LED controller" + depends on LEDS_CLASS + help + This option enables support for the LED controller in the + Allwinner sun20i SoCs. + source "drivers/leds/blink/Kconfig" comment "Flash and Torch LED drivers" diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 7e604d3028c80a..4c5487d31903c6 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_LEDS_REGULATOR) += leds-regulator.o obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o obj-$(CONFIG_LEDS_SC27XX_BLTC) += leds-sc27xx-bltc.o obj-$(CONFIG_LEDS_SGM3140) += leds-sgm3140.o +obj-$(CONFIG_LEDS_SUN20I) += leds-sun20i.o obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o obj-$(CONFIG_LEDS_SYSCON) += leds-syscon.o obj-$(CONFIG_LEDS_TCA6507) += leds-tca6507.o diff --git a/drivers/leds/leds-sun20i.c b/drivers/leds/leds-sun20i.c new file mode 100644 index 00000000000000..a0ef49bbba9134 --- /dev/null +++ b/drivers/leds/leds-sun20i.c @@ -0,0 +1,562 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2021 Samuel Holland +// +// Partly based on drivers/leds/leds-turris-omnia.c, which is: +// Copyright (c) 2020 by Marek Behún +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define LEDC_CTRL_REG 0x0000 +#define LEDC_CTRL_REG_DATA_LENGTH (0x1fff << 16) +#define LEDC_CTRL_REG_RGB_MODE (0x7 << 6) +#define LEDC_CTRL_REG_LEDC_EN BIT(0) +#define LEDC_T01_TIMING_CTRL_REG 0x0004 +#define LEDC_T01_TIMING_CTRL_REG_T1H (0x3f << 21) +#define LEDC_T01_TIMING_CTRL_REG_T1L (0x1f << 16) +#define LEDC_T01_TIMING_CTRL_REG_T0H (0x1f << 6) +#define LEDC_T01_TIMING_CTRL_REG_T0L (0x3f << 0) +#define LEDC_RESET_TIMING_CTRL_REG 0x000c +#define LEDC_RESET_TIMING_CTRL_REG_LED_NUM (0x3ff << 0) +#define LEDC_DATA_REG 0x0014 +#define LEDC_DMA_CTRL_REG 0x0018 +#define LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL (0x1f << 0) +#define LEDC_INT_CTRL_REG 0x001c +#define LEDC_INT_CTRL_REG_GLOBAL_INT_EN BIT(5) +#define LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN BIT(1) +#define LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN BIT(0) +#define LEDC_INT_STS_REG 0x0020 +#define LEDC_INT_STS_REG_FIFO_CPUREQ_INT BIT(1) +#define LEDC_INT_STS_REG_TRANS_FINISH_INT BIT(0) + +#define LEDC_FIFO_DEPTH 32 +#define LEDC_MAX_LEDS 1024 + +#define LEDS_TO_BYTES(n) ((n) * sizeof(u32)) + +struct sun20i_ledc_led { + struct led_classdev_mc mc_cdev; + struct mc_subled subled_info[3]; +}; +#define to_ledc_led(mc) container_of(mc, struct sun20i_ledc_led, mc_cdev) + +struct sun20i_ledc_timing { + u32 t0h_ns; + u32 t0l_ns; + u32 t1h_ns; + u32 t1l_ns; + u32 treset_ns; +}; + +struct sun20i_ledc { + struct device *dev; + void __iomem *base; + struct clk *bus_clk; + struct clk *mod_clk; + struct reset_control *reset; + struct regulator *vled; + + u32 *buffer; + struct dma_chan *dma_chan; + dma_addr_t dma_handle; + int pio_length; + int pio_offset; + + spinlock_t lock; + int next_length; + bool xfer_active; + + u32 format; + struct sun20i_ledc_timing timing; + + int num_leds; + struct sun20i_ledc_led leds[]; +}; + +static int sun20i_ledc_dma_xfer(struct sun20i_ledc *priv, int length) +{ + struct dma_async_tx_descriptor *desc; + dma_cookie_t cookie; + + desc = dmaengine_prep_slave_single(priv->dma_chan, priv->dma_handle, + LEDS_TO_BYTES(length), + DMA_MEM_TO_DEV, 0); + if (!desc) + return -ENOMEM; + + cookie = dmaengine_submit(desc); + if (dma_submit_error(cookie)) + return -EIO; + + dma_async_issue_pending(priv->dma_chan); + + return 0; +} + +static void sun20i_ledc_pio_xfer(struct sun20i_ledc *priv, int length) +{ + u32 burst, offset, val; + + if (length) { + /* New transfer (FIFO is empty). */ + offset = 0; + burst = min(length, LEDC_FIFO_DEPTH); + } else { + /* Existing transfer (FIFO is half-full). */ + length = priv->pio_length; + offset = priv->pio_offset; + burst = min(length, LEDC_FIFO_DEPTH / 2); + } + + writesl(priv->base + LEDC_DATA_REG, priv->buffer + offset, burst); + + if (burst < length) { + priv->pio_length = length - burst; + priv->pio_offset = offset + burst; + + if (!offset) { + val = readl(priv->base + LEDC_INT_CTRL_REG); + val |= LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN; + writel(val, priv->base + LEDC_INT_CTRL_REG); + } + } else { + /* Disable the request IRQ once all data is written. */ + val = readl(priv->base + LEDC_INT_CTRL_REG); + val &= ~LEDC_INT_CTRL_REG_FIFO_CPUREQ_INT_EN; + writel(val, priv->base + LEDC_INT_CTRL_REG); + } +} + +static void sun20i_ledc_start_xfer(struct sun20i_ledc *priv, int length) +{ + u32 val; + + dev_dbg(priv->dev, "Updating %d LEDs\n", length); + + val = readl(priv->base + LEDC_CTRL_REG); + val &= ~LEDC_CTRL_REG_DATA_LENGTH; + val |= length << 16 | LEDC_CTRL_REG_LEDC_EN; + writel(val, priv->base + LEDC_CTRL_REG); + + if (length > LEDC_FIFO_DEPTH) { + int ret = sun20i_ledc_dma_xfer(priv, length); + if (!ret) + return; + + dev_warn(priv->dev, "Failed to set up DMA: %d\n", ret); + } + + sun20i_ledc_pio_xfer(priv, length); +} + +static irqreturn_t sun20i_ledc_irq(int irq, void *dev_id) +{ + struct sun20i_ledc *priv = dev_id; + u32 val; + + val = readl(priv->base + LEDC_INT_STS_REG); + + if (val & LEDC_INT_STS_REG_TRANS_FINISH_INT) { + int next_length; + + /* Start the next transfer if needed. */ + spin_lock(&priv->lock); + next_length = priv->next_length; + if (next_length) + priv->next_length = 0; + else + priv->xfer_active = false; + spin_unlock(&priv->lock); + + if (next_length) + sun20i_ledc_start_xfer(priv, next_length); + } else if (val & LEDC_INT_STS_REG_FIFO_CPUREQ_INT) { + /* Continue the current transfer. */ + sun20i_ledc_pio_xfer(priv, 0); + } + + writel(val, priv->base + LEDC_INT_STS_REG); + + return IRQ_HANDLED; +} + +static void sun20i_ledc_brightness_set(struct led_classdev *cdev, + enum led_brightness brightness) +{ + struct sun20i_ledc *priv = dev_get_drvdata(cdev->dev->parent); + struct led_classdev_mc *mc_cdev = lcdev_to_mccdev(cdev); + struct sun20i_ledc_led *led = to_ledc_led(mc_cdev); + int addr = led - priv->leds; + unsigned long flags; + bool xfer_active; + int next_length; + + led_mc_calc_color_components(mc_cdev, brightness); + + priv->buffer[addr] = led->subled_info[0].brightness << 16 | + led->subled_info[1].brightness << 8 | + led->subled_info[2].brightness; + + dev_dbg(priv->dev, "LED %d -> #%06x\n", addr, priv->buffer[addr]); + + spin_lock_irqsave(&priv->lock, flags); + next_length = max(priv->next_length, addr + 1); + xfer_active = priv->xfer_active; + if (xfer_active) { + priv->next_length = next_length; + } else { + priv->xfer_active = true; + } + spin_unlock_irqrestore(&priv->lock, flags); + + if (!xfer_active) + sun20i_ledc_start_xfer(priv, next_length); +} + +static const char *sun20i_ledc_formats[] = { + "rgb", + "rbg", + "grb", + "gbr", + "brg", + "bgr", +}; + +static int sun20i_ledc_parse_format(const struct device_node *np, + struct sun20i_ledc *priv) +{ + const char *format = "grb"; + u32 i; + + of_property_read_string(np, "format", &format); + + for (i = 0; i < ARRAY_SIZE(sun20i_ledc_formats); ++i) { + if (!strcmp(format, sun20i_ledc_formats[i])) { + priv->format = i; + return 0; + } + } + + dev_err(priv->dev, "Bad pixel format '%s'\n", format); + + return -EINVAL; +} + +static void sun20i_ledc_set_format(struct sun20i_ledc *priv) +{ + u32 val; + + val = readl(priv->base + LEDC_CTRL_REG); + val &= ~LEDC_CTRL_REG_RGB_MODE; + val |= priv->format << 6; + writel(val, priv->base + LEDC_CTRL_REG); +} + +static const struct sun20i_ledc_timing sun20i_ledc_default_timing = { + .t0h_ns = 336, + .t0l_ns = 840, + .t1h_ns = 882, + .t1l_ns = 294, + .treset_ns = 300000, +}; + +static int sun20i_ledc_parse_timing(const struct device_node *np, + struct sun20i_ledc *priv) +{ + struct sun20i_ledc_timing *timing = &priv->timing; + + *timing = sun20i_ledc_default_timing; + + of_property_read_u32(np, "t0h-ns", &timing->t0h_ns); + of_property_read_u32(np, "t0l-ns", &timing->t0l_ns); + of_property_read_u32(np, "t1h-ns", &timing->t1h_ns); + of_property_read_u32(np, "t1l-ns", &timing->t1l_ns); + of_property_read_u32(np, "treset-ns", &timing->treset_ns); + + return 0; +} + +static void sun20i_ledc_set_timing(struct sun20i_ledc *priv) +{ + const struct sun20i_ledc_timing *timing = &priv->timing; + unsigned long mod_freq = clk_get_rate(priv->mod_clk); + u32 cycle_ns = NSEC_PER_SEC / mod_freq; + u32 val; + + val = (timing->t1h_ns / cycle_ns) << 21 | + (timing->t1l_ns / cycle_ns) << 16 | + (timing->t0h_ns / cycle_ns) << 6 | + (timing->t0l_ns / cycle_ns); + writel(val, priv->base + LEDC_T01_TIMING_CTRL_REG); + + val = (timing->treset_ns / cycle_ns) << 16 | + (priv->num_leds - 1); + writel(val, priv->base + LEDC_RESET_TIMING_CTRL_REG); +} + +static int sun20i_ledc_resume(struct device *dev) +{ + struct sun20i_ledc *priv = dev_get_drvdata(dev); + u32 val; + int ret; + + ret = regulator_enable(priv->vled); + if (ret) + return ret; + + ret = reset_control_deassert(priv->reset); + if (ret) + goto err_disable_regulator; + + ret = clk_prepare_enable(priv->bus_clk); + if (ret) + goto err_assert_reset; + + ret = clk_prepare_enable(priv->mod_clk); + if (ret) + goto err_disable_bus_clk; + + sun20i_ledc_set_format(priv); + sun20i_ledc_set_timing(priv); + + /* The trigger level must be at least the burst length. */ + val = readl(priv->base + LEDC_DMA_CTRL_REG); + val &= ~LEDC_DMA_CTRL_REG_FIFO_TRIG_LEVEL; + val |= LEDC_FIFO_DEPTH / 2; + writel(val, priv->base + LEDC_DMA_CTRL_REG); + + val = LEDC_INT_CTRL_REG_GLOBAL_INT_EN | + LEDC_INT_CTRL_REG_TRANS_FINISH_INT_EN; + writel(val, priv->base + LEDC_INT_CTRL_REG); + + return 0; + +err_disable_bus_clk: + clk_disable_unprepare(priv->bus_clk); +err_assert_reset: + reset_control_assert(priv->reset); +err_disable_regulator: + regulator_disable(priv->vled); + + return ret; +} + +static int sun20i_ledc_suspend(struct device *dev) +{ + struct sun20i_ledc *priv = dev_get_drvdata(dev); + + clk_disable_unprepare(priv->mod_clk); + clk_disable_unprepare(priv->bus_clk); + reset_control_assert(priv->reset); + regulator_disable(priv->vled); + + return 0; +} + +static void sun20i_ledc_dma_cleanup(void *data) +{ + struct sun20i_ledc *priv = data; + struct device *dma_dev = dmaengine_get_dma_device(priv->dma_chan); + + if (priv->buffer) + dma_free_wc(dma_dev, LEDS_TO_BYTES(priv->num_leds), + priv->buffer, priv->dma_handle); + dma_release_channel(priv->dma_chan); +} + +static int sun20i_ledc_probe(struct platform_device *pdev) +{ + const struct device_node *np = pdev->dev.of_node; + struct dma_slave_config dma_cfg = {}; + struct led_init_data init_data = {}; + struct device *dev = &pdev->dev; + struct device_node *child; + struct sun20i_ledc *priv; + struct resource *mem; + int count, irq, ret; + + count = of_get_available_child_count(np); + if (!count) + return -ENODEV; + if (count > LEDC_MAX_LEDS) { + dev_err(dev, "Too many LEDs! (max is %d)\n", LEDC_MAX_LEDS); + return -EINVAL; + } + + priv = devm_kzalloc(dev, struct_size(priv, leds, count), GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->dev = dev; + priv->num_leds = count; + spin_lock_init(&priv->lock); + dev_set_drvdata(dev, priv); + + ret = sun20i_ledc_parse_format(np, priv); + if (ret) + return ret; + + ret = sun20i_ledc_parse_timing(np, priv); + if (ret) + return ret; + + priv->base = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); + if (IS_ERR(priv->base)) + return PTR_ERR(priv->base); + + priv->bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(priv->bus_clk)) + return PTR_ERR(priv->bus_clk); + + priv->mod_clk = devm_clk_get(dev, "mod"); + if (IS_ERR(priv->mod_clk)) + return PTR_ERR(priv->mod_clk); + + priv->reset = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(priv->reset)) + return PTR_ERR(priv->reset); + + priv->vled = devm_regulator_get(dev, "vled"); + if (IS_ERR(priv->vled)) + return PTR_ERR(priv->vled); + + priv->dma_chan = dma_request_chan(dev, "tx"); + if (IS_ERR(priv->dma_chan)) + return PTR_ERR(priv->dma_chan); + + ret = devm_add_action_or_reset(dev, sun20i_ledc_dma_cleanup, priv); + if (ret) + return ret; + + dma_cfg.dst_addr = mem->start + LEDC_DATA_REG; + dma_cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + dma_cfg.dst_maxburst = LEDC_FIFO_DEPTH / 2; + ret = dmaengine_slave_config(priv->dma_chan, &dma_cfg); + if (ret) + return ret; + + priv->buffer = dma_alloc_wc(dmaengine_get_dma_device(priv->dma_chan), + LEDS_TO_BYTES(priv->num_leds), + &priv->dma_handle, GFP_KERNEL); + if (!priv->buffer) + return -ENOMEM; + + irq = platform_get_irq(pdev, 0); + if (irq < 0) + return irq; + + ret = devm_request_irq(dev, irq, sun20i_ledc_irq, 0, dev_name(dev), priv); + if (ret) + return ret; + + ret = sun20i_ledc_resume(dev); + if (ret) + return ret; + + for_each_available_child_of_node(np, child) { + struct sun20i_ledc_led *led; + struct led_classdev *cdev; + u32 addr, color; + + ret = of_property_read_u32(child, "reg", &addr); + if (ret || addr >= count) { + dev_err(dev, "LED 'reg' values must be from 0 to %d\n", + priv->num_leds - 1); + ret = -EINVAL; + goto err_put_child; + } + + ret = of_property_read_u32(child, "color", &color); + if (ret || color != LED_COLOR_ID_RGB) { + dev_err(dev, "LED 'color' must be LED_COLOR_ID_RGB\n"); + ret = -EINVAL; + goto err_put_child; + } + + led = &priv->leds[addr]; + + led->subled_info[0].color_index = LED_COLOR_ID_RED; + led->subled_info[0].channel = 0; + led->subled_info[1].color_index = LED_COLOR_ID_GREEN; + led->subled_info[1].channel = 1; + led->subled_info[2].color_index = LED_COLOR_ID_BLUE; + led->subled_info[2].channel = 2; + + led->mc_cdev.num_colors = ARRAY_SIZE(led->subled_info); + led->mc_cdev.subled_info = led->subled_info; + + cdev = &led->mc_cdev.led_cdev; + cdev->max_brightness = U8_MAX; + cdev->brightness_set = sun20i_ledc_brightness_set; + + init_data.fwnode = of_fwnode_handle(child); + + ret = devm_led_classdev_multicolor_register_ext(dev, + &led->mc_cdev, + &init_data); + if (ret) { + dev_err(dev, "Failed to register LED %u: %d\n", addr, ret); + goto err_put_child; + } + } + + dev_info(dev, "Registered %d LEDs\n", priv->num_leds); + + return 0; + +err_put_child: + of_node_put(child); + sun20i_ledc_suspend(&pdev->dev); + + return ret; +} + +int sun20i_ledc_remove(struct platform_device *pdev) +{ + sun20i_ledc_suspend(&pdev->dev); + + return 0; +} + +void sun20i_ledc_shutdown(struct platform_device *pdev) +{ + sun20i_ledc_suspend(&pdev->dev); +} + +static const struct of_device_id sun20i_ledc_of_match[] = { + { .compatible = "allwinner,sun20i-d1-ledc" }, + {} +}; +MODULE_DEVICE_TABLE(of, sun20i_ledc_of_match); + +SIMPLE_DEV_PM_OPS(sun20i_ledc_pm, sun20i_ledc_suspend, sun20i_ledc_resume); + +static struct platform_driver sun20i_ledc_driver = { + .probe = sun20i_ledc_probe, + .remove = sun20i_ledc_remove, + .shutdown = sun20i_ledc_shutdown, + .driver = { + .name = "sun20i-ledc", + .of_match_table = sun20i_ledc_of_match, + .pm = pm_ptr(&sun20i_ledc_pm), + }, +}; +module_platform_driver(sun20i_ledc_driver); + +MODULE_AUTHOR("Samuel Holland "); +MODULE_DESCRIPTION("Allwinner sun20i LED controller driver"); +MODULE_LICENSE("GPL"); From 1ad05bafb26f365af5b1df29bdef502e90b645c9 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 17 May 2021 00:00:52 -0500 Subject: [PATCH 052/120] [STUB] mailbox: Add v2 mailbox --- .../mailbox/allwinner,sun20i-d1-msgbox.yaml | 70 +++++++++++++++++++ drivers/mailbox/Kconfig | 13 +++- .../dt-bindings/mailbox/sun20i-d1-msgbox.h | 18 +++++ 3 files changed, 99 insertions(+), 2 deletions(-) create mode 100644 Documentation/devicetree/bindings/mailbox/allwinner,sun20i-d1-msgbox.yaml create mode 100644 include/dt-bindings/mailbox/sun20i-d1-msgbox.h diff --git a/Documentation/devicetree/bindings/mailbox/allwinner,sun20i-d1-msgbox.yaml b/Documentation/devicetree/bindings/mailbox/allwinner,sun20i-d1-msgbox.yaml new file mode 100644 index 00000000000000..d61237dbbd33c3 --- /dev/null +++ b/Documentation/devicetree/bindings/mailbox/allwinner,sun20i-d1-msgbox.yaml @@ -0,0 +1,70 @@ +# SPDX-License-Identifier: GPL-2.0 +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/mailbox/allwinner,sun20i-d1-msgbox.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Allwinner sunxi Message Box v2 + +maintainers: + - Samuel Holland + +properties: + compatible: + oneOf: + - const: allwinner,sun20i-d1-msgbox + + reg: + maxItems: 1 + + clocks: + maxItems: 1 + description: bus clock + + resets: + maxItems: 1 + description: bus reset + + interrupts: + items: + - description: receive interrupt + - description: transmit interrupt + + interrupt-names: + items: + - const: "rx" + - const: "tx" + + '#mbox-cells': + const: 2 + description: first cell is the user/channel number, second is direction + +required: + - compatible + - reg + - clocks + - resets + - interrupts + - interrupt-names + - '#mbox-cells' + +additionalProperties: false + +examples: + - | + #include + #include + #include + + msgbox: mailbox@3003000 { + compatible = "allwinner,sun20i-d1-msgbox"; + reg = <0x3003000 0x1000>; + clocks = <&ccu CLK_BUS_MSGBOX0>; + resets = <&ccu RST_BUS_MSGBOX0>; + interrupts = <101 IRQ_TYPE_LEVEL_HIGH>, + <102 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "rx", "tx"; + #mbox-cells = <2>; + }; + +... diff --git a/drivers/mailbox/Kconfig b/drivers/mailbox/Kconfig index b4b780ea2ac8cc..0a5b292428f309 100644 --- a/drivers/mailbox/Kconfig +++ b/drivers/mailbox/Kconfig @@ -247,13 +247,22 @@ config ZYNQMP_IPI_MBOX registers to kick the other processor or enquire status. config SUN6I_MSGBOX - tristate "Allwinner sun6i/sun8i/sun9i/sun50i Message Box" + tristate "Allwinner sun6i/sun8i/sun9i/sun50i ARISC Message Box" depends on ARCH_SUNXI || COMPILE_TEST default ARCH_SUNXI help Mailbox implementation for the hardware message box present in various Allwinner SoCs. This mailbox is used for communication - between the application CPUs and the power management coprocessor. + between the ARM CPUs and the ARISC power management coprocessor. + +config SUN8I_MSGBOX + tristate "Allwinner sun8i/sun20i/sun50i DSP/RISC-V Message Box" + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST + default ARCH_SUNXI || SOC_SUNXI + help + Mailbox implementation for the hardware message box present in + various Allwinner SoCs. This mailbox is used for communication + between the ARM/RISC-V CPUs and the integrated DSP. config SPRD_MBOX tristate "Spreadtrum Mailbox" diff --git a/include/dt-bindings/mailbox/sun20i-d1-msgbox.h b/include/dt-bindings/mailbox/sun20i-d1-msgbox.h new file mode 100644 index 00000000000000..2f149f6d59f366 --- /dev/null +++ b/include/dt-bindings/mailbox/sun20i-d1-msgbox.h @@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * This header provides constants for binding nvidia,tegra186-hsp. + */ + +#ifndef _DT_BINDINGS_MAILBOX_SUN20I_D1_MSGBOX_H_ +#define _DT_BINDINGS_MAILBOX_SUN20I_D1_MSGBOX_H_ + +/* First cell: channel (transmitting user) */ +#define MBOX_USER_CPUX 0 +#define MBOX_USER_DSP 1 +#define MBOX_USER_RISCV 2 + +/* Second cell: direction (RX if phandle references local mailbox, else TX) */ +#define MBOX_RX 0 +#define MBOX_TX 1 + +#endif /* _DT_BINDINGS_MAILBOX_SUN20I_D1_MSGBOX_H_ */ From 96ee3f83612883dc767ce5ce24ca4a584e15cb1a Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:52:53 -0500 Subject: [PATCH 053/120] dt-bindings: media: Add compatible for D1 video engine Signed-off-by: Samuel Holland --- .../bindings/media/allwinner,sun4i-a10-video-engine.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml index c34303b87a5be8..c3de96d10396a7 100644 --- a/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml +++ b/Documentation/devicetree/bindings/media/allwinner,sun4i-a10-video-engine.yaml @@ -20,6 +20,7 @@ properties: - allwinner,sun8i-h3-video-engine - allwinner,sun8i-v3s-video-engine - allwinner,sun8i-r40-video-engine + - allwinner,sun20i-d1-video-engine - allwinner,sun50i-a64-video-engine - allwinner,sun50i-h5-video-engine - allwinner,sun50i-h6-video-engine From d867a5ce568dc749b6a99fdc9c0d3f370c8937e3 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:47:22 -0500 Subject: [PATCH 054/120] media: cedrus: Add D1 variant Signed-off-by: Samuel Holland --- drivers/staging/media/sunxi/cedrus/cedrus.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c index c0d005dafc6c04..98c66431b232e8 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus.c @@ -527,6 +527,14 @@ static const struct cedrus_variant sun8i_r40_cedrus_variant = { .mod_rate = 297000000, }; +static const struct cedrus_variant sun20i_d1_cedrus_variant = { + .capabilities = CEDRUS_CAPABILITY_UNTILED | + CEDRUS_CAPABILITY_MPEG2_DEC | + CEDRUS_CAPABILITY_H264_DEC | + CEDRUS_CAPABILITY_H265_DEC, + .mod_rate = 432000000, +}; + static const struct cedrus_variant sun50i_a64_cedrus_variant = { .capabilities = CEDRUS_CAPABILITY_UNTILED | CEDRUS_CAPABILITY_MPEG2_DEC | @@ -583,6 +591,10 @@ static const struct of_device_id cedrus_dt_match[] = { .compatible = "allwinner,sun8i-r40-video-engine", .data = &sun8i_r40_cedrus_variant, }, + { + .compatible = "allwinner,sun20i-d1-video-engine", + .data = &sun20i_d1_cedrus_variant, + }, { .compatible = "allwinner,sun50i-a64-video-engine", .data = &sun50i_a64_cedrus_variant, From 982b375479c63f50d7bec7ae02d035814aee32c0 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:18:44 -0500 Subject: [PATCH 055/120] dt-bindings: mmc: sunxi: Add D1 MMC and eMMC compatibles Signed-off-by: Samuel Holland --- .../devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml index 4f62ad6ce50c7f..94e2c6c4e4b764 100644 --- a/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml +++ b/Documentation/devicetree/bindings/mmc/allwinner,sun4i-a10-mmc.yaml @@ -24,6 +24,7 @@ properties: - const: allwinner,sun7i-a20-mmc - const: allwinner,sun8i-a83t-emmc - const: allwinner,sun9i-a80-mmc + - const: allwinner,sun20i-d1-mmc - const: allwinner,sun50i-a64-emmc - const: allwinner,sun50i-a64-mmc - const: allwinner,sun50i-a100-emmc @@ -49,6 +50,9 @@ properties: - items: - const: allwinner,sun50i-h6-mmc - const: allwinner,sun50i-a64-mmc + - items: + - const: allwinner,sun20i-d1-emmc + - const: allwinner,sun50i-a100-emmc - items: - const: allwinner,sun50i-h616-emmc - const: allwinner,sun50i-a100-emmc From 09b0cf6810d81787d1483aeae36823b2351fac8e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:15:56 -0500 Subject: [PATCH 056/120] mmc: sunxi-mmc: Correct the maximum transfer size Signed-off-by: Samuel Holland --- drivers/mmc/host/sunxi-mmc.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 2702736a1c57de..4e0d593dbbe7af 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -214,6 +214,9 @@ #define SDXC_IDMAC_DES0_CES BIT(30) /* card error summary */ #define SDXC_IDMAC_DES0_OWN BIT(31) /* 1-idma owns it, 0-host owns it */ +/* Buffer size must be a multiple of 4 bytes. */ +#define SDXC_IDMAC_DES1_ALIGN 4 + #define SDXC_CLK_400K 0 #define SDXC_CLK_25M 1 #define SDXC_CLK_50M 2 @@ -361,17 +364,16 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, { struct sunxi_idma_des *pdes = (struct sunxi_idma_des *)host->sg_cpu; dma_addr_t next_desc = host->sg_dma; - int i, max_len = (1 << host->cfg->idma_des_size_bits); + int i; for (i = 0; i < data->sg_len; i++) { pdes[i].config = cpu_to_le32(SDXC_IDMAC_DES0_CH | SDXC_IDMAC_DES0_OWN | SDXC_IDMAC_DES0_DIC); - if (data->sg[i].length == max_len) - pdes[i].buf_size = 0; /* 0 == max_len */ - else - pdes[i].buf_size = cpu_to_le32(data->sg[i].length); + pdes[i].buf_size = + cpu_to_le32(ALIGN(data->sg[i].length, + SDXC_IDMAC_DES1_ALIGN)); next_desc += sizeof(struct sunxi_idma_des); pdes[i].buf_addr_ptr1 = @@ -1411,7 +1413,8 @@ static int sunxi_mmc_probe(struct platform_device *pdev) mmc->max_blk_count = 8192; mmc->max_blk_size = 4096; mmc->max_segs = PAGE_SIZE / sizeof(struct sunxi_idma_des); - mmc->max_seg_size = (1 << host->cfg->idma_des_size_bits); + mmc->max_seg_size = (1 << host->cfg->idma_des_size_bits) - + SDXC_IDMAC_DES1_ALIGN; mmc->max_req_size = mmc->max_seg_size * mmc->max_segs; /* 400kHz ~ 52MHz */ mmc->f_min = 400000; From b8630c819a18ab2fb3efaad9724cf85d1b48541b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:16:30 -0500 Subject: [PATCH 057/120] mmc: sunxi-mmc: Fix DMA descriptors above 32 bits Signed-off-by: Samuel Holland --- drivers/mmc/host/sunxi-mmc.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index 4e0d593dbbe7af..d99aba9d730478 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -379,8 +379,9 @@ static void sunxi_mmc_init_idma_des(struct sunxi_mmc_host *host, pdes[i].buf_addr_ptr1 = cpu_to_le32(sg_dma_address(&data->sg[i]) >> host->cfg->idma_des_shift); - pdes[i].buf_addr_ptr2 = cpu_to_le32((u32)next_desc >> - host->cfg->idma_des_shift); + pdes[i].buf_addr_ptr2 = + cpu_to_le32(next_desc >> + host->cfg->idma_des_shift); } pdes[0].config |= cpu_to_le32(SDXC_IDMAC_DES0_FD); From d65ada58e59171bc937efa2c2cc550207841ef12 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:16:55 -0500 Subject: [PATCH 058/120] mmc: sunxi-mmc: Add D1 MMC compatible Signed-off-by: Samuel Holland --- drivers/mmc/host/sunxi-mmc.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index d99aba9d730478..cde3e8dbc94b83 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -1170,6 +1170,14 @@ static const struct sunxi_mmc_cfg sun9i_a80_cfg = { .can_calibrate = false, }; +static const struct sunxi_mmc_cfg sun20i_d1_cfg = { + .idma_des_size_bits = 13, + .idma_des_shift = 2, + .can_calibrate = true, + .mask_data0 = true, + .needs_new_timings = true, +}; + static const struct sunxi_mmc_cfg sun50i_a64_cfg = { .idma_des_size_bits = 16, .clk_delays = NULL, @@ -1208,6 +1216,7 @@ static const struct of_device_id sunxi_mmc_of_match[] = { { .compatible = "allwinner,sun7i-a20-mmc", .data = &sun7i_a20_cfg }, { .compatible = "allwinner,sun8i-a83t-emmc", .data = &sun8i_a83t_emmc_cfg }, { .compatible = "allwinner,sun9i-a80-mmc", .data = &sun9i_a80_cfg }, + { .compatible = "allwinner,sun20i-d1-mmc", .data = &sun20i_d1_cfg }, { .compatible = "allwinner,sun50i-a64-mmc", .data = &sun50i_a64_cfg }, { .compatible = "allwinner,sun50i-a64-emmc", .data = &sun50i_a64_emmc_cfg }, { .compatible = "allwinner,sun50i-a100-mmc", .data = &sun50i_a100_cfg }, From 0e0069899e263d77a2ed96becda13fb662796829 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:40:49 -0500 Subject: [PATCH 059/120] mmc: sunxi-mmc: Add more registers Signed-off-by: Samuel Holland --- drivers/mmc/host/sunxi-mmc.c | 55 ++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 12 deletions(-) diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index cde3e8dbc94b83..e6a21bcc3b475e 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -54,25 +54,56 @@ #define SDXC_REG_MISTA (0x34) /* SMC Masked Interrupt Status Register */ #define SDXC_REG_RINTR (0x38) /* SMC Raw Interrupt Status Register */ #define SDXC_REG_STAS (0x3C) /* SMC Status Register */ -#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Registe */ +#define SDXC_REG_FTRGL (0x40) /* SMC FIFO Threshold Watermark Register */ #define SDXC_REG_FUNS (0x44) /* SMC Function Select Register */ #define SDXC_REG_CBCR (0x48) /* SMC CIU Byte Count Register */ #define SDXC_REG_BBCR (0x4C) /* SMC BIU Byte Count Register */ #define SDXC_REG_DBGC (0x50) /* SMC Debug Enable Register */ -#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset for Register */ +#define SDXC_REG_HWRST (0x78) /* SMC Card Hardware Reset Register */ #define SDXC_REG_DMAC (0x80) /* SMC IDMAC Control Register */ -#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Addre */ +#define SDXC_REG_DLBA (0x84) /* SMC IDMAC Descriptor List Base Address */ #define SDXC_REG_IDST (0x88) /* SMC IDMAC Status Register */ #define SDXC_REG_IDIE (0x8C) /* SMC IDMAC Interrupt Enable Register */ -#define SDXC_REG_CHDA (0x90) -#define SDXC_REG_CBDA (0x94) +#define SDXC_REG_CHDA (0x90) /* Current Host Descriptor Address */ +#define SDXC_REG_CBDA (0x94) /* Current Buffer Descriptor Address */ + +/* New registers introduced in A80 */ +#define SDXC_REG_A12A 0x058 /* Auto Command 12 Register */ +#define SDXC_REG_THLD 0x100 /* Card Threshold Control Register */ +#define SDXC_REG_DSBD 0x10C /* eMMC 4.5 DDR Start Bit Detection */ + +/* New registers introduced in A83T */ +#define SDXC_REG_NTSR 0x05C /* New Timing Set Register */ +#define SDXC_REG_SDBG 0x060 /* New Timing Set Debug Register */ + +/* New registers introduced in H3 */ +#define SDXC_REG_RES_CRC 0x110 /* CRC Response from Card/eMMC */ +#define SDXC_REG_D7_CRC 0x114 /* CRC Data 7 from Card/eMMC */ +#define SDXC_REG_D6_CRC 0x118 /* CRC Data 6 from Card/eMMC */ +#define SDXC_REG_D5_CRC 0x11C /* CRC Data 5 from Card/eMMC */ +#define SDXC_REG_D4_CRC 0x120 /* CRC Data 4 from Card/eMMC */ +#define SDXC_REG_D3_CRC 0x124 /* CRC Data 3 from Card/eMMC */ +#define SDXC_REG_D2_CRC 0x128 /* CRC Data 2 from Card/eMMC */ +#define SDXC_REG_D1_CRC 0x12C /* CRC Data 1 from Card/eMMC */ +#define SDXC_REG_D0_CRC 0x130 /* CRC Data 0 from Card/eMMC */ +#define SDXC_REG_CRC_STA 0x134 /* CRC Status from Write Operation */ /* New registers introduced in A64 */ -#define SDXC_REG_A12A 0x058 /* SMC Auto Command 12 Register */ -#define SDXC_REG_SD_NTSR 0x05C /* SMC New Timing Set Register */ +#define SDXC_REG_CSDC 0x054 /* CRC Status Detect Register */ #define SDXC_REG_DRV_DL 0x140 /* Drive Delay Control Register */ -#define SDXC_REG_SAMP_DL_REG 0x144 /* SMC sample delay control */ -#define SDXC_REG_DS_DL_REG 0x148 /* SMC data strobe delay control */ +#define SDXC_REG_SAMP_DL 0x144 /* Sample Delay Control Register */ +#define SDXC_REG_DS_DL 0x148 /* Data Strobe Delay Control Register */ + +/* New registers introduced in H6 */ +#define SDXC_REG_EMCE 0x064 /* Embedded Encrypt/Decrypt Control */ +#define SDXC_REG_EMCE_DBG 0x068 /* Embedded Encrypt/Decrypt Debug */ + +/* New registers introduced in H616 */ +#define SDXC_REG_EXT_CMD 0x138 /* Extended Command Register */ +#define SDXC_REG_EXT_RESP 0x13C /* Extended Response Register */ + +/* New registers introduced in A100 */ +#define SDXC_REG_HS400_DL 0x14C /* HS400 Delay Control Register */ #define mmc_readl(host, reg) \ readl((host)->reg_base + SDXC_##reg) @@ -836,9 +867,9 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, */ if (host->use_new_timings) { /* Don't touch the delay bits */ - rval = mmc_readl(host, REG_SD_NTSR); + rval = mmc_readl(host, REG_NTSR); rval |= SDXC_2X_TIMING_MODE; - mmc_writel(host, REG_SD_NTSR, rval); + mmc_writel(host, REG_NTSR, rval); } /* sunxi_mmc_clk_set_phase expects the actual card clock rate */ @@ -846,7 +877,7 @@ static int sunxi_mmc_clk_set_rate(struct sunxi_mmc_host *host, if (ret) return ret; - ret = sunxi_mmc_calibrate(host, SDXC_REG_SAMP_DL_REG); + ret = sunxi_mmc_calibrate(host, SDXC_REG_SAMP_DL); if (ret) return ret; From d4c8de15d55e44a6138f22c929983c2a35d6fe95 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:42:55 -0500 Subject: [PATCH 060/120] net: stmmac: dwmac-sun8i: Add D1 variant Signed-off-by: Samuel Holland --- drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 4422baeed3d89b..576167fa4b8354 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -1326,6 +1326,8 @@ static const struct of_device_id sun8i_dwmac_match[] = { .data = &emac_variant_a83t }, { .compatible = "allwinner,sun8i-r40-gmac", .data = &emac_variant_r40 }, + { .compatible = "allwinner,sun20i-d1-emac", + .data = &emac_variant_a64 }, { .compatible = "allwinner,sun50i-a64-emac", .data = &emac_variant_a64 }, { .compatible = "allwinner,sun50i-h6-emac", From 56df1caf9c5b03cbb1183570443478b1fa5b5e43 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:43:20 -0500 Subject: [PATCH 061/120] nvmem: sunxi_sid: Add D1 variant Signed-off-by: Samuel Holland --- drivers/nvmem/sunxi_sid.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/nvmem/sunxi_sid.c b/drivers/nvmem/sunxi_sid.c index 275b9155e47330..5750e1f4bcdbbf 100644 --- a/drivers/nvmem/sunxi_sid.c +++ b/drivers/nvmem/sunxi_sid.c @@ -184,6 +184,11 @@ static const struct sunxi_sid_cfg sun8i_h3_cfg = { .need_register_readout = true, }; +static const struct sunxi_sid_cfg sun20i_d1_cfg = { + .value_offset = 0x200, + .size = 0x100, +}; + static const struct sunxi_sid_cfg sun50i_a64_cfg = { .value_offset = 0x200, .size = 0x100, @@ -200,6 +205,7 @@ static const struct of_device_id sunxi_sid_of_match[] = { { .compatible = "allwinner,sun7i-a20-sid", .data = &sun7i_a20_cfg }, { .compatible = "allwinner,sun8i-a83t-sid", .data = &sun50i_a64_cfg }, { .compatible = "allwinner,sun8i-h3-sid", .data = &sun8i_h3_cfg }, + { .compatible = "allwinner,sun20i-d1-sid", .data = &sun20i_d1_cfg }, { .compatible = "allwinner,sun50i-a64-sid", .data = &sun50i_a64_cfg }, { .compatible = "allwinner,sun50i-h5-sid", .data = &sun50i_a64_cfg }, { .compatible = "allwinner,sun50i-h6-sid", .data = &sun50i_h6_cfg }, From 9c8d03140a23450fc74eadf05f28393a4186253c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:43:58 -0500 Subject: [PATCH 062/120] of/irq: Use interrupts-extended to find parent Signed-off-by: Samuel Holland --- drivers/of/irq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/of/irq.c b/drivers/of/irq.c index 352e14b007e784..d84d27fb22038d 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -60,7 +60,8 @@ struct device_node *of_irq_find_parent(struct device_node *child) return NULL; do { - if (of_property_read_u32(child, "interrupt-parent", &parent)) { + if (of_property_read_u32(child, "interrupt-parent", &parent) && + of_property_read_u32(child, "interrupts-extended", &parent)) { p = of_get_parent(child); } else { if (of_irq_workarounds & OF_IMAP_NO_PHANDLE) From 41eb2764a48c7587d29fc2c2611542461d4275e3 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 15 Jun 2021 12:06:29 +0100 Subject: [PATCH 063/120] phy: sun4i-usb: Rework HCI PHY (aka. "pmu_unk1") handling As Icenowy pointed out, newer manuals (starting with H6) actually document the register block at offset 0x800 as "HCI controller and PHY interface", also describe the bits in our "PMU_UNK1" register. Let's put proper names to those "unknown" variables and symbols. While we are at it, generalise the existing code by allowing a bitmap of bits to clear and set, to cover newer SoCs: The A100 and H616 use a different bit for the SIDDQ control. Signed-off-by: Andre Przywara --- drivers/phy/allwinner/phy-sun4i-usb.c | 30 ++++++++++++--------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 788dd5cdbb7d3e..142f4cafdc7802 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -43,7 +43,7 @@ #define REG_PHYCTL_A33 0x10 #define REG_PHY_OTGCTL 0x20 -#define REG_PMU_UNK1 0x10 +#define REG_HCI_PHY_CTL 0x10 #define PHYCTL_DATA BIT(7) @@ -82,6 +82,7 @@ /* A83T specific control bits for PHY0 */ #define PHY_CTL_VBUSVLDEXT BIT(5) #define PHY_CTL_SIDDQ BIT(3) +#define PHY_CTL_H3_SIDDQ BIT(1) /* A83T specific control bits for PHY2 HSIC */ #define SUNXI_EHCI_HS_FORCE BIT(20) @@ -115,9 +116,9 @@ struct sun4i_usb_phy_cfg { int hsic_index; enum sun4i_usb_phy_type type; u32 disc_thresh; + u32 hci_phy_ctl_clear; u8 phyctl_offset; bool dedicated_clocks; - bool enable_pmu_unk1; bool phy0_dual_route; int missing_phys; }; @@ -288,6 +289,12 @@ static int sun4i_usb_phy_init(struct phy *_phy) return ret; } + if (phy->pmu && data->cfg->hci_phy_ctl_clear) { + val = readl(phy->pmu + REG_HCI_PHY_CTL); + val &= ~data->cfg->hci_phy_ctl_clear; + writel(val, phy->pmu + REG_HCI_PHY_CTL); + } + if (data->cfg->type == sun8i_a83t_phy || data->cfg->type == sun50i_h6_phy) { if (phy->index == 0) { @@ -297,11 +304,6 @@ static int sun4i_usb_phy_init(struct phy *_phy) writel(val, data->base + data->cfg->phyctl_offset); } } else { - if (phy->pmu && data->cfg->enable_pmu_unk1) { - val = readl(phy->pmu + REG_PMU_UNK1); - writel(val & ~2, phy->pmu + REG_PMU_UNK1); - } - /* Enable USB 45 Ohm resistor calibration */ if (phy->index == 0) sun4i_usb_phy_write(phy, PHY_RES45_CAL_EN, 0x01, 1); @@ -863,7 +865,6 @@ static const struct sun4i_usb_phy_cfg sun4i_a10_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { @@ -872,7 +873,6 @@ static const struct sun4i_usb_phy_cfg sun5i_a13_cfg = { .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { @@ -881,7 +881,6 @@ static const struct sun4i_usb_phy_cfg sun6i_a31_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { @@ -890,7 +889,6 @@ static const struct sun4i_usb_phy_cfg sun7i_a20_cfg = { .disc_thresh = 2, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = false, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { @@ -899,7 +897,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a23_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A10, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { @@ -908,7 +905,6 @@ static const struct sun4i_usb_phy_cfg sun8i_a33_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = false, }; static const struct sun4i_usb_phy_cfg sun8i_a83t_cfg = { @@ -925,7 +921,7 @@ static const struct sun4i_usb_phy_cfg sun8i_h3_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -935,7 +931,7 @@ static const struct sun4i_usb_phy_cfg sun8i_r40_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -945,7 +941,7 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; @@ -955,7 +951,7 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, - .enable_pmu_unk1 = true, + .hci_phy_ctl_clear = PHY_CTL_H3_SIDDQ, .phy0_dual_route = true, }; From 4826f27027d381f7f0286d2ec68f9789fc3f92fd Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 23 Jun 2021 22:14:15 -0500 Subject: [PATCH 064/120] phy: sun4i-usb: Remove disc_thresh where not applicable Signed-off-by: Samuel Holland --- drivers/phy/allwinner/phy-sun4i-usb.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 142f4cafdc7802..6675dad174154f 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -958,7 +958,6 @@ static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { static const struct sun4i_usb_phy_cfg sun50i_h6_cfg = { .num_phys = 4, .type = sun50i_h6_phy, - .disc_thresh = 3, .phyctl_offset = REG_PHYCTL_A33, .dedicated_clocks = true, .phy0_dual_route = true, From ba22d6110ba2727e7bc54453b2c4ef4f2642ce3c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:45:25 -0500 Subject: [PATCH 065/120] phy: sun4i-usb: Add D1 variant Signed-off-by: Samuel Holland --- drivers/phy/allwinner/phy-sun4i-usb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/phy/allwinner/phy-sun4i-usb.c b/drivers/phy/allwinner/phy-sun4i-usb.c index 6675dad174154f..021335c91661ce 100644 --- a/drivers/phy/allwinner/phy-sun4i-usb.c +++ b/drivers/phy/allwinner/phy-sun4i-usb.c @@ -945,6 +945,15 @@ static const struct sun4i_usb_phy_cfg sun8i_v3s_cfg = { .phy0_dual_route = true, }; +static const struct sun4i_usb_phy_cfg sun20i_d1_cfg = { + .num_phys = 2, + .type = sun50i_h6_phy, + .phyctl_offset = REG_PHYCTL_A33, + .dedicated_clocks = true, + .hci_phy_ctl_clear = PHY_CTL_SIDDQ, + .phy0_dual_route = true, +}; + static const struct sun4i_usb_phy_cfg sun50i_a64_cfg = { .num_phys = 2, .type = sun50i_a64_phy, @@ -975,8 +984,8 @@ static const struct of_device_id sun4i_usb_phy_of_match[] = { { .compatible = "allwinner,sun8i-h3-usb-phy", .data = &sun8i_h3_cfg }, { .compatible = "allwinner,sun8i-r40-usb-phy", .data = &sun8i_r40_cfg }, { .compatible = "allwinner,sun8i-v3s-usb-phy", .data = &sun8i_v3s_cfg }, - { .compatible = "allwinner,sun50i-a64-usb-phy", - .data = &sun50i_a64_cfg}, + { .compatible = "allwinner,sun20i-d1-usb-phy", .data = &sun20i_d1_cfg }, + { .compatible = "allwinner,sun50i-a64-usb-phy", .data = &sun50i_a64_cfg }, { .compatible = "allwinner,sun50i-h6-usb-phy", .data = &sun50i_h6_cfg }, { }, }; From de2b24581281168406bacf98147eded7dee9f06c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:53:42 -0500 Subject: [PATCH 066/120] dt-bindings: pinctrl: Add compatible for Allwinner D1 Signed-off-by: Samuel Holland --- .../pinctrl/allwinner,sun4i-a10-pinctrl.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml index cce63c3cc46309..5d999471064505 100644 --- a/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml +++ b/Documentation/devicetree/bindings/pinctrl/allwinner,sun4i-a10-pinctrl.yaml @@ -46,6 +46,7 @@ properties: - allwinner,sun8i-v3s-pinctrl - allwinner,sun9i-a80-pinctrl - allwinner,sun9i-a80-r-pinctrl + - allwinner,sun20i-d1-pinctrl - allwinner,sun50i-a64-pinctrl - allwinner,sun50i-a64-r-pinctrl - allwinner,sun50i-a100-pinctrl @@ -170,6 +171,18 @@ allOf: minItems: 7 maxItems: 7 + - if: + properties: + compatible: + enum: + - allwinner,sun20i-d1-pinctrl + + then: + properties: + interrupts: + minItems: 6 + maxItems: 6 + - if: properties: compatible: From 3bd5882004d17381ff3b224b8188deb4f866b81c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 19:56:23 -0500 Subject: [PATCH 067/120] pinctrl: sunxi: Support new 2.5V I/O bias mode Signed-off-by: Samuel Holland --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 11 +++++++++++ drivers/pinctrl/sunxi/pinctrl-sunxi.h | 7 +++++++ 2 files changed, 18 insertions(+) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index dc8d39ae045b22..c0b80cdf241134 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -654,6 +654,16 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl, reg &= ~IO_BIAS_MASK; writel(reg | val, pctl->membase + sunxi_grp_config_reg(pin)); return 0; + case BIAS_VOLTAGE_PIO_POW_MODE_CTL: + val = 1800000 < uV && uV <= 2500000 ? BIT(bank) : 0; + + raw_spin_lock_irqsave(&pctl->lock, flags); + reg = readl(pctl->membase + PIO_POW_MOD_CTL_REG); + reg &= ~BIT(bank); + writel(reg | val, pctl->membase + PIO_POW_MOD_CTL_REG); + raw_spin_unlock_irqrestore(&pctl->lock, flags); + + fallthrough; case BIAS_VOLTAGE_PIO_POW_MODE_SEL: val = uV <= 1800000 ? 1 : 0; @@ -662,6 +672,7 @@ static int sunxi_pinctrl_set_io_bias_cfg(struct sunxi_pinctrl *pctl, reg &= ~(1 << bank); writel(reg | val << bank, pctl->membase + PIO_POW_MOD_SEL_REG); raw_spin_unlock_irqrestore(&pctl->lock, flags); + return 0; default: return -EINVAL; diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index a32bb5bcb75476..0f1aab58650c7f 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h @@ -98,6 +98,7 @@ #define PINCTRL_SUN8I_V3S BIT(10) #define PIO_POW_MOD_SEL_REG 0x340 +#define PIO_POW_MOD_CTL_REG 0x344 enum sunxi_desc_bias_voltage { BIAS_VOLTAGE_NONE, @@ -111,6 +112,12 @@ enum sunxi_desc_bias_voltage { * register, as seen on H6 SoC, for example. */ BIAS_VOLTAGE_PIO_POW_MODE_SEL, + /* + * Bias voltage is set through PIO_POW_MOD_SEL_REG + * and PIO_POW_MOD_CTL_REG register, as seen on + * A100 and D1 SoC, for example. + */ + BIAS_VOLTAGE_PIO_POW_MODE_CTL, }; struct sunxi_desc_function { From b44da171242553a703faa3e1d17870eb0b373dc4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:06:19 -0500 Subject: [PATCH 068/120] [HACK] pinctrl: sunxi: Adapt for D1 register layout Signed-off-by: Samuel Holland --- drivers/pinctrl/sunxi/pinctrl-sunxi.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.h b/drivers/pinctrl/sunxi/pinctrl-sunxi.h index 0f1aab58650c7f..8ebba0ab5f696b 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.h +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.h @@ -34,11 +34,11 @@ #define SUNXI_PIN_NAME_MAX_LEN 5 -#define BANK_MEM_SIZE 0x24 +#define BANK_MEM_SIZE 0x30 #define MUX_REGS_OFFSET 0x0 #define DATA_REGS_OFFSET 0x10 #define DLEVEL_REGS_OFFSET 0x14 -#define PULL_REGS_OFFSET 0x1c +#define PULL_REGS_OFFSET 0x24 #define PINS_PER_BANK 32 #define MUX_PINS_PER_REG 8 @@ -47,8 +47,8 @@ #define DATA_PINS_PER_REG 32 #define DATA_PINS_BITS 1 #define DATA_PINS_MASK 0x01 -#define DLEVEL_PINS_PER_REG 16 -#define DLEVEL_PINS_BITS 2 +#define DLEVEL_PINS_PER_REG 8 +#define DLEVEL_PINS_BITS 4 #define DLEVEL_PINS_MASK 0x03 #define PULL_PINS_PER_REG 16 #define PULL_PINS_BITS 2 @@ -84,7 +84,7 @@ #define IO_BIAS_MASK GENMASK(3, 0) #define SUN4I_FUNC_INPUT 0 -#define SUN4I_FUNC_IRQ 6 +#define SUN4I_FUNC_IRQ 0xe #define PINCTRL_SUN5I_A10S BIT(1) #define PINCTRL_SUN5I_A13 BIT(2) From 1d8979090e4bfb6d8b37c18db604f886e293bf70 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:13:04 -0500 Subject: [PATCH 069/120] pinctrl: sunxi: Add support for Allwinner D1 SoC Signed-off-by: Samuel Holland --- drivers/pinctrl/sunxi/Kconfig | 7 +- drivers/pinctrl/sunxi/Makefile | 1 + drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c | 836 ++++++++++++++++++++++ 3 files changed, 843 insertions(+), 1 deletion(-) create mode 100644 drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c diff --git a/drivers/pinctrl/sunxi/Kconfig b/drivers/pinctrl/sunxi/Kconfig index 33751a6a075728..395ee316be6a44 100644 --- a/drivers/pinctrl/sunxi/Kconfig +++ b/drivers/pinctrl/sunxi/Kconfig @@ -1,5 +1,5 @@ # SPDX-License-Identifier: GPL-2.0-only -if ARCH_SUNXI +if ARCH_SUNXI || SOC_SUNXI config PINCTRL_SUNXI bool @@ -84,6 +84,11 @@ config PINCTRL_SUN9I_A80_R depends on RESET_CONTROLLER select PINCTRL_SUNXI +config PINCTRL_SUN20I_D1 + bool "Support for the Allwinner D1 PIO" + default RISCV && SOC_SUNXI + select PINCTRL_SUNXI + config PINCTRL_SUN50I_A64 bool "Support for the Allwinner A64 PIO" default ARM64 && ARCH_SUNXI diff --git a/drivers/pinctrl/sunxi/Makefile b/drivers/pinctrl/sunxi/Makefile index d3440c42b9d626..2ff5a55927ad62 100644 --- a/drivers/pinctrl/sunxi/Makefile +++ b/drivers/pinctrl/sunxi/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_PINCTRL_SUN8I_A83T_R) += pinctrl-sun8i-a83t-r.o obj-$(CONFIG_PINCTRL_SUN8I_H3) += pinctrl-sun8i-h3.o obj-$(CONFIG_PINCTRL_SUN8I_H3_R) += pinctrl-sun8i-h3-r.o obj-$(CONFIG_PINCTRL_SUN8I_V3S) += pinctrl-sun8i-v3s.o +obj-$(CONFIG_PINCTRL_SUN20I_D1) += pinctrl-sun20i-d1.o obj-$(CONFIG_PINCTRL_SUN50I_H5) += pinctrl-sun50i-h5.o obj-$(CONFIG_PINCTRL_SUN50I_H6) += pinctrl-sun50i-h6.o obj-$(CONFIG_PINCTRL_SUN50I_H6_R) += pinctrl-sun50i-h6-r.o diff --git a/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c new file mode 100644 index 00000000000000..10fe29d62ea478 --- /dev/null +++ b/drivers/pinctrl/sunxi/pinctrl-sun20i-d1.c @@ -0,0 +1,836 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Allwinner D1 SoC pinctrl driver. + * + * Copyright (c) 2020 wuyan@allwinnertech.com + * Copyright (c) 2021 Samuel Holland + */ + +#include +#include +#include +#include +#include + +#include "pinctrl-sunxi.h" + +/* PB:8pins,PC:8pins,PD:23pins,PE:18pins,PF:7pins, PG:16pins */ +static const struct sunxi_desc_pin d1_pins[] = { + /* PB */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "pwm3"), + SUNXI_FUNCTION(0x3, "ir"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x5, "spi1"), /* WP */ + SUNXI_FUNCTION(0x6, "uart0"), /* TX */ + SUNXI_FUNCTION(0x7, "uart2"), /* TX */ + SUNXI_FUNCTION(0x8, "spdif"), /* OUT */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "pwm4"), + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT3 */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN3 */ + SUNXI_FUNCTION(0x6, "uart0"), /* RX */ + SUNXI_FUNCTION(0x7, "uart2"), /* RX */ + SUNXI_FUNCTION(0x8, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D0 */ + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT2 */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN2 */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D18 */ + SUNXI_FUNCTION(0x7, "uart4"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D1 */ + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN0 */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D19 */ + SUNXI_FUNCTION(0x7, "uart4"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D8 */ + SUNXI_FUNCTION(0x3, "i2s2_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x5, "i2s2_din"), /* DIN1 */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D20 */ + SUNXI_FUNCTION(0x7, "uart5"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D9 */ + SUNXI_FUNCTION(0x3, "i2s2"), /* BCLK */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x5, "pwm0"), + SUNXI_FUNCTION(0x6, "lcd0"), /* D21 */ + SUNXI_FUNCTION(0x7, "uart5"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D16 */ + SUNXI_FUNCTION(0x3, "i2s2"), /* LRCK */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x5, "pwm1"), + SUNXI_FUNCTION(0x6, "lcd0"), /* D22 */ + SUNXI_FUNCTION(0x7, "uart3"), /* TX */ + SUNXI_FUNCTION(0x8, "bist0"), /* BIST_RESULT0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D17 */ + SUNXI_FUNCTION(0x3, "i2s2"), /* MCLK */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x5, "ir"), /* RX */ + SUNXI_FUNCTION(0x6, "lcd0"), /* D23 */ + SUNXI_FUNCTION(0x7, "uart3"), /* RX */ + SUNXI_FUNCTION(0x8, "bist1"), /* BIST_RESULT1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA3 */ + SUNXI_FUNCTION(0x3, "pwm5"), + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x5, "spi1"), /* HOLD */ + SUNXI_FUNCTION(0x6, "uart0"), /* TX */ + SUNXI_FUNCTION(0x7, "uart1"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA2 */ + SUNXI_FUNCTION(0x3, "pwm6"), + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x5, "spi1"), /* MISO */ + SUNXI_FUNCTION(0x6, "uart0"), /* RX */ + SUNXI_FUNCTION(0x7, "uart1"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA1 */ + SUNXI_FUNCTION(0x3, "pwm7"), + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "spi1"), /* MOSI */ + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x7, "uart1"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* DATA0 */ + SUNXI_FUNCTION(0x3, "pwm2"), + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "spi1"), /* CLK */ + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x7, "uart1"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(B, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "dmic"), /* CLK */ + SUNXI_FUNCTION(0x3, "pwm0"), + SUNXI_FUNCTION(0x4, "spdif"), /* IN */ + SUNXI_FUNCTION(0x5, "spi1"), /* CS0 */ + SUNXI_FUNCTION(0x6, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x7, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 0, 12)), + /* PC */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* TX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "ledc"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* RX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* CLK */ + SUNXI_FUNCTION(0x3, "sdc2"), /* CLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* CS0 */ + SUNXI_FUNCTION(0x3, "sdc2"), /* CMD */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* MOSI */ + SUNXI_FUNCTION(0x3, "sdc2"), /* D2 */ + SUNXI_FUNCTION(0x4, "boot"), /* SEL0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* MISO */ + SUNXI_FUNCTION(0x3, "sdc2"), /* D1 */ + SUNXI_FUNCTION(0x4, "boot"), /* SEL1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* WP */ + SUNXI_FUNCTION(0x3, "sdc2"), /* D0 */ + SUNXI_FUNCTION(0x4, "uart3"), /* TX */ + SUNXI_FUNCTION(0x5, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x6, "pll"), /* DBG-CLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(C, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spi0"), /* HOLD */ + SUNXI_FUNCTION(0x3, "sdc2"), /* D3 */ + SUNXI_FUNCTION(0x4, "uart3"), /* RX */ + SUNXI_FUNCTION(0x5, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x6, "tcon"), /* TRIG0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 1, 7)), + /* PD */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D2 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V0P */ + SUNXI_FUNCTION(0x4, "dsi"), /* D0P */ + SUNXI_FUNCTION(0x5, "i2c0"), /* SCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D3 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V0N */ + SUNXI_FUNCTION(0x4, "dsi"), /* D0N */ + SUNXI_FUNCTION(0x5, "uart2"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D4 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V1P */ + SUNXI_FUNCTION(0x4, "dsi"), /* D1P */ + SUNXI_FUNCTION(0x5, "uart2"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D5 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V1N */ + SUNXI_FUNCTION(0x4, "dsi"), /* D1N */ + SUNXI_FUNCTION(0x5, "uart2"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D6 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V2P */ + SUNXI_FUNCTION(0x4, "dsi"), /* CKP */ + SUNXI_FUNCTION(0x5, "uart2"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D7 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V2N */ + SUNXI_FUNCTION(0x4, "dsi"), /* CKN */ + SUNXI_FUNCTION(0x5, "uart5"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D10 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* CKP */ + SUNXI_FUNCTION(0x4, "dsi"), /* D2P */ + SUNXI_FUNCTION(0x5, "uart5"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D11 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* CKN */ + SUNXI_FUNCTION(0x4, "dsi"), /* D2N */ + SUNXI_FUNCTION(0x5, "uart4"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D12 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V3P */ + SUNXI_FUNCTION(0x4, "dsi"), /* D3P */ + SUNXI_FUNCTION(0x5, "uart4"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D13 */ + SUNXI_FUNCTION(0x3, "lvds0"), /* V3N */ + SUNXI_FUNCTION(0x4, "dsi"), /* D3N */ + SUNXI_FUNCTION(0x5, "pwm6"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D14 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V0P */ + SUNXI_FUNCTION(0x4, "spi1"), /* CS0 */ + SUNXI_FUNCTION(0x5, "uart3"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D15 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V0N */ + SUNXI_FUNCTION(0x4, "spi1"), /* CLK */ + SUNXI_FUNCTION(0x5, "uart3"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D18 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V1P */ + SUNXI_FUNCTION(0x4, "spi1"), /* MOSI */ + SUNXI_FUNCTION(0x5, "i2c0"), /* SDA */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 12)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 13), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D19 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V1N */ + SUNXI_FUNCTION(0x4, "spi1"), /* MISO */ + SUNXI_FUNCTION(0x5, "uart3"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 13)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 14), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D20 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V2P */ + SUNXI_FUNCTION(0x4, "spi1"), /* HOLD */ + SUNXI_FUNCTION(0x5, "uart3"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 14)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 15), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D21 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V2N */ + SUNXI_FUNCTION(0x4, "spi1"), /* WP */ + SUNXI_FUNCTION(0x5, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 15)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 16), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D22 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* CKP */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA3 */ + SUNXI_FUNCTION(0x5, "pwm0"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 16)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 17), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* D23 */ + SUNXI_FUNCTION(0x3, "lvds1"), /* CKN */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA2 */ + SUNXI_FUNCTION(0x5, "pwm1"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 17)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 18), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* CLK */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V3P */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA1 */ + SUNXI_FUNCTION(0x5, "pwm2"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 18)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 19), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* DE */ + SUNXI_FUNCTION(0x3, "lvds1"), /* V3N */ + SUNXI_FUNCTION(0x4, "dmic"), /* DATA0 */ + SUNXI_FUNCTION(0x5, "pwm3"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 19)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 20), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* HSYNC */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "dmic"), /* CLK */ + SUNXI_FUNCTION(0x5, "pwm4"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 20)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 21), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "lcd0"), /* VSYNC */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x4, "uart1"), /* TX */ + SUNXI_FUNCTION(0x5, "pwm5"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 21)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(D, 22), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x3, "ir"), /* RX */ + SUNXI_FUNCTION(0x4, "uart1"), /* RX */ + SUNXI_FUNCTION(0x5, "pwm7"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 2, 22)), + /* PE */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* HSYNC */ + SUNXI_FUNCTION(0x3, "uart2"), /* RTS */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x5, "lcd0"), /* HSYNC */ + SUNXI_FUNCTION(0x8, "emac"), /* RXCTL/CRS_DV */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* VSYNC */ + SUNXI_FUNCTION(0x3, "uart2"), /* CTS */ + SUNXI_FUNCTION(0x4, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x5, "lcd0"), /* VSYNC */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* PCLK */ + SUNXI_FUNCTION(0x3, "uart2"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x6, "uart0"), /* TX */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "csi0"), /* MCLK */ + SUNXI_FUNCTION(0x3, "uart2"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x6, "uart0"), /* RX */ + SUNXI_FUNCTION(0x8, "emac"), /* TXCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D0 */ + SUNXI_FUNCTION(0x3, "uart4"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x6, "d_jtag"), /* MS */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* MS */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D1 */ + SUNXI_FUNCTION(0x3, "uart4"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x5, "ledc"), + SUNXI_FUNCTION(0x6, "d_jtag"), /* D1 */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* D1 */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D2 */ + SUNXI_FUNCTION(0x3, "uart5"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x5, "spdif"), /* IN */ + SUNXI_FUNCTION(0x6, "d_jtag"), /* D0 */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* D0 */ + SUNXI_FUNCTION(0x8, "emac"), /* TXCTL/TXEN */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D3 */ + SUNXI_FUNCTION(0x3, "uart5"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x5, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x6, "d_jtag"), /* CK */ + SUNXI_FUNCTION(0x7, "r_jtag"), /* CK */ + SUNXI_FUNCTION(0x8, "emac"), /* CK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D4 */ + SUNXI_FUNCTION(0x3, "uart1"), /* RTS */ + SUNXI_FUNCTION(0x4, "pwm2"), + SUNXI_FUNCTION(0x5, "uart3"), /* TX */ + SUNXI_FUNCTION(0x6, "jtag"), /* MS */ + SUNXI_FUNCTION(0x8, "emac"), /* MDC */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D5 */ + SUNXI_FUNCTION(0x3, "uart1"), /* CTS */ + SUNXI_FUNCTION(0x4, "pwm3"), + SUNXI_FUNCTION(0x5, "uart3"), /* RX */ + SUNXI_FUNCTION(0x6, "jtag"), /* D1 */ + SUNXI_FUNCTION(0x8, "emac"), /* MDIO */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D6 */ + SUNXI_FUNCTION(0x3, "uart1"), /* TX */ + SUNXI_FUNCTION(0x4, "pwm4"), + SUNXI_FUNCTION(0x5, "ir"), /* RX */ + SUNXI_FUNCTION(0x6, "jtag"), /* D0 */ + SUNXI_FUNCTION(0x8, "emac"), /* EPHY-25M */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ncsi0"), /* D7 */ + SUNXI_FUNCTION(0x3, "uart1"), /* RX */ + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT3 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN3 */ + SUNXI_FUNCTION(0x6, "jtag"), /* CK */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD2 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x3, "ncsi0"), /* FIELD */ + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT2 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN2 */ + SUNXI_FUNCTION(0x8, "emac"), /* TXD3 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 12)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 13), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x3, "pwm5"), + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN1 */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA3 */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD2 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 13)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 14), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* MS */ + SUNXI_FUNCTION(0x4, "i2s0_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x5, "i2s0_din"), /* DIN0 */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA2 */ + SUNXI_FUNCTION(0x8, "emac"), /* RXD3 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 14)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 15), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* D1 */ + SUNXI_FUNCTION(0x4, "pwm6"), + SUNXI_FUNCTION(0x5, "i2s0"), /* LRCK */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA1 */ + SUNXI_FUNCTION(0x8, "emac"), /* RXCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 15)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 16), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* D0 */ + SUNXI_FUNCTION(0x4, "pwm7"), + SUNXI_FUNCTION(0x5, "i2s0"), /* BCLK */ + SUNXI_FUNCTION(0x6, "dmic"), /* DATA0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 16)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(E, 17), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x3, "d_jtag"), /* CK */ + SUNXI_FUNCTION(0x4, "ir"), /* TX */ + SUNXI_FUNCTION(0x5, "i2s0"), /* MCLK */ + SUNXI_FUNCTION(0x6, "dmic"), /* CLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 3, 17)), + /* PF */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc0"), /* D1 */ + SUNXI_FUNCTION(0x3, "jtag"), /* MS */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* MS */ + SUNXI_FUNCTION(0x5, "i2s2_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x6, "i2s2_din"), /* DIN0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc0"), /* D0 */ + SUNXI_FUNCTION(0x3, "jtag"), /* DI */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* DI */ + SUNXI_FUNCTION(0x5, "i2s2_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x6, "i2s2_din"), /* DIN1 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc0"), /* CLK */ + SUNXI_FUNCTION(0x3, "uart0"), /* TX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x5, "ledc"), + SUNXI_FUNCTION(0x6, "spdif"), /* IN */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc0"), /* CMD */ + SUNXI_FUNCTION(0x3, "jtag"), /* DO */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* DO */ + SUNXI_FUNCTION(0x5, "i2s2"), /* BCLK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc0"), /* D3 */ + SUNXI_FUNCTION(0x3, "uart0"), /* RX */ + SUNXI_FUNCTION(0x4, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x5, "pwm6"), + SUNXI_FUNCTION(0x6, "ir"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc0"), /* D2 */ + SUNXI_FUNCTION(0x3, "jtag"), /* CK */ + SUNXI_FUNCTION(0x4, "r_jtag"), /* CK */ + SUNXI_FUNCTION(0x5, "i2s2"), /* LRCK */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(F, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x3, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x4, "ir"), /* RX */ + SUNXI_FUNCTION(0x5, "i2s2"), /* MCLK */ + SUNXI_FUNCTION(0x6, "pwm5"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 4, 6)), + /* PG */ + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 0), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc1"), /* CLK */ + SUNXI_FUNCTION(0x3, "uart3"), /* TX */ + SUNXI_FUNCTION(0x4, "emac"), /* RXCTRL/CRS_DV */ + SUNXI_FUNCTION(0x5, "pwm7"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 0)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 1), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc1"), /* CMD */ + SUNXI_FUNCTION(0x3, "uart3"), /* RX */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD0 */ + SUNXI_FUNCTION(0x5, "pwm6"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 1)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 2), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc1"), /* D0 */ + SUNXI_FUNCTION(0x3, "uart3"), /* RTS */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD1 */ + SUNXI_FUNCTION(0x5, "uart4"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 2)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 3), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc1"), /* D1 */ + SUNXI_FUNCTION(0x3, "uart3"), /* CTS */ + SUNXI_FUNCTION(0x4, "emac"), /* TXCK */ + SUNXI_FUNCTION(0x5, "uart4"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 3)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 4), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc1"), /* D2 */ + SUNXI_FUNCTION(0x3, "uart5"), /* TX */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD0 */ + SUNXI_FUNCTION(0x5, "pwm5"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 4)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 5), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "sdc1"), /* D3 */ + SUNXI_FUNCTION(0x3, "uart5"), /* RX */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD1 */ + SUNXI_FUNCTION(0x5, "pwm4"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 5)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 6), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* TX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD2 */ + SUNXI_FUNCTION(0x5, "pwm1"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 6)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 7), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* RX */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* TXD3 */ + SUNXI_FUNCTION(0x5, "spdif"), /* IN */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 7)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 8), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* RTS */ + SUNXI_FUNCTION(0x3, "i2c1"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD2 */ + SUNXI_FUNCTION(0x5, "uart3"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 8)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 9), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart1"), /* CTS */ + SUNXI_FUNCTION(0x3, "i2c1"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* RXD3 */ + SUNXI_FUNCTION(0x5, "uart3"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 9)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 10), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "pwm3"), + SUNXI_FUNCTION(0x3, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* RXCK */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x6, "ir"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 10)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 11), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1"), /* MCLK */ + SUNXI_FUNCTION(0x3, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* EPHY-25M */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x6, "tcon"), /* TRIG0 */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 11)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 12), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1"), /* LRCK */ + SUNXI_FUNCTION(0x3, "i2c0"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* TXCTL/TXEN */ + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x6, "pwm0"), + SUNXI_FUNCTION(0x7, "uart1"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 12)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 13), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1"), /* BCLK */ + SUNXI_FUNCTION(0x3, "i2c0"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* CLKIN/RXER */ + SUNXI_FUNCTION(0x5, "pwm2"), + SUNXI_FUNCTION(0x6, "ledc"), + SUNXI_FUNCTION(0x7, "uart1"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 13)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 14), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1_din"), /* DIN0 */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SCK */ + SUNXI_FUNCTION(0x4, "emac"), /* MDC */ + SUNXI_FUNCTION(0x5, "i2s1_dout"), /* DOUT1 */ + SUNXI_FUNCTION(0x6, "spi0"), /* WP */ + SUNXI_FUNCTION(0x7, "uart1"), /* RTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 14)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 15), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "i2s1_dout"), /* DOUT0 */ + SUNXI_FUNCTION(0x3, "i2c2"), /* SDA */ + SUNXI_FUNCTION(0x4, "emac"), /* MDIO */ + SUNXI_FUNCTION(0x5, "i2s1_din"), /* DIN1 */ + SUNXI_FUNCTION(0x6, "spi0"), /* HOLD */ + SUNXI_FUNCTION(0x7, "uart1"), /* CTS */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 15)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 16), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "ir"), /* RX */ + SUNXI_FUNCTION(0x3, "tcon"), /* TRIG0 */ + SUNXI_FUNCTION(0x4, "pwm5"), + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT2 */ + SUNXI_FUNCTION(0x6, "spdif"), /* IN */ + SUNXI_FUNCTION(0x7, "ledc"), + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 16)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 17), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* TX */ + SUNXI_FUNCTION(0x3, "i2c3"), /* SCK */ + SUNXI_FUNCTION(0x4, "pwm7"), + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT0 */ + SUNXI_FUNCTION(0x6, "ir"), /* TX */ + SUNXI_FUNCTION(0x7, "uart0"), /* TX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 17)), + SUNXI_PIN(SUNXI_PINCTRL_PIN(G, 18), + SUNXI_FUNCTION(0x0, "gpio_in"), + SUNXI_FUNCTION(0x1, "gpio_out"), + SUNXI_FUNCTION(0x2, "uart2"), /* RX */ + SUNXI_FUNCTION(0x3, "i2c3"), /* SDA */ + SUNXI_FUNCTION(0x4, "pwm6"), + SUNXI_FUNCTION(0x5, "clk"), /* FANOUT1 */ + SUNXI_FUNCTION(0x6, "spdif"), /* OUT */ + SUNXI_FUNCTION(0x7, "uart0"), /* RX */ + SUNXI_FUNCTION_IRQ_BANK(0xe, 5, 18)), +}; + +static const unsigned int d1_irq_bank_map[] = { 1, 2, 3, 4, 5, 6 }; + +static const struct sunxi_pinctrl_desc d1_pinctrl_data = { + .pins = d1_pins, + .npins = ARRAY_SIZE(d1_pins), + .irq_banks = ARRAY_SIZE(d1_irq_bank_map), + .irq_bank_map = d1_irq_bank_map, + .io_bias_cfg_variant = BIAS_VOLTAGE_PIO_POW_MODE_CTL, +}; + +static int d1_pinctrl_probe(struct platform_device *pdev) +{ + return sunxi_pinctrl_init(pdev, &d1_pinctrl_data); +} + +static const struct of_device_id d1_pinctrl_match[] = { + { .compatible = "allwinner,sun20i-d1-pinctrl" }, + {} +}; + +static struct platform_driver d1_pinctrl_driver = { + .probe = d1_pinctrl_probe, + .driver = { + .name = "sun20i-d1-pinctrl", + .of_match_table = d1_pinctrl_match, + }, +}; +builtin_platform_driver(d1_pinctrl_driver); From 0f0a8273b5229d6865a609ece7a9a25c89a0b8ba Mon Sep 17 00:00:00 2001 From: Ban Tao Date: Tue, 2 Mar 2021 20:40:23 +0800 Subject: [PATCH 070/120] pwm: sun8i-v536: document device tree bindings This adds binding documentation for sun8i-v536 SoC PWM driver. Signed-off-by: Ban Tao --- .../bindings/pwm/pwm-sun8i-v536.txt | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 Documentation/devicetree/bindings/pwm/pwm-sun8i-v536.txt diff --git a/Documentation/devicetree/bindings/pwm/pwm-sun8i-v536.txt b/Documentation/devicetree/bindings/pwm/pwm-sun8i-v536.txt new file mode 100644 index 00000000000000..ab3f4fe0560a25 --- /dev/null +++ b/Documentation/devicetree/bindings/pwm/pwm-sun8i-v536.txt @@ -0,0 +1,24 @@ +Allwinner sun8i-v536 SoC PWM controller + +Required properties: + - compatible: should be "allwinner,-pwm" + "allwinner,sun8i-v833-pwm" + "allwinner,sun8i-v536-pwm" + "allwinner,sun50i-r818-pwm" + "allwinner,sun50i-a133-pwm" + "allwinner,sun50i-r329-pwm" + - reg: physical base address and length of the controller's registers + - #pwm-cells: should be 3. See pwm.txt in this directory for a description of + the cells format. + - clocks: From common clock binding, handle to the parent clock. + - resets: From reset clock binding, handle to the parent clock. + +Example: + + pwm: pwm@300a0000 { + compatible = "allwinner,sun50i-r818-pwm"; + reg = <0x0300a000 0x3ff>; + clocks = <&ccu CLK_BUS_PWM>; + resets = <&ccu RST_BUS_PWM>; + #pwm-cells = <3>; + }; From 3de9d170aaa3b78b1df72456d31f95bae4632a5c Mon Sep 17 00:00:00 2001 From: Ban Tao Date: Tue, 2 Mar 2021 20:37:37 +0800 Subject: [PATCH 071/120] pwm: sunxi: Add Allwinner SoC PWM controller driver The Allwinner R818, A133, R329, V536 and V833 has a new PWM controller IP compared to the older Allwinner SoCs. Signed-off-by: Ban Tao --- MAINTAINERS | 6 + drivers/pwm/Kconfig | 11 + drivers/pwm/Makefile | 1 + drivers/pwm/pwm-sun8i-v536.c | 401 +++++++++++++++++++++++++++++++++++ 4 files changed, 419 insertions(+) create mode 100644 drivers/pwm/pwm-sun8i-v536.c diff --git a/MAINTAINERS b/MAINTAINERS index bd26af81094d5e..93f632ece37e97 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -773,6 +773,12 @@ L: linux-media@vger.kernel.org S: Maintained F: drivers/staging/media/sunxi/cedrus/ +ALLWINNER PWM DRIVER +M: Ban Tao +L: linux-pwm@vger.kernel.org +S: Maintained +F: drivers/pwm/pwm-sun8i-v536.c + ALPHA PORT M: Richard Henderson M: Ivan Kokshaysky diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index c76adedd58c9f0..3ae89090a7d7f5 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -569,6 +569,17 @@ config PWM_SUN4I To compile this driver as a module, choose M here: the module will be called pwm-sun4i. +config PWM_SUN8I_V536 + tristate "Allwinner SUN8I_V536 PWM support" + depends on ARCH_SUNXI || COMPILE_TEST + depends on HAS_IOMEM && COMMON_CLK + help + Enhanced PWM framework driver for Allwinner R818, A133, R329, + V536 and V833 SoCs. + + To compile this driver as a module, choose M here: the module + will be called pwm-sun8i-v536. + config PWM_TEGRA tristate "NVIDIA Tegra PWM support" depends on ARCH_TEGRA || COMPILE_TEST diff --git a/drivers/pwm/Makefile b/drivers/pwm/Makefile index 708840b7fba8d8..2ab762e719ff0d 100644 --- a/drivers/pwm/Makefile +++ b/drivers/pwm/Makefile @@ -53,6 +53,7 @@ obj-$(CONFIG_PWM_STM32) += pwm-stm32.o obj-$(CONFIG_PWM_STM32_LP) += pwm-stm32-lp.o obj-$(CONFIG_PWM_STMPE) += pwm-stmpe.o obj-$(CONFIG_PWM_SUN4I) += pwm-sun4i.o +obj-$(CONFIG_PWM_SUN8I_V536) += pwm-sun8i-v536.o obj-$(CONFIG_PWM_TEGRA) += pwm-tegra.o obj-$(CONFIG_PWM_TIECAP) += pwm-tiecap.o obj-$(CONFIG_PWM_TIEHRPWM) += pwm-tiehrpwm.o diff --git a/drivers/pwm/pwm-sun8i-v536.c b/drivers/pwm/pwm-sun8i-v536.c new file mode 100644 index 00000000000000..52101df6bd41b1 --- /dev/null +++ b/drivers/pwm/pwm-sun8i-v536.c @@ -0,0 +1,401 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Driver for Allwinner sun8i-v536 Pulse Width Modulation Controller + * + * Copyright (C) 2021 Ban Tao + * + * + * Limitations: + * - When PWM is disabled, the output is driven to inactive. + * - If the register is reconfigured while PWM is running, + * it does not complete the currently running period. + * - If the user input duty is beyond acceptible limits, + * -EINVAL is returned. + */ + +#include +#include +#include +#include +#include +#include +#include + +#define PWM_GET_CLK_OFFSET(chan) (0x20 + ((chan >> 1) * 0x4)) +#define PWM_CLK_APB_SCR BIT(7) +#define PWM_DIV_M 0 +#define PWM_DIV_M_MASK GENMASK(3, PWM_DIV_M) + +#define PWM_CLK_REG 0x40 +#define PWM_CLK_GATING BIT(0) + +#define PWM_ENABLE_REG 0x80 +#define PWM_EN BIT(0) + +#define PWM_CTL_REG(chan) (0x100 + 0x20 * chan) +#define PWM_ACT_STA BIT(8) +#define PWM_PRESCAL_K 0 +#define PWM_PRESCAL_K_MASK GENMASK(7, PWM_PRESCAL_K) + +#define PWM_PERIOD_REG(chan) (0x104 + 0x20 * chan) +#define PWM_ENTIRE_CYCLE 16 +#define PWM_ENTIRE_CYCLE_MASK GENMASK(31, PWM_ENTIRE_CYCLE) +#define PWM_ACT_CYCLE 0 +#define PWM_ACT_CYCLE_MASK GENMASK(15, PWM_ACT_CYCLE) + +#define BIT_CH(bit, chan) ((bit) << (chan)) +#define SET_BITS(shift, mask, reg, val) \ + (((reg) & ~mask) | (val << (shift))) + +#define PWM_OSC_CLK 24000000 +#define PWM_PRESCALER_MAX 256 +#define PWM_CLK_DIV_M__MAX 9 +#define PWM_ENTIRE_CYCLE_MAX 65536 + +struct sun8i_pwm_data { + unsigned int npwm; +}; + +struct sun8i_pwm_chip { + struct pwm_chip chip; + struct clk *clk; + struct reset_control *rst_clk; + void __iomem *base; + const struct sun8i_pwm_data *data; +}; + +static inline struct sun8i_pwm_chip *to_sun8i_pwm_chip(struct pwm_chip *chip) +{ + return container_of(chip, struct sun8i_pwm_chip, chip); +} + +static inline u32 sun8i_pwm_readl(struct sun8i_pwm_chip *chip, + unsigned long offset) +{ + return readl(chip->base + offset); +} + +static inline void sun8i_pwm_writel(struct sun8i_pwm_chip *chip, + u32 val, unsigned long offset) +{ + writel(val, chip->base + offset); +} + +static void sun8i_pwm_get_state(struct pwm_chip *chip, + struct pwm_device *pwm, + struct pwm_state *state) +{ + struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip); + u64 clk_rate; + u32 tmp, entire_cycles, active_cycles; + unsigned int prescaler, div_m; + + tmp = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + if (tmp & PWM_CLK_APB_SCR) + clk_rate = clk_get_rate(pc->clk); + else + clk_rate = PWM_OSC_CLK; + + tmp = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + div_m = 0x1 << (tmp & PWM_DIV_M_MASK); + + tmp = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm)); + prescaler = (tmp & PWM_PRESCAL_K_MASK) + 1; + + tmp = sun8i_pwm_readl(pc, PWM_PERIOD_REG(pwm->hwpwm)); + entire_cycles = (tmp >> PWM_ENTIRE_CYCLE) + 1; + active_cycles = (tmp & PWM_ACT_CYCLE_MASK); + + /* (clk / div_m / prescaler) / entire_cycles = NSEC_PER_SEC / period_ns. */ + state->period = DIV_ROUND_CLOSEST_ULL(entire_cycles * NSEC_PER_SEC, + clk_rate) * div_m * prescaler; + /* duty_ns / period_ns = active_cycles / entire_cycles. */ + state->duty_cycle = DIV_ROUND_CLOSEST_ULL(active_cycles * state->period, + entire_cycles); + + /* parsing polarity */ + tmp = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm)); + if (tmp & PWM_ACT_STA) + state->polarity = PWM_POLARITY_NORMAL; + else + state->polarity = PWM_POLARITY_INVERSED; + + /* parsing enabled */ + tmp = sun8i_pwm_readl(pc, PWM_ENABLE_REG); + if (tmp & BIT_CH(PWM_EN, pwm->hwpwm)) + state->enabled = true; + else + state->enabled = false; + + dev_dbg(chip->dev, "duty_ns=%lld period_ns=%lld polarity=%s enabled=%s.\n", + state->duty_cycle, state->period, + state->polarity ? "inversed":"normal", + state->enabled ? "true":"false"); +} + +static void sun8i_pwm_set_polarity(struct pwm_chip *chip, struct pwm_device *pwm, + enum pwm_polarity polarity) +{ + struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip); + u32 temp; + + temp = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm)); + + if (polarity == PWM_POLARITY_NORMAL) + temp |= PWM_ACT_STA; + else + temp &= ~PWM_ACT_STA; + + sun8i_pwm_writel(pc, temp, PWM_CTL_REG(pwm->hwpwm)); +} + +static int sun8i_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip); + unsigned long long c; + unsigned long entire_cycles, active_cycles; + unsigned int div_m, prescaler; + u64 duty_ns = state->duty_cycle, period_ns = state->period; + u32 config; + int ret = 0; + + if (period_ns > 334) { + /* if freq < 3M, then select 24M clock */ + c = PWM_OSC_CLK; + config = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + config &= ~PWM_CLK_APB_SCR; + sun8i_pwm_writel(pc, config, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + } else { + /* if freq > 3M, then select APB as clock */ + c = clk_get_rate(pc->clk); + config = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + config |= PWM_CLK_APB_SCR; + sun8i_pwm_writel(pc, config, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + } + + dev_dbg(chip->dev, "duty_ns=%lld period_ns=%lld c =%llu.\n", + duty_ns, period_ns, c); + + /* + * (clk / div_m / prescaler) / entire_cycles = NSEC_PER_SEC / period_ns. + * So, entire_cycles = clk * period_ns / NSEC_PER_SEC / div_m / prescaler. + */ + c = c * period_ns; + c = DIV_ROUND_CLOSEST_ULL(c, NSEC_PER_SEC); + for (div_m = 0; div_m < PWM_CLK_DIV_M__MAX; div_m++) { + for (prescaler = 0; prescaler < PWM_PRESCALER_MAX; prescaler++) { + /* + * actual prescaler = prescaler(reg value) + 1. + * actual div_m = 0x1 << div_m(reg value). + */ + entire_cycles = ((unsigned long)c >> div_m)/(prescaler + 1); + if (entire_cycles <= PWM_ENTIRE_CYCLE_MAX) + goto calc_end; + } + } + ret = -EINVAL; + goto exit; + +calc_end: + /* + * duty_ns / period_ns = active_cycles / entire_cycles. + * So, active_cycles = entire_cycles * duty_ns / period_ns. + */ + c = (unsigned long long)entire_cycles * duty_ns; + c = DIV_ROUND_CLOSEST_ULL(c, period_ns); + active_cycles = c; + if (entire_cycles == 0) + entire_cycles++; + + /* config clk div_m*/ + config = sun8i_pwm_readl(pc, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + config = SET_BITS(PWM_DIV_M, PWM_DIV_M_MASK, config, div_m); + sun8i_pwm_writel(pc, config, PWM_GET_CLK_OFFSET(pwm->hwpwm)); + + /* config prescaler */ + config = sun8i_pwm_readl(pc, PWM_CTL_REG(pwm->hwpwm)); + config = SET_BITS(PWM_PRESCAL_K, PWM_PRESCAL_K_MASK, config, prescaler); + sun8i_pwm_writel(pc, config, PWM_CTL_REG(pwm->hwpwm)); + + /* config active and period cycles */ + config = sun8i_pwm_readl(pc, PWM_PERIOD_REG(pwm->hwpwm)); + config = SET_BITS(PWM_ACT_CYCLE, PWM_ACT_CYCLE_MASK, config, active_cycles); + config = SET_BITS(PWM_ENTIRE_CYCLE, PWM_ENTIRE_CYCLE_MASK, + config, (entire_cycles - 1)); + sun8i_pwm_writel(pc, config, PWM_PERIOD_REG(pwm->hwpwm)); + + dev_dbg(chip->dev, "active_cycles=%lu entire_cycles=%lu prescaler=%u div_m=%u\n", + active_cycles, entire_cycles, prescaler, div_m); + +exit: + return ret; +} + +static void sun8i_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm, + bool enable) +{ + struct sun8i_pwm_chip *pc = to_sun8i_pwm_chip(chip); + u32 clk, pwm_en; + + clk = sun8i_pwm_readl(pc, PWM_CLK_REG); + pwm_en = sun8i_pwm_readl(pc, PWM_ENABLE_REG); + + if (enable) { + clk |= BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + sun8i_pwm_writel(pc, clk, PWM_CLK_REG); + + pwm_en |= BIT_CH(PWM_EN, pwm->hwpwm); + sun8i_pwm_writel(pc, pwm_en, PWM_ENABLE_REG); + } else { + pwm_en &= ~BIT_CH(PWM_EN, pwm->hwpwm); + sun8i_pwm_writel(pc, pwm_en, PWM_ENABLE_REG); + + clk &= ~BIT_CH(PWM_CLK_GATING, pwm->hwpwm); + sun8i_pwm_writel(pc, clk, PWM_CLK_REG); + } +} + +static int sun8i_pwm_apply(struct pwm_chip *chip, struct pwm_device *pwm, + const struct pwm_state *state) +{ + struct pwm_state curstate; + int ret; + + pwm_get_state(pwm, &curstate); + + ret = sun8i_pwm_config(chip, pwm, state); + + if (state->polarity != curstate.polarity) + sun8i_pwm_set_polarity(chip, pwm, state->polarity); + + if (state->enabled != curstate.enabled) + sun8i_pwm_enable(chip, pwm, state->enabled); + + return ret; +} + +static const struct pwm_ops sun8i_pwm_ops = { + .get_state = sun8i_pwm_get_state, + .apply = sun8i_pwm_apply, + .owner = THIS_MODULE, +}; + +static const struct sun8i_pwm_data sun8i_pwm_data_c9 = { + .npwm = 9, +}; + +static const struct sun8i_pwm_data sun50i_pwm_data_c16 = { + .npwm = 16, +}; + +static const struct of_device_id sun8i_pwm_dt_ids[] = { + { + .compatible = "allwinner,sun8i-v536-pwm", + .data = &sun8i_pwm_data_c9, + }, { + .compatible = "allwinner,sun50i-r818-pwm", + .data = &sun50i_pwm_data_c16, + }, { + /* sentinel */ + }, +}; +MODULE_DEVICE_TABLE(of, sun8i_pwm_dt_ids); + +static int sun8i_pwm_probe(struct platform_device *pdev) +{ + struct sun8i_pwm_chip *pc; + int ret; + + pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); + if (!pc) + return dev_err_probe(&pdev->dev, -ENOMEM, + "memory allocation failed\n"); + + pc->data = of_device_get_match_data(&pdev->dev); + if (!pc->data) + return dev_err_probe(&pdev->dev, -ENODEV, + "can't get match data\n"); + + pc->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pc->base)) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->base), + "can't remap pwm resource\n"); + + pc->clk = devm_clk_get(&pdev->dev, NULL); + if (IS_ERR(pc->clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->clk), + "get clock failed\n"); + + pc->rst_clk = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(pc->rst_clk)) + return dev_err_probe(&pdev->dev, PTR_ERR(pc->rst_clk), + "get reset failed\n"); + + /* Deassert reset */ + ret = reset_control_deassert(pc->rst_clk); + if (ret < 0) + return dev_err_probe(&pdev->dev, ret, + "cannot deassert reset control\n"); + + ret = clk_prepare_enable(pc->clk); + if (ret) { + dev_err(&pdev->dev, "cannot prepare and enable clk %pe\n", + ERR_PTR(ret)); + goto err_clk; + } + + pc->chip.dev = &pdev->dev; + pc->chip.ops = &sun8i_pwm_ops; + pc->chip.npwm = pc->data->npwm; + pc->chip.of_xlate = of_pwm_xlate_with_flags; + pc->chip.base = -1; + pc->chip.of_pwm_n_cells = 3; + + ret = pwmchip_add(&pc->chip); + if (ret < 0) { + dev_err(&pdev->dev, "failed to add PWM chip: %d\n", ret); + goto err_pwm_add; + } + + platform_set_drvdata(pdev, pc); + + return 0; + +err_pwm_add: + clk_disable_unprepare(pc->clk); +err_clk: + reset_control_assert(pc->rst_clk); + + return ret; +} + +static int sun8i_pwm_remove(struct platform_device *pdev) +{ + struct sun8i_pwm_chip *pc = platform_get_drvdata(pdev); + int ret; + + ret = pwmchip_remove(&pc->chip); + if (ret) + return ret; + + clk_disable_unprepare(pc->clk); + reset_control_assert(pc->rst_clk); + + return 0; +} + +static struct platform_driver sun8i_pwm_driver = { + .driver = { + .name = "sun8i-pwm-v536", + .of_match_table = sun8i_pwm_dt_ids, + }, + .probe = sun8i_pwm_probe, + .remove = sun8i_pwm_remove, +}; +module_platform_driver(sun8i_pwm_driver); + +MODULE_ALIAS("platform:sun8i-v536-pwm"); +MODULE_AUTHOR("Ban Tao "); +MODULE_DESCRIPTION("Allwinner sun8i-v536 PWM driver"); +MODULE_LICENSE("GPL v2"); From ecc0e9142b936b87b44716fa36addb55cc4a794c Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 11:05:20 -0500 Subject: [PATCH 072/120] squash? pwm: sunxi: Add Allwinner SoC PWM controller driver --- drivers/pwm/Kconfig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 3ae89090a7d7f5..738bb194fa3b01 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -570,11 +570,11 @@ config PWM_SUN4I will be called pwm-sun4i. config PWM_SUN8I_V536 - tristate "Allwinner SUN8I_V536 PWM support" - depends on ARCH_SUNXI || COMPILE_TEST + tristate "Allwinner SUN8I V536 enhanced PWM support" + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on HAS_IOMEM && COMMON_CLK help - Enhanced PWM framework driver for Allwinner R818, A133, R329, + Enhanced PWM framework driver for Allwinner A133, D1, R329, R818, V536 and V833 SoCs. To compile this driver as a module, choose M here: the module From a39d6727131a753737529e05b0c2035995d78a9e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:56:25 -0500 Subject: [PATCH 073/120] pwm: sun8i-v536: Add support for the Allwinner D1 Signed-off-by: Samuel Holland --- drivers/pwm/pwm-sun8i-v536.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/pwm/pwm-sun8i-v536.c b/drivers/pwm/pwm-sun8i-v536.c index 52101df6bd41b1..0f7365e144be8b 100644 --- a/drivers/pwm/pwm-sun8i-v536.c +++ b/drivers/pwm/pwm-sun8i-v536.c @@ -285,6 +285,10 @@ static const struct sun8i_pwm_data sun8i_pwm_data_c9 = { .npwm = 9, }; +static const struct sun8i_pwm_data sun20i_pwm_data_c8 = { + .npwm = 8, +}; + static const struct sun8i_pwm_data sun50i_pwm_data_c16 = { .npwm = 16, }; @@ -293,6 +297,9 @@ static const struct of_device_id sun8i_pwm_dt_ids[] = { { .compatible = "allwinner,sun8i-v536-pwm", .data = &sun8i_pwm_data_c9, + }, { + .compatible = "allwinner,sun20i-d1-pwm", + .data = &sun20i_pwm_data_c8, }, { .compatible = "allwinner,sun50i-r818-pwm", .data = &sun50i_pwm_data_c16, From d5b2dfc9c547865ef1feb924c714f8fcbde764d7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 11 Jul 2021 10:54:55 -0500 Subject: [PATCH 074/120] remoteproc: sun8i-dsp: Add a driver for the DSPs in sunxi SoCs Signed-off-by: Samuel Holland --- drivers/remoteproc/Kconfig | 7 + drivers/remoteproc/Makefile | 1 + drivers/remoteproc/sun8i_dsp_rproc.c | 269 +++++++++++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 drivers/remoteproc/sun8i_dsp_rproc.c diff --git a/drivers/remoteproc/Kconfig b/drivers/remoteproc/Kconfig index 9a6eedc3994a54..341e0472193874 100644 --- a/drivers/remoteproc/Kconfig +++ b/drivers/remoteproc/Kconfig @@ -289,6 +289,13 @@ config STM32_RPROC This can be either built-in or a loadable module. +config SUN8I_DSP_REMOTEPROC + tristate "Allwinner sun8i DSP remoteproc support" + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST + help + Say y here to support the DSP in some sun8i/sun20i/sun50i SoCs + via the remote processor framework. + config TI_K3_DSP_REMOTEPROC tristate "TI K3 DSP remoteproc support" depends on ARCH_K3 diff --git a/drivers/remoteproc/Makefile b/drivers/remoteproc/Makefile index bb26c9e4ef9cf3..e2daa32065a49a 100644 --- a/drivers/remoteproc/Makefile +++ b/drivers/remoteproc/Makefile @@ -33,5 +33,6 @@ qcom_wcnss_pil-y += qcom_wcnss_iris.o obj-$(CONFIG_ST_REMOTEPROC) += st_remoteproc.o obj-$(CONFIG_ST_SLIM_REMOTEPROC) += st_slim_rproc.o obj-$(CONFIG_STM32_RPROC) += stm32_rproc.o +obj-$(CONFIG_SUN8I_DSP_REMOTEPROC) += sun8i_dsp_rproc.o obj-$(CONFIG_TI_K3_DSP_REMOTEPROC) += ti_k3_dsp_remoteproc.o obj-$(CONFIG_TI_K3_R5_REMOTEPROC) += ti_k3_r5_remoteproc.o diff --git a/drivers/remoteproc/sun8i_dsp_rproc.c b/drivers/remoteproc/sun8i_dsp_rproc.c new file mode 100644 index 00000000000000..0d7682a4788e0d --- /dev/null +++ b/drivers/remoteproc/sun8i_dsp_rproc.c @@ -0,0 +1,269 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (c) 2021 Samuel Holland + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "remoteproc_internal.h" + +#define SUN8I_DSP_RESET_VEC_REG 0x0000 +#define SUN8I_DSP_CTRL_REG0 0x0004 +#define SUN8I_DSP_CTRL_REG0_RUN_STALL BIT(0) +#define SUN8I_DSP_CTRL_REG0_RESET_VEC_SEL BIT(1) +#define SUN8I_DSP_CTRL_REG0_DSP_CLKEN BIT(2) +#define SUN8I_DSP_CTRL_REG1 0x0008 +#define SUN8I_DSP_PRID_REG 0x000c +#define SUN8I_DSP_PRID_REG_PRID_MASK (0xff << 0) +#define SUN8I_DSP_STAT_REG 0x0010 +#define SUN8I_DSP_STAT_REG_PFAULT_INFO_VALID BIT(0) +#define SUN8I_DSP_STAT_REG_PFAULT_ERROR BIT(1) +#define SUN8I_DSP_STAT_REG_DOUBLE_EXCE_ERROR BIT(2) +#define SUN8I_DSP_STAT_REG_XOCD_MODE BIT(3) +#define SUN8I_DSP_STAT_REG_DEBUG_MODE BIT(4) +#define SUN8I_DSP_STAT_REG_PWAIT_MODE BIT(5) +#define SUN8I_DSP_STAT_REG_IRAM0_LOAD_STORE BIT(6) +#define SUN8I_DSP_BIST_CTRL_REG 0x0014 +#define SUN8I_DSP_BIST_CTRL_REG_EN BIT(0) +#define SUN8I_DSP_BIST_CTRL_REG_WDATA_PAT_MASK (0x7 << 1) +#define SUN8I_DSP_BIST_CTRL_REG_ADDR_MODE_SEL BIT(4) +#define SUN8I_DSP_BIST_CTRL_REG_REG_SEL_MASK (0x7 << 5) +#define SUN8I_DSP_BIST_CTRL_REG_BUSY BIT(8) +#define SUN8I_DSP_BIST_CTRL_REG_STOP BIT(9) +#define SUN8I_DSP_BIST_CTRL_REG_ERR_CYC_MASK (0x3 << 10) +#define SUN8I_DSP_BIST_CTRL_REG_ERR_PAT_MASK (0x7 << 12) +#define SUN8I_DSP_BIST_CTRL_REG_ERR_STA BIT(15) +#define SUN8I_DSP_BIST_CTRL_REG_SELECT_MASK (0xf << 16) +#define SUN8I_DSP_JTRST_REG 0x001c +#define SUN8I_DSP_VER_REG 0x0020 +#define SUN8I_DSP_VER_REG_MINOR_VER_MASK (0x1f << 0) +#define SUN8I_DSP_VER_REG_MAJOR_VER_MASK (0x1f << 16) + +#define SUN8I_DSP_CLK_FREQ 400000000 + +struct sun8i_dsp_rproc { + void __iomem *cfg_base; + struct clk *cfg_clk; + struct reset_control *cfg_reset; + struct reset_control *dbg_reset; + struct clk *dsp_clk; + struct reset_control *dsp_reset; + struct mbox_client client; + struct mbox_chan *rx_chan; + struct mbox_chan *tx_chan; +}; + +static int sun8i_dsp_rproc_start(struct rproc *rproc) +{ + struct sun8i_dsp_rproc *dsp = rproc->priv; + int ret; + u32 val; + + ret = sunxi_sram_claim(rproc->dev.parent); + if (ret) + return ret; + + ret = clk_prepare_enable(dsp->cfg_clk); + if (ret) + goto err_release_sram; + + ret = reset_control_deassert(dsp->cfg_reset); + if (ret) + goto err_gate_cfg; + + ret = reset_control_deassert(dsp->dbg_reset); + if (ret) + goto err_reset_cfg; + + writel(rproc->bootaddr, dsp->cfg_base + SUN8I_DSP_RESET_VEC_REG); + + val = readl(dsp->cfg_base + SUN8I_DSP_CTRL_REG0); + val |= SUN8I_DSP_CTRL_REG0_RESET_VEC_SEL | + SUN8I_DSP_CTRL_REG0_RUN_STALL; + writel(val, dsp->cfg_base + SUN8I_DSP_CTRL_REG0); + + ret = clk_prepare_enable(dsp->dsp_clk); + if (ret) + goto err_reset_dbg; + + ret = reset_control_deassert(dsp->dsp_reset); + if (ret) + goto err_gate_dsp; + + val &= ~SUN8I_DSP_CTRL_REG0_RUN_STALL; + writel(val, dsp->cfg_base + SUN8I_DSP_CTRL_REG0); + + return 0; + +err_gate_dsp: + clk_disable_unprepare(dsp->dsp_clk); +err_reset_dbg: + reset_control_assert(dsp->dbg_reset); +err_reset_cfg: + reset_control_assert(dsp->cfg_reset); +err_gate_cfg: + clk_disable_unprepare(dsp->cfg_clk); +err_release_sram: + sunxi_sram_release(rproc->dev.parent); + + return ret; +} + +static int sun8i_dsp_rproc_stop(struct rproc *rproc) +{ + struct sun8i_dsp_rproc *dsp = rproc->priv; + + reset_control_assert(dsp->dsp_reset); + clk_disable_unprepare(dsp->dsp_clk); + reset_control_assert(dsp->dbg_reset); + reset_control_assert(dsp->cfg_reset); + clk_disable_unprepare(dsp->cfg_clk); + sunxi_sram_release(rproc->dev.parent); + + return 0; +} + +static void sun8i_dsp_rproc_kick(struct rproc *rproc, int vqid) +{ + struct sun8i_dsp_rproc *dsp = rproc->priv; + long msg = vqid; + int ret; + + ret = mbox_send_message(dsp->tx_chan, (void *)msg); + if (ret) + dev_warn(&rproc->dev, "Failed to kick: %d\n", ret); +} + +static const struct rproc_ops sun8i_dsp_rproc_ops = { + .start = sun8i_dsp_rproc_start, + .stop = sun8i_dsp_rproc_stop, + .kick = sun8i_dsp_rproc_kick, +}; + +static void sun8i_dsp_rproc_mbox_rx_callback(struct mbox_client *client, void *msg) +{ + struct rproc *rproc = dev_get_drvdata(client->dev); + + rproc_vq_interrupt(rproc, (long)msg); +} + +static void sun8i_dsp_rproc_mbox_free(void *data) +{ + struct sun8i_dsp_rproc *dsp = data; + + if (!IS_ERR_OR_NULL(dsp->tx_chan)) + mbox_free_channel(dsp->tx_chan); + if (!IS_ERR_OR_NULL(dsp->rx_chan)) + mbox_free_channel(dsp->rx_chan); +} + +static int sun8i_dsp_rproc_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct device *dev = &pdev->dev; + struct sun8i_dsp_rproc *dsp; + const char *firmware_name; + struct rproc *rproc; + int i, ret; + u32 freq; + + firmware_name = NULL; + of_property_read_string(np, "firmware-name", &firmware_name); + rproc = devm_rproc_alloc(dev, dev_name(dev), &sun8i_dsp_rproc_ops, + firmware_name, sizeof(struct sun8i_dsp_rproc)); + if (!rproc) + return -ENOMEM; + + dev_set_drvdata(dev, rproc); + dsp = rproc->priv; + + i = of_property_match_string(np, "reg-names", "cfg"); + if (i < 0) + return -EINVAL; + + dsp->cfg_base = devm_platform_ioremap_resource(pdev, i); + if (IS_ERR(dsp->cfg_base)) + return dev_err_probe(dev, PTR_ERR(dsp->cfg_base), + "Failed to map cfg\n"); + + dsp->cfg_clk = devm_clk_get(dev, "cfg"); + if (IS_ERR(dsp->cfg_clk)) + return dev_err_probe(dev, PTR_ERR(dsp->cfg_clk), + "Failed to get %s clock\n", "cfg"); + + dsp->cfg_reset = devm_reset_control_get_exclusive(dev, "cfg"); + if (IS_ERR(dsp->cfg_reset)) + return dev_err_probe(dev, PTR_ERR(dsp->cfg_reset), + "Failed to get %s reset\n", "cfg"); + + dsp->cfg_reset = devm_reset_control_get_exclusive(dev, "dbg"); + if (IS_ERR(dsp->cfg_reset)) + return dev_err_probe(dev, PTR_ERR(dsp->cfg_reset), + "Failed to get %s reset\n", "dbg"); + + dsp->dsp_clk = devm_clk_get(dev, "dsp"); + if (IS_ERR(dsp->dsp_clk)) + return dev_err_probe(dev, PTR_ERR(dsp->dsp_clk), + "Failed to get %s clock\n", "dsp"); + + freq = SUN8I_DSP_CLK_FREQ; + of_property_read_u32(np, "clock-frequency", &freq); + ret = clk_set_rate(dsp->dsp_clk, freq); + if (ret) + return dev_err_probe(dev, ret, + "Failed to set clock frequency\n"); + + dsp->dsp_reset = devm_reset_control_get_exclusive(dev, "dsp"); + if (IS_ERR(dsp->dsp_reset)) + return dev_err_probe(dev, PTR_ERR(dsp->dsp_reset), + "Failed to get %s reset\n", "dsp"); + + dsp->client.dev = dev; + dsp->client.rx_callback = sun8i_dsp_rproc_mbox_rx_callback; + + ret = devm_add_action(dev, sun8i_dsp_rproc_mbox_free, dsp); + if (ret) + return ret; + + dsp->rx_chan = mbox_request_channel_byname(&dsp->client, "rx"); + if (IS_ERR(dsp->rx_chan)) + return dev_err_probe(dev, PTR_ERR(dsp->rx_chan), + "Failed to request RX channel\n"); + + dsp->tx_chan = mbox_request_channel_byname(&dsp->client, "tx"); + if (IS_ERR(dsp->tx_chan)) + return dev_err_probe(dev, PTR_ERR(dsp->tx_chan), + "Failed to request TX channel\n"); + + ret = devm_rproc_add(dev, rproc); + if (ret) + return dev_err_probe(dev, ret, "Failed to register rproc\n"); + + return 0; +} + +static const struct of_device_id sun8i_dsp_rproc_of_match[] = { + { .compatible = "allwinner,sun20i-d1-dsp" }, + {} +}; +MODULE_DEVICE_TABLE(of, sun8i_dsp_rproc_of_match); + +static struct platform_driver sun8i_dsp_rproc_driver = { + .probe = sun8i_dsp_rproc_probe, + .driver = { + .name = "sun8i-dsp-rproc", + .of_match_table = sun8i_dsp_rproc_of_match, + }, +}; +module_platform_driver(sun8i_dsp_rproc_driver); + +MODULE_AUTHOR("Samuel Holland "); +MODULE_DESCRIPTION("Allwinner sun8i DSP remoteproc driver"); +MODULE_LICENSE("GPL"); From 3524ea0fa2d0ea33998d2ad402c4756a089d7fe0 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Fri, 26 Feb 2021 10:27:51 +0000 Subject: [PATCH 075/120] rtc: sun6i: Add support for linear day storage Newer versions of the Allwinner RTC, as for instance found in the H616 SoC, no longer store a broken-down day/month/year representation in the RTC_DAY_REG, but just a linear day number. The user manual does not give any indication about the expected epoch time of this day count, but the BSP kernel uses the UNIX epoch, which allows easy support due to existing conversion functions in the kernel. Allow tagging a compatible string with a flag, and use that to mark those new RTCs. Then convert between a UNIX day number (converted into seconds) and the broken-down day representation using mktime64() and time64_to_tm() in the set_time/get_time functions. That enables support for the RTC in those new chips. Reviewed-by: Andre Przywara --- drivers/rtc/rtc-sun6i.c | 58 +++++++++++++++++++++++++++++------------ 1 file changed, 41 insertions(+), 17 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index adec1b14a8deb1..0228e9dfd96974 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -133,12 +133,15 @@ struct sun6i_rtc_clk_data { unsigned int has_auto_swt : 1; }; +#define RTC_LINEAR_DAY BIT(0) + struct sun6i_rtc_dev { struct rtc_device *rtc; const struct sun6i_rtc_clk_data *data; void __iomem *base; int irq; unsigned long alarm; + unsigned long flags; struct clk_hw hw; struct clk_hw *int_osc; @@ -471,17 +474,30 @@ static int sun6i_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) rtc_tm->tm_min = SUN6I_TIME_GET_MIN_VALUE(time); rtc_tm->tm_hour = SUN6I_TIME_GET_HOUR_VALUE(time); - rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); - rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date); - rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); - - rtc_tm->tm_mon -= 1; - - /* - * switch from (data_year->min)-relative offset to - * a (1900)-relative one - */ - rtc_tm->tm_year += SUN6I_YEAR_OFF; + if (chip->flags & RTC_LINEAR_DAY) { + struct tm tm; + + /* + * Newer chips store a linear day number, the manual + * does not mandate any epoch base. The BSP driver uses + * the UNIX epoch, let's just copy that, as it's the + * easiest anyway. + */ + time64_to_tm((date & 0xffff) * 3600ULL * 24, 0, &tm); + rtc_tm->tm_mday = tm.tm_mday; + rtc_tm->tm_mon = tm.tm_mon; + rtc_tm->tm_year = tm.tm_year; + } else { + rtc_tm->tm_mday = SUN6I_DATE_GET_DAY_VALUE(date); + rtc_tm->tm_mon = SUN6I_DATE_GET_MON_VALUE(date) - 1; + rtc_tm->tm_year = SUN6I_DATE_GET_YEAR_VALUE(date); + + /* + * switch from (data_year->min)-relative offset to + * a (1900)-relative one + */ + rtc_tm->tm_year += SUN6I_YEAR_OFF; + } return 0; } @@ -571,15 +587,21 @@ static int sun6i_rtc_settime(struct device *dev, struct rtc_time *rtc_tm) u32 date = 0; u32 time = 0; - rtc_tm->tm_year -= SUN6I_YEAR_OFF; rtc_tm->tm_mon += 1; - date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | - SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | - SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); + if (chip->flags & RTC_LINEAR_DAY) { + date = mktime64(rtc_tm->tm_year + 1900, rtc_tm->tm_mon, + rtc_tm->tm_mday, 0, 0, 0) / (3600ULL * 24); + } else { + rtc_tm->tm_year -= SUN6I_YEAR_OFF; + + date = SUN6I_DATE_SET_DAY_VALUE(rtc_tm->tm_mday) | + SUN6I_DATE_SET_MON_VALUE(rtc_tm->tm_mon) | + SUN6I_DATE_SET_YEAR_VALUE(rtc_tm->tm_year); - if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) - date |= SUN6I_LEAP_SET_VALUE(1); + if (is_leap_year(rtc_tm->tm_year + SUN6I_YEAR_MIN)) + date |= SUN6I_LEAP_SET_VALUE(1); + } time = SUN6I_TIME_SET_SEC_VALUE(rtc_tm->tm_sec) | SUN6I_TIME_SET_MIN_VALUE(rtc_tm->tm_min) | @@ -678,6 +700,8 @@ static int sun6i_rtc_probe(struct platform_device *pdev) platform_set_drvdata(pdev, chip); + chip->flags = (unsigned long)of_device_get_match_data(&pdev->dev); + chip->irq = platform_get_irq(pdev, 0); if (chip->irq < 0) return chip->irq; From 3d4e09a165b9134ad9f3c987489d78478526dad9 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Wed, 21 Apr 2021 12:46:43 +0100 Subject: [PATCH 076/120] rtc: sun6i: Add Allwinner H616 support The H616 RTC changes its day storage to the newly introduced linear day scheme, so pair the new compatible string with this feature flag. So far the clock parts seem to be the same as the H6, so combine the compatible string with the existing H6 support bits. Signed-off-by: Andre Przywara --- drivers/rtc/rtc-sun6i.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index 0228e9dfd96974..ec0cd0ee539adf 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -382,6 +382,8 @@ static void __init sun50i_h6_rtc_clk_init(struct device_node *node) } CLK_OF_DECLARE_DRIVER(sun50i_h6_rtc_clk, "allwinner,sun50i-h6-rtc", sun50i_h6_rtc_clk_init); +CLK_OF_DECLARE_DRIVER(sun50i_h616_rtc_clk, "allwinner,sun50i-h616-rtc", + sun50i_h6_rtc_clk_init); /* * The R40 user manual is self-conflicting on whether the prescaler is @@ -773,6 +775,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { { .compatible = "allwinner,sun8i-v3-rtc" }, { .compatible = "allwinner,sun50i-h5-rtc" }, { .compatible = "allwinner,sun50i-h6-rtc" }, + { .compatible = "allwinner,sun50i-h616-rtc", + .data = (void *)RTC_LINEAR_DAY }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); From 6744fe8bf4694f5092542ca84f5a7487e1ab20f4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 21:51:03 -0500 Subject: [PATCH 077/120] [WIP] rtc: sun6i: Make fw_devlink happy This doesn't work, but it is good enough to let clock consumers probe. Signed-off-by: Samuel Holland --- drivers/rtc/rtc-sun6i.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/drivers/rtc/rtc-sun6i.c b/drivers/rtc/rtc-sun6i.c index ec0cd0ee539adf..39e8ad0887748f 100644 --- a/drivers/rtc/rtc-sun6i.c +++ b/drivers/rtc/rtc-sun6i.c @@ -697,8 +697,17 @@ static int sun6i_rtc_probe(struct platform_device *pdev) struct sun6i_rtc_dev *chip = sun6i_rtc; int ret; - if (!chip) - return -ENODEV; + if (!chip) { + chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL); + if (!chip) + return -ENOMEM; + + chip->base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(chip->base)) + return PTR_ERR(chip->base); + + spin_lock_init(&chip->lock); + } platform_set_drvdata(pdev, chip); @@ -777,6 +786,8 @@ static const struct of_device_id sun6i_rtc_dt_ids[] = { { .compatible = "allwinner,sun50i-h6-rtc" }, { .compatible = "allwinner,sun50i-h616-rtc", .data = (void *)RTC_LINEAR_DAY }, + { .compatible = "allwinner,sun20i-d1-rtc", + .data = (void *)RTC_LINEAR_DAY }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, sun6i_rtc_dt_ids); From 4406d2ece2441803ff1d3ac5f3d99a621cb5ed34 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 19 Jan 2020 15:52:21 -0600 Subject: [PATCH 078/120] soc: sunxi: sram: Actually marked claimed regions as claimed Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 42833e33a96cc8..20b5d38e6da828 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -254,6 +254,7 @@ int sunxi_sram_claim(struct device *dev) writel(val | ((device << sram_data->offset) & mask), base + sram_data->reg); + sram_desc->claimed = true; spin_unlock(&sram_lock); return 0; From de67022721cd10f6467717770784b9a864af3394 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 11 Jul 2021 10:56:17 -0500 Subject: [PATCH 079/120] soc: sunxi: sram: Map SRAM back to CPU on release Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 20b5d38e6da828..65dfc809469bc1 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -265,17 +265,26 @@ int sunxi_sram_release(struct device *dev) { const struct sunxi_sram_data *sram_data; struct sunxi_sram_desc *sram_desc; + unsigned int device; + u32 val, mask; if (!dev || !dev->of_node) return -EINVAL; - sram_data = sunxi_sram_of_parse(dev->of_node, NULL); + sram_data = sunxi_sram_of_parse(dev->of_node, &device); if (IS_ERR(sram_data)) return -EINVAL; sram_desc = to_sram_desc(sram_data); spin_lock(&sram_lock); + mask = GENMASK(sram_data->offset + sram_data->width - 1, + sram_data->offset); + val = readl(base + sram_data->reg); + val &= ~mask; + writel(val | ((~device << sram_data->offset) & mask), + base + sram_data->reg); + sram_desc->claimed = false; spin_unlock(&sram_lock); From 9ac742b1f6cfe546ec7d09bc334db9ab92b13029 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:47:08 -0500 Subject: [PATCH 080/120] soc: sunxi: sram: Fix debugfs file leak Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 65dfc809469bc1..681d53545dd891 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -106,6 +106,7 @@ static struct device *sram_dev; static LIST_HEAD(claimed_sram); static DEFINE_SPINLOCK(sram_lock); static void __iomem *base; +static struct dentry *debugfs_dir; static int sunxi_sram_show(struct seq_file *s, void *data) { @@ -342,7 +343,6 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { static int sunxi_sram_probe(struct platform_device *pdev) { struct resource *res; - struct dentry *d; struct regmap *emac_clock; const struct sunxi_sramc_variant *variant; @@ -359,11 +359,6 @@ static int sunxi_sram_probe(struct platform_device *pdev) of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - d = debugfs_create_file("sram", S_IRUGO, NULL, NULL, - &sunxi_sram_fops); - if (!d) - return -ENOMEM; - if (variant->num_emac_clocks > 0) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -372,6 +367,17 @@ static int sunxi_sram_probe(struct platform_device *pdev) return PTR_ERR(emac_clock); } + debugfs_dir = debugfs_create_dir("sunxi-sram", NULL); + debugfs_create_file("sram", S_IRUGO, debugfs_dir, NULL, + &sunxi_sram_fops); + + return 0; +} + +static int sunxi_sram_remove(struct platform_device *pdev) +{ + debugfs_remove(debugfs_dir); + return 0; } @@ -422,6 +428,7 @@ static struct platform_driver sunxi_sram_driver = { .of_match_table = sunxi_sram_dt_match, }, .probe = sunxi_sram_probe, + .remove = sunxi_sram_remove, }; module_platform_driver(sunxi_sram_driver); From 368ec7bb37966caa31ea1c67534d46ac18e03ff3 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:48:49 -0500 Subject: [PATCH 081/120] soc: sunxi: sram: Use devm_of_platform_populate Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 681d53545dd891..7b7d4474a6341a 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -345,6 +345,7 @@ static int sunxi_sram_probe(struct platform_device *pdev) struct resource *res; struct regmap *emac_clock; const struct sunxi_sramc_variant *variant; + int ret; sram_dev = &pdev->dev; @@ -357,8 +358,6 @@ static int sunxi_sram_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); - if (variant->num_emac_clocks > 0) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -367,6 +366,10 @@ static int sunxi_sram_probe(struct platform_device *pdev) return PTR_ERR(emac_clock); } + ret = devm_of_platform_populate(&pdev->dev); + if (ret) + return ret; + debugfs_dir = debugfs_create_dir("sunxi-sram", NULL); debugfs_create_file("sram", S_IRUGO, debugfs_dir, NULL, &sunxi_sram_fops); From 7e6a802a4fd3fa9cf50f6f6fb7803078f087805b Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:49:10 -0500 Subject: [PATCH 082/120] soc: sunxi: sram: Add support for D1 LDOs Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 71 ++++++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 7b7d4474a6341a..15714566515aab 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -18,9 +18,13 @@ #include #include #include +#include #include +#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 +#define SUNXI_SYS_LDO_CTRL_REG 0x150 + struct sunxi_sram_func { char *func; u8 val; @@ -293,7 +297,47 @@ int sunxi_sram_release(struct device *dev) } EXPORT_SYMBOL(sunxi_sram_release); +static const struct regulator_ops sunxi_ldo_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, +}; + +static const struct regulator_desc sun20i_d1_ldos[] = { + { + .name = "ldoa", + .supply_name = "ldo-in", + .of_match = "ldoa", + .regulators_node = "regulators", + .ops = &sunxi_ldo_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = BIT(5), + .min_uV = 1600005, /* nominally 1.8 V */ + .uV_step = 13333, + .vsel_reg = SUNXI_SYS_LDO_CTRL_REG, + .vsel_mask = GENMASK(7, 0), + }, + { + .name = "ldob", + .supply_name = "ldo-in", + .of_match = "ldob", + .regulators_node = "regulators", + .ops = &sunxi_ldo_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = BIT(6), + .min_uV = 1166675, /* nominally 1.5 V */ + .uV_step = 13333, + .vsel_reg = SUNXI_SYS_LDO_CTRL_REG, + .vsel_mask = GENMASK(15, 8), + }, +}; + struct sunxi_sramc_variant { + const struct regulator_desc *ldos; + int num_ldos; int num_emac_clocks; }; @@ -305,6 +349,12 @@ static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = { .num_emac_clocks = 1, }; +static const struct sunxi_sramc_variant sun20i_d1_sramc_variant = { + .ldos = sun20i_d1_ldos, + .num_ldos = ARRAY_SIZE(sun20i_d1_ldos), + .num_emac_clocks = 1, +}; + static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = { .num_emac_clocks = 1, }; @@ -313,7 +363,6 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = { .num_emac_clocks = 2, }; -#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30 static bool sunxi_sram_regmap_accessible_reg(struct device *dev, unsigned int reg) { @@ -321,6 +370,8 @@ static bool sunxi_sram_regmap_accessible_reg(struct device *dev, variant = of_device_get_match_data(dev); + if (reg == SUNXI_SYS_LDO_CTRL_REG) + return true; if (reg < SUNXI_SRAM_EMAC_CLOCK_REG) return false; if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4) @@ -334,7 +385,7 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = { .val_bits = 32, .reg_stride = 4, /* last defined register */ - .max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4, + .max_register = SUNXI_SYS_LDO_CTRL_REG, /* other devices have no business accessing other registers */ .readable_reg = sunxi_sram_regmap_accessible_reg, .writeable_reg = sunxi_sram_regmap_accessible_reg, @@ -358,7 +409,7 @@ static int sunxi_sram_probe(struct platform_device *pdev) if (IS_ERR(base)) return PTR_ERR(base); - if (variant->num_emac_clocks > 0) { + if (variant->num_ldos || variant->num_emac_clocks) { emac_clock = devm_regmap_init_mmio(&pdev->dev, base, &sunxi_sram_emac_clock_regmap); @@ -366,6 +417,20 @@ static int sunxi_sram_probe(struct platform_device *pdev) return PTR_ERR(emac_clock); } + if (variant->num_ldos) { + struct regulator_config config = { .dev = &pdev->dev }; + struct regulator_dev *rdev; + int i; + + for (i = 0; i < variant->num_ldos; ++i) { + const struct regulator_desc *desc = &variant->ldos[i]; + + rdev = devm_regulator_register(&pdev->dev, desc, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + } + } + ret = devm_of_platform_populate(&pdev->dev); if (ret) return ret; From 71178443be4142beaafb76be7710a4cf051fe3f7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:46:04 -0500 Subject: [PATCH 083/120] soc: sunxi: sram: Fix debugfs for A64 SRAM C Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 15714566515aab..1b4f1b5a119aa6 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -82,8 +82,8 @@ static struct sunxi_sram_desc sun4i_a10_sram_d = { static struct sunxi_sram_desc sun50i_a64_sram_c = { .data = SUNXI_SRAM_DATA("C", 0x4, 24, 1, - SUNXI_SRAM_MAP(0, 1, "cpu"), - SUNXI_SRAM_MAP(1, 0, "de2")), + SUNXI_SRAM_MAP(1, 0, "cpu"), + SUNXI_SRAM_MAP(0, 1, "de2")), }; static const struct of_device_id sunxi_sram_dt_ids[] = { From 292cc815d8a5772e08e0e26570c10d7331219e52 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:46:19 -0500 Subject: [PATCH 084/120] soc: sunxi: sram: Add D1 DSP SRAM Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 1b4f1b5a119aa6..3c9d2969c1e459 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -80,6 +80,12 @@ static struct sunxi_sram_desc sun4i_a10_sram_d = { SUNXI_SRAM_MAP(1, 1, "usb-otg")), }; +static struct sunxi_sram_desc sun20i_d1_dsp_sram = { + .data = SUNXI_SRAM_DATA("DSP", 0x8, 0, 1, + SUNXI_SRAM_MAP(1, 0, "cpu"), + SUNXI_SRAM_MAP(0, 1, "dsp")), +}; + static struct sunxi_sram_desc sun50i_a64_sram_c = { .data = SUNXI_SRAM_DATA("C", 0x4, 24, 1, SUNXI_SRAM_MAP(1, 0, "cpu"), @@ -99,6 +105,10 @@ static const struct of_device_id sunxi_sram_dt_ids[] = { .compatible = "allwinner,sun4i-a10-sram-d", .data = &sun4i_a10_sram_d.data, }, + { + .compatible = "allwinner,sun20i-d1-dsp-sram", + .data = &sun20i_d1_dsp_sram.data, + }, { .compatible = "allwinner,sun50i-a64-sram-c", .data = &sun50i_a64_sram_c.data, From d61e28a54ea0bfec67185743fd5edc9d29fb9407 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:46:45 -0500 Subject: [PATCH 085/120] soc: sunxi: sram: Add D1 syscon variant Signed-off-by: Samuel Holland --- drivers/soc/sunxi/sunxi_sram.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/soc/sunxi/sunxi_sram.c b/drivers/soc/sunxi/sunxi_sram.c index 3c9d2969c1e459..e1afb470193db1 100644 --- a/drivers/soc/sunxi/sunxi_sram.c +++ b/drivers/soc/sunxi/sunxi_sram.c @@ -480,6 +480,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = { .compatible = "allwinner,sun8i-h3-system-control", .data = &sun8i_h3_sramc_variant, }, + { + .compatible = "allwinner,sun20i-d1-system-control", + .data = &sun20i_d1_sramc_variant, + }, { .compatible = "allwinner,sun50i-a64-sram-controller", .data = &sun50i_a64_sramc_variant, From a13eb4ab7bfb623188a0dd7f4630836d162bfc3a Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 16 Jul 2021 21:33:16 -0500 Subject: [PATCH 086/120] spi: spi-sun6i: Use a struct for quirks Signed-off-by: Samuel Holland --- drivers/spi/spi-sun6i.c | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 23ad052528dbe7..125fd3052db5ad 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -85,7 +85,12 @@ #define SUN6I_TXDATA_REG 0x200 #define SUN6I_RXDATA_REG 0x300 +struct sun6i_spi_quirks { + unsigned long fifo_depth; +}; + struct sun6i_spi { + const struct sun6i_spi_quirks *quirks; struct spi_master *master; void __iomem *base_addr; dma_addr_t dma_addr_rx; @@ -99,7 +104,6 @@ struct sun6i_spi { const u8 *tx_buf; u8 *rx_buf; int len; - unsigned long fifo_depth; }; static inline u32 sun6i_spi_read(struct sun6i_spi *sspi, u32 reg) @@ -156,7 +160,7 @@ static inline void sun6i_spi_fill_fifo(struct sun6i_spi *sspi) u8 byte; /* See how much data we can fit */ - cnt = sspi->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi); + cnt = sspi->quirks->fifo_depth - sun6i_spi_get_tx_fifo_count(sspi); len = min((int)cnt, sspi->len); @@ -289,14 +293,14 @@ static int sun6i_spi_transfer_one(struct spi_master *master, * the hardcoded value used in old generation of Allwinner * SPI controller. (See spi-sun4i.c) */ - trig_level = sspi->fifo_depth / 4 * 3; + trig_level = sspi->quirks->fifo_depth / 4 * 3; } else { /* * Setup FIFO DMA request trigger level * We choose 1/2 of the full fifo depth, that value will * be used as DMA burst length. */ - trig_level = sspi->fifo_depth / 2; + trig_level = sspi->quirks->fifo_depth / 2; if (tfr->tx_buf) reg |= SUN6I_FIFO_CTL_TF_DRQ_EN; @@ -410,9 +414,9 @@ static int sun6i_spi_transfer_one(struct spi_master *master, reg = SUN6I_INT_CTL_TC; if (!use_dma) { - if (rx_len > sspi->fifo_depth) + if (rx_len > sspi->quirks->fifo_depth) reg |= SUN6I_INT_CTL_RF_RDY; - if (tx_len > sspi->fifo_depth) + if (tx_len > sspi->quirks->fifo_depth) reg |= SUN6I_INT_CTL_TF_ERQ; } @@ -543,7 +547,7 @@ static bool sun6i_spi_can_dma(struct spi_master *master, * the fifo length we can just fill the fifo and wait for a single * irq, so don't bother setting up dma */ - return xfer->len > sspi->fifo_depth; + return xfer->len > sspi->quirks->fifo_depth; } static int sun6i_spi_probe(struct platform_device *pdev) @@ -582,7 +586,7 @@ static int sun6i_spi_probe(struct platform_device *pdev) } sspi->master = master; - sspi->fifo_depth = (unsigned long)of_device_get_match_data(&pdev->dev); + sspi->quirks = of_device_get_match_data(&pdev->dev); master->max_speed_hz = 100 * 1000 * 1000; master->min_speed_hz = 3 * 1000; @@ -696,9 +700,17 @@ static int sun6i_spi_remove(struct platform_device *pdev) return 0; } +static const struct sun6i_spi_quirks sun6i_a31_spi_quirks = { + .fifo_depth = SUN6I_FIFO_DEPTH, +}; + +static const struct sun6i_spi_quirks sun8i_h3_spi_quirks = { + .fifo_depth = SUN8I_FIFO_DEPTH, +}; + static const struct of_device_id sun6i_spi_match[] = { - { .compatible = "allwinner,sun6i-a31-spi", .data = (void *)SUN6I_FIFO_DEPTH }, - { .compatible = "allwinner,sun8i-h3-spi", .data = (void *)SUN8I_FIFO_DEPTH }, + { .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_quirks }, + { .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_quirks }, {} }; MODULE_DEVICE_TABLE(of, sun6i_spi_match); From b2033639a922f621d67ff34f2b82730545404b57 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Fri, 16 Jul 2021 21:46:31 -0500 Subject: [PATCH 087/120] spi: spi-sun6i: Add Allwinner R329 support Signed-off-by: Samuel Holland --- drivers/spi/spi-sun6i.c | 78 ++++++++++++++++++++++++++--------------- 1 file changed, 49 insertions(+), 29 deletions(-) diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 125fd3052db5ad..77a9e0646f3f3a 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -30,6 +30,7 @@ #define SUN6I_GBL_CTL_REG 0x04 #define SUN6I_GBL_CTL_BUS_ENABLE BIT(0) #define SUN6I_GBL_CTL_MASTER BIT(1) +#define SUN6I_GBL_CTL_SAMPLE_MODE BIT(2) #define SUN6I_GBL_CTL_TP BIT(7) #define SUN6I_GBL_CTL_RST BIT(31) @@ -87,6 +88,8 @@ struct sun6i_spi_quirks { unsigned long fifo_depth; + bool has_divider : 1; + bool has_new_sample_mode : 1; }; struct sun6i_spi { @@ -351,38 +354,44 @@ static int sun6i_spi_transfer_one(struct spi_master *master, sun6i_spi_write(sspi, SUN6I_TFR_CTL_REG, reg); /* Ensure that we have a parent clock fast enough */ - mclk_rate = clk_get_rate(sspi->mclk); - if (mclk_rate < (2 * tfr->speed_hz)) { - clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); + if (sspi->quirks->has_divider) { mclk_rate = clk_get_rate(sspi->mclk); - } + if (mclk_rate < (2 * tfr->speed_hz)) { + clk_set_rate(sspi->mclk, 2 * tfr->speed_hz); + mclk_rate = clk_get_rate(sspi->mclk); + } - /* - * Setup clock divider. - * - * We have two choices there. Either we can use the clock - * divide rate 1, which is calculated thanks to this formula: - * SPI_CLK = MOD_CLK / (2 ^ cdr) - * Or we can use CDR2, which is calculated with the formula: - * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) - * Wether we use the former or the latter is set through the - * DRS bit. - * - * First try CDR2, and if we can't reach the expected - * frequency, fall back to CDR1. - */ - div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); - div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); - if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { - reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; - tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); + /* + * Setup clock divider. + * + * We have two choices there. Either we can use the clock + * divide rate 1, which is calculated thanks to this formula: + * SPI_CLK = MOD_CLK / (2 ^ cdr) + * Or we can use CDR2, which is calculated with the formula: + * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) + * Wether we use the former or the latter is set through the + * DRS bit. + * + * First try CDR2, and if we can't reach the expected + * frequency, fall back to CDR1. + */ + div_cdr1 = DIV_ROUND_UP(mclk_rate, tfr->speed_hz); + div_cdr2 = DIV_ROUND_UP(div_cdr1, 2); + if (div_cdr2 <= (SUN6I_CLK_CTL_CDR2_MASK + 1)) { + reg = SUN6I_CLK_CTL_CDR2(div_cdr2 - 1) | SUN6I_CLK_CTL_DRS; + tfr->effective_speed_hz = mclk_rate / (2 * div_cdr2); + } else { + div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); + reg = SUN6I_CLK_CTL_CDR1(div); + tfr->effective_speed_hz = mclk_rate / (1 << div); + } + sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); } else { - div = min(SUN6I_CLK_CTL_CDR1_MASK, order_base_2(div_cdr1)); - reg = SUN6I_CLK_CTL_CDR1(div); - tfr->effective_speed_hz = mclk_rate / (1 << div); + clk_set_rate(sspi->mclk, tfr->speed_hz); + mclk_rate = clk_get_rate(sspi->mclk); + tfr->effective_speed_hz = mclk_rate; } - sun6i_spi_write(sspi, SUN6I_CLK_CTL_REG, reg); /* Finally enable the bus - doing so before might raise SCK to HIGH */ reg = sun6i_spi_read(sspi, SUN6I_GBL_CTL_REG); reg |= SUN6I_GBL_CTL_BUS_ENABLE; @@ -492,6 +501,7 @@ static int sun6i_spi_runtime_resume(struct device *dev) struct spi_master *master = dev_get_drvdata(dev); struct sun6i_spi *sspi = spi_master_get_devdata(master); int ret; + u32 reg; ret = clk_prepare_enable(sspi->hclk); if (ret) { @@ -511,8 +521,10 @@ static int sun6i_spi_runtime_resume(struct device *dev) goto err2; } - sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, - SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP); + reg = SUN6I_GBL_CTL_MASTER | SUN6I_GBL_CTL_TP; + if (sspi->quirks->has_new_sample_mode) + reg |= SUN6I_GBL_CTL_SAMPLE_MODE; + sun6i_spi_write(sspi, SUN6I_GBL_CTL_REG, reg); return 0; @@ -702,15 +714,23 @@ static int sun6i_spi_remove(struct platform_device *pdev) static const struct sun6i_spi_quirks sun6i_a31_spi_quirks = { .fifo_depth = SUN6I_FIFO_DEPTH, + .has_divider = true, }; static const struct sun6i_spi_quirks sun8i_h3_spi_quirks = { .fifo_depth = SUN8I_FIFO_DEPTH, + .has_divider = true, +}; + +static const struct sun6i_spi_quirks sun50i_r329_spi_quirks = { + .fifo_depth = SUN8I_FIFO_DEPTH, + .has_new_sample_mode = true, }; static const struct of_device_id sun6i_spi_match[] = { { .compatible = "allwinner,sun6i-a31-spi", .data = &sun6i_a31_spi_quirks }, { .compatible = "allwinner,sun8i-h3-spi", .data = &sun8i_h3_spi_quirks }, + { .compatible = "allwinner,sun50i-r329-spi", .data = &sun50i_r329_spi_quirks }, {} }; MODULE_DEVICE_TABLE(of, sun6i_spi_match); From 3e272aa4b4364c227f0f56f45958cc77a1b26528 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 23 Jun 2021 20:25:05 -0500 Subject: [PATCH 088/120] thermal/of: Remove duplicate null check Signed-off-by: Samuel Holland --- drivers/thermal/thermal_of.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/drivers/thermal/thermal_of.c b/drivers/thermal/thermal_of.c index 6379f26a335f64..3d1527ba003f84 100644 --- a/drivers/thermal/thermal_of.c +++ b/drivers/thermal/thermal_of.c @@ -555,10 +555,6 @@ void thermal_zone_of_sensor_unregister(struct device *dev, tz = tzd->devdata; - /* no __thermal_zone, nothing to be done */ - if (!tz) - return; - /* stop temperature polling */ thermal_zone_device_disable(tzd); From 1f563b3f8d3eb7f749c05d9a13797493862de903 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:03:12 -0500 Subject: [PATCH 089/120] dt-bindings: thermal: sun8i: Add compatible for D1 thermal sensor Signed-off-by: Samuel Holland --- .../thermal/allwinner,sun8i-a83t-ths.yaml | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml index 6e0b110153b01f..f72ceef424bdba 100644 --- a/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml +++ b/Documentation/devicetree/bindings/thermal/allwinner,sun8i-a83t-ths.yaml @@ -16,6 +16,7 @@ properties: - allwinner,sun8i-a83t-ths - allwinner,sun8i-h3-ths - allwinner,sun8i-r40-ths + - allwinner,sun20i-d1-ths - allwinner,sun50i-a64-ths - allwinner,sun50i-a100-ths - allwinner,sun50i-h5-ths @@ -55,6 +56,10 @@ properties: - 0 - 1 + vref-supply: + description: + Regulator for the analog reference voltage + allOf: - if: properties: @@ -84,7 +89,9 @@ allOf: properties: compatible: contains: - const: allwinner,sun8i-h3-ths + enum: + - allwinner,sun8i-h3-ths + - allwinner,sun20i-d1-ths then: properties: @@ -103,6 +110,7 @@ allOf: enum: - allwinner,sun8i-h3-ths - allwinner,sun8i-r40-ths + - allwinner,sun20i-d1-ths - allwinner,sun50i-a64-ths - allwinner,sun50i-a100-ths - allwinner,sun50i-h5-ths @@ -114,6 +122,17 @@ allOf: - clock-names - resets + - if: + properties: + compatible: + contains: + enum: + - allwinner,sun20i-d1-ths + + then: + required: + - vref-supply + required: - compatible - reg From b569c6e72d3e5f01a79b3b40638fdff486c6bd1d Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:04:52 -0500 Subject: [PATCH 090/120] thermal: sun8i: Fill in the unknown field name Signed-off-by: Samuel Holland --- drivers/thermal/sun8i_thermal.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index d9cd23cbb6717e..5a22388f5373ce 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -50,7 +50,8 @@ #define SUN8I_THS_CTRL2_T_ACQ1(x) ((GENMASK(15, 0) & (x)) << 16) #define SUN8I_THS_DATA_IRQ_STS(x) BIT(x + 8) -#define SUN50I_THS_CTRL0_T_ACQ(x) ((GENMASK(15, 0) & (x)) << 16) +#define SUN50I_THS_CTRL0_T_ACQ(x) (GENMASK(15, 0) & (x)) +#define SUN50I_THS_CTRL0_FS_DIV(x) ((GENMASK(15, 0) & (x)) << 16) #define SUN50I_THS_FILTER_EN BIT(2) #define SUN50I_THS_FILTER_TYPE(x) (GENMASK(1, 0) & (x)) #define SUN50I_H6_THS_PC_TEMP_PERIOD(x) ((GENMASK(19, 0) & (x)) << 12) @@ -417,12 +418,6 @@ static int sun8i_h3_thermal_init(struct ths_device *tmdev) return 0; } -/* - * Without this undocumented value, the returned temperatures would - * be higher than real ones by about 20C. - */ -#define SUN50I_H6_CTRL0_UNK 0x0000002f - static int sun50i_h6_thermal_init(struct ths_device *tmdev) { int val; @@ -435,7 +430,8 @@ static int sun50i_h6_thermal_init(struct ths_device *tmdev) * = 479 */ regmap_write(tmdev->regmap, SUN50I_THS_CTRL0, - SUN50I_H6_CTRL0_UNK | SUN50I_THS_CTRL0_T_ACQ(479)); + SUN50I_THS_CTRL0_T_ACQ(47) | + SUN50I_THS_CTRL0_FS_DIV(479)); /* average over 4 samples */ regmap_write(tmdev->regmap, SUN50I_H6_THS_MFC, SUN50I_THS_FILTER_EN | From 2070d3dc1e8e8590241f3acac91d315c1b005201 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 23 Jun 2021 19:29:37 -0500 Subject: [PATCH 091/120] thermal: sun8i: Set the event type for new samples Signed-off-by: Samuel Holland --- drivers/thermal/sun8i_thermal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index 5a22388f5373ce..48ce46762e1f24 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -192,7 +192,7 @@ static irqreturn_t sun8i_irq_thread(int irq, void *data) for_each_set_bit(i, &irq_bitmap, tmdev->chip->sensor_num) { thermal_zone_device_update(tmdev->sensor[i].tzd, - THERMAL_EVENT_UNSPECIFIED); + THERMAL_EVENT_TEMP_SAMPLE); } return IRQ_HANDLED; From 53df3430ecf41c52e45ea20e2adc02eab5396e45 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 23 Jun 2021 19:30:10 -0500 Subject: [PATCH 092/120] thermal: sun8i: Use optional clock/reset getters Signed-off-by: Samuel Holland --- drivers/thermal/sun8i_thermal.c | 34 +++++++++------------------------ 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index 48ce46762e1f24..a24b892984f83c 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -66,8 +66,6 @@ struct tsensor { }; struct ths_thermal_chip { - bool has_mod_clk; - bool has_bus_clk_reset; int sensor_num; int offset; int scale; @@ -335,21 +333,17 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) if (IS_ERR(tmdev->regmap)) return PTR_ERR(tmdev->regmap); - if (tmdev->chip->has_bus_clk_reset) { - tmdev->reset = devm_reset_control_get(dev, NULL); - if (IS_ERR(tmdev->reset)) - return PTR_ERR(tmdev->reset); + tmdev->reset = devm_reset_control_get_optional(dev, NULL); + if (IS_ERR(tmdev->reset)) + return PTR_ERR(tmdev->reset); - tmdev->bus_clk = devm_clk_get(&pdev->dev, "bus"); - if (IS_ERR(tmdev->bus_clk)) - return PTR_ERR(tmdev->bus_clk); - } + tmdev->bus_clk = devm_clk_get_optional(&pdev->dev, "bus"); + if (IS_ERR(tmdev->bus_clk)) + return PTR_ERR(tmdev->bus_clk); - if (tmdev->chip->has_mod_clk) { - tmdev->mod_clk = devm_clk_get(&pdev->dev, "mod"); - if (IS_ERR(tmdev->mod_clk)) - return PTR_ERR(tmdev->mod_clk); - } + tmdev->mod_clk = devm_clk_get_optional(&pdev->dev, "mod"); + if (IS_ERR(tmdev->mod_clk)) + return PTR_ERR(tmdev->mod_clk); ret = reset_control_deassert(tmdev->reset); if (ret) @@ -552,8 +546,6 @@ static const struct ths_thermal_chip sun8i_h3_ths = { .sensor_num = 1, .scale = 1211, .offset = 217000, - .has_mod_clk = true, - .has_bus_clk_reset = true, .temp_data_base = SUN8I_THS_TEMP_DATA, .calibrate = sun8i_h3_ths_calibrate, .init = sun8i_h3_thermal_init, @@ -565,8 +557,6 @@ static const struct ths_thermal_chip sun8i_r40_ths = { .sensor_num = 2, .offset = 251086, .scale = 1130, - .has_mod_clk = true, - .has_bus_clk_reset = true, .temp_data_base = SUN8I_THS_TEMP_DATA, .calibrate = sun8i_h3_ths_calibrate, .init = sun8i_h3_thermal_init, @@ -578,8 +568,6 @@ static const struct ths_thermal_chip sun50i_a64_ths = { .sensor_num = 3, .offset = 260890, .scale = 1170, - .has_mod_clk = true, - .has_bus_clk_reset = true, .temp_data_base = SUN8I_THS_TEMP_DATA, .calibrate = sun8i_h3_ths_calibrate, .init = sun8i_h3_thermal_init, @@ -589,7 +577,6 @@ static const struct ths_thermal_chip sun50i_a64_ths = { static const struct ths_thermal_chip sun50i_a100_ths = { .sensor_num = 3, - .has_bus_clk_reset = true, .ft_deviation = 8000, .offset = 187744, .scale = 672, @@ -602,8 +589,6 @@ static const struct ths_thermal_chip sun50i_a100_ths = { static const struct ths_thermal_chip sun50i_h5_ths = { .sensor_num = 2, - .has_mod_clk = true, - .has_bus_clk_reset = true, .temp_data_base = SUN8I_THS_TEMP_DATA, .calibrate = sun8i_h3_ths_calibrate, .init = sun8i_h3_thermal_init, @@ -613,7 +598,6 @@ static const struct ths_thermal_chip sun50i_h5_ths = { static const struct ths_thermal_chip sun50i_h6_ths = { .sensor_num = 2, - .has_bus_clk_reset = true, .ft_deviation = 7000, .offset = 187744, .scale = 672, From f5f58e83604feac0cf1fdd539633aff4b3a37ef0 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 23 Jun 2021 20:17:46 -0500 Subject: [PATCH 093/120] thermal: sun8i: Ensure vref is powered Signed-off-by: Samuel Holland --- drivers/thermal/sun8i_thermal.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index a24b892984f83c..c4b993446b9a6b 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -84,6 +85,7 @@ struct ths_device { struct device *dev; struct regmap *regmap; struct reset_control *reset; + struct regulator *supply; struct clk *bus_clk; struct clk *mod_clk; struct tsensor sensor[MAX_SENSOR_NUM]; @@ -333,6 +335,10 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) if (IS_ERR(tmdev->regmap)) return PTR_ERR(tmdev->regmap); + tmdev->supply = devm_regulator_get(dev, "vref"); + if (IS_ERR(tmdev->supply)) + return PTR_ERR(tmdev->supply); + tmdev->reset = devm_reset_control_get_optional(dev, NULL); if (IS_ERR(tmdev->reset)) return PTR_ERR(tmdev->reset); @@ -345,10 +351,14 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) if (IS_ERR(tmdev->mod_clk)) return PTR_ERR(tmdev->mod_clk); - ret = reset_control_deassert(tmdev->reset); + ret = regulator_enable(tmdev->supply); if (ret) return ret; + ret = reset_control_deassert(tmdev->reset); + if (ret) + goto disable_supply; + ret = clk_prepare_enable(tmdev->bus_clk); if (ret) goto assert_reset; @@ -373,6 +383,8 @@ static int sun8i_ths_resource_init(struct ths_device *tmdev) clk_disable_unprepare(tmdev->bus_clk); assert_reset: reset_control_assert(tmdev->reset); +disable_supply: + regulator_disable(tmdev->supply); return ret; } @@ -527,6 +539,7 @@ static int sun8i_ths_remove(struct platform_device *pdev) clk_disable_unprepare(tmdev->mod_clk); clk_disable_unprepare(tmdev->bus_clk); reset_control_assert(tmdev->reset); + regulator_disable(tmdev->supply); return 0; } From 9f05fddd7544cd5251cc1e83aba11681cce1d1e0 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:05:08 -0500 Subject: [PATCH 094/120] thermal: sun8i: Add support for the D1 thermal sensor Signed-off-by: Samuel Holland --- drivers/thermal/sun8i_thermal.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/thermal/sun8i_thermal.c b/drivers/thermal/sun8i_thermal.c index c4b993446b9a6b..14de5be15ca8e3 100644 --- a/drivers/thermal/sun8i_thermal.c +++ b/drivers/thermal/sun8i_thermal.c @@ -577,6 +577,17 @@ static const struct ths_thermal_chip sun8i_r40_ths = { .calc_temp = sun8i_ths_calc_temp, }; +static const struct ths_thermal_chip sun20i_d1_ths = { + .sensor_num = 1, + .offset = 188147, + .scale = 672, + .temp_data_base = SUN50I_H6_THS_TEMP_DATA, + .calibrate = sun50i_h6_ths_calibrate, + .init = sun50i_h6_thermal_init, + .irq_ack = sun50i_h6_irq_ack, + .calc_temp = sun8i_ths_calc_temp, +}; + static const struct ths_thermal_chip sun50i_a64_ths = { .sensor_num = 3, .offset = 260890, @@ -625,6 +636,7 @@ static const struct of_device_id of_ths_match[] = { { .compatible = "allwinner,sun8i-a83t-ths", .data = &sun8i_a83t_ths }, { .compatible = "allwinner,sun8i-h3-ths", .data = &sun8i_h3_ths }, { .compatible = "allwinner,sun8i-r40-ths", .data = &sun8i_r40_ths }, + { .compatible = "allwinner,sun20i-d1-ths", .data = &sun20i_d1_ths }, { .compatible = "allwinner,sun50i-a64-ths", .data = &sun50i_a64_ths }, { .compatible = "allwinner,sun50i-a100-ths", .data = &sun50i_a100_ths }, { .compatible = "allwinner,sun50i-h5-ths", .data = &sun50i_h5_ths }, From 496cfd036af82d05cec3cae6a40115ff62a77042 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 6 Jun 2021 10:54:58 -0500 Subject: [PATCH 095/120] dt-bindings: watchdog: Add compatible for Allwinner D1 Signed-off-by: Samuel Holland --- .../devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml index 9aa3c313c49f2e..fa53cd50515bb3 100644 --- a/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml +++ b/Documentation/devicetree/bindings/watchdog/allwinner,sun4i-a10-wdt.yaml @@ -28,6 +28,7 @@ properties: - items: - const: allwinner,suniv-f1c100s-wdt - const: allwinner,sun4i-a10-wdt + - const: allwinner,sun20i-d1-wdt reg: maxItems: 1 From ed3744034b2fe7fc73de84cdb0b2f3f5c86f55f9 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 21:49:39 -0500 Subject: [PATCH 096/120] watchdog: sunxi_wdt: Add support for the D1 SoC Signed-off-by: Samuel Holland --- drivers/watchdog/sunxi_wdt.c | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/drivers/watchdog/sunxi_wdt.c b/drivers/watchdog/sunxi_wdt.c index b50757882a98a9..72ee7791736bc7 100644 --- a/drivers/watchdog/sunxi_wdt.c +++ b/drivers/watchdog/sunxi_wdt.c @@ -48,6 +48,7 @@ struct sunxi_wdt_reg { u8 wdt_timeout_shift; u8 wdt_reset_mask; u8 wdt_reset_val; + u32 wdt_cfg_key; }; struct sunxi_wdt_dev { @@ -91,12 +92,14 @@ static int sunxi_wdt_restart(struct watchdog_device *wdt_dev, val = readl(wdt_base + regs->wdt_cfg); val &= ~(regs->wdt_reset_mask); val |= regs->wdt_reset_val; + val |= regs->wdt_cfg_key; writel(val, wdt_base + regs->wdt_cfg); /* Set lowest timeout and enable watchdog */ val = readl(wdt_base + regs->wdt_mode); val &= ~(WDT_TIMEOUT_MASK << regs->wdt_timeout_shift); val |= WDT_MODE_EN; + val |= regs->wdt_cfg_key; writel(val, wdt_base + regs->wdt_mode); /* @@ -109,6 +112,7 @@ static int sunxi_wdt_restart(struct watchdog_device *wdt_dev, mdelay(5); val = readl(wdt_base + regs->wdt_mode); val |= WDT_MODE_EN; + val |= regs->wdt_cfg_key; writel(val, wdt_base + regs->wdt_mode); } return 0; @@ -141,6 +145,7 @@ static int sunxi_wdt_set_timeout(struct watchdog_device *wdt_dev, reg = readl(wdt_base + regs->wdt_mode); reg &= ~(WDT_TIMEOUT_MASK << regs->wdt_timeout_shift); reg |= wdt_timeout_map[timeout] << regs->wdt_timeout_shift; + reg |= regs->wdt_cfg_key; writel(reg, wdt_base + regs->wdt_mode); sunxi_wdt_ping(wdt_dev); @@ -154,7 +159,7 @@ static int sunxi_wdt_stop(struct watchdog_device *wdt_dev) void __iomem *wdt_base = sunxi_wdt->wdt_base; const struct sunxi_wdt_reg *regs = sunxi_wdt->wdt_regs; - writel(0, wdt_base + regs->wdt_mode); + writel(regs->wdt_cfg_key, wdt_base + regs->wdt_mode); return 0; } @@ -176,11 +181,13 @@ static int sunxi_wdt_start(struct watchdog_device *wdt_dev) reg = readl(wdt_base + regs->wdt_cfg); reg &= ~(regs->wdt_reset_mask); reg |= regs->wdt_reset_val; + reg |= regs->wdt_cfg_key; writel(reg, wdt_base + regs->wdt_cfg); /* Enable watchdog */ reg = readl(wdt_base + regs->wdt_mode); reg |= WDT_MODE_EN; + reg |= regs->wdt_cfg_key; writel(reg, wdt_base + regs->wdt_mode); return 0; @@ -220,9 +227,20 @@ static const struct sunxi_wdt_reg sun6i_wdt_reg = { .wdt_reset_val = 0x01, }; +static const struct sunxi_wdt_reg sun20i_wdt_reg = { + .wdt_ctrl = 0x10, + .wdt_cfg = 0x14, + .wdt_mode = 0x18, + .wdt_timeout_shift = 4, + .wdt_reset_mask = 0x03, + .wdt_reset_val = 0x01, + .wdt_cfg_key = 0x16aa0000, +}; + static const struct of_device_id sunxi_wdt_dt_ids[] = { { .compatible = "allwinner,sun4i-a10-wdt", .data = &sun4i_wdt_reg }, { .compatible = "allwinner,sun6i-a31-wdt", .data = &sun6i_wdt_reg }, + { .compatible = "allwinner,sun20i-d1-wdt", .data = &sun20i_wdt_reg }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, sunxi_wdt_dt_ids); From 78b13a92f5a4f8155f1b670e82ca7d1487a12c7e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:47:55 -0500 Subject: [PATCH 097/120] ASoC: simple-card-utils: Fix overallocation of DLCs Signed-off-by: Samuel Holland --- sound/soc/generic/simple-card-utils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 677f7da93b4bb8..10c63b73900c66 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -640,8 +640,8 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, cnf_num += li->num[i].codecs; } - dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); - dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL); + dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); + dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dlcs), GFP_KERNEL); if (!dais || !dlcs) return -ENOMEM; From 1b1e31b38c86d09eafaa63d0160023f882c0ceba Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:50:41 -0500 Subject: [PATCH 098/120] ASoC: sun4i-i2s: Correct registers for multiple data pins Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun4i-i2s.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 1e9116cd365e58..98878b31de3741 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -115,13 +115,13 @@ #define SUN8I_I2S_FIFO_TX_REG 0x20 #define SUN8I_I2S_CHAN_CFG_REG 0x30 -#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(6, 4) +#define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM_MASK GENMASK(7, 4) #define SUN8I_I2S_CHAN_CFG_RX_SLOT_NUM(chan) ((chan - 1) << 4) -#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(2, 0) +#define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM_MASK GENMASK(3, 0) #define SUN8I_I2S_CHAN_CFG_TX_SLOT_NUM(chan) (chan - 1) -#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 #define SUN8I_I2S_TX_CHAN_SEL_REG 0x34 +#define SUN8I_I2S_TX_CHAN_MAP_REG 0x44 #define SUN8I_I2S_TX_CHAN_OFFSET_MASK GENMASK(13, 12) #define SUN8I_I2S_TX_CHAN_OFFSET(offset) (offset << 12) #define SUN8I_I2S_TX_CHAN_EN_MASK GENMASK(11, 4) @@ -138,12 +138,13 @@ #define SUN50I_H6_I2S_TX_CHAN_EN_MASK GENMASK(15, 0) #define SUN50I_H6_I2S_TX_CHAN_EN(num_chan) (((1 << num_chan) - 1)) -#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG 0x44 -#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG 0x48 +#define SUN50I_H6_I2S_TX_CHAN_SEL_REG(pin) (0x34 + 4 * (pin)) +#define SUN50I_H6_I2S_TX_CHAN_MAP0_REG(pin) (0x44 + 8 * (pin)) +#define SUN50I_H6_I2S_TX_CHAN_MAP1_REG(pin) (0x48 + 8 * (pin)) #define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 #define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 -#define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6C +#define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6c struct sun4i_i2s; @@ -523,13 +524,13 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, unsigned int lrck_period; /* Map the channels for playback and capture */ - regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0xFEDCBA98); - regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x76543210); + regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0xFEDCBA98); + regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x76543210); regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); /* Configure the channels */ - regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, + regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), SUN50I_H6_I2S_TX_CHAN_SEL_MASK, SUN50I_H6_I2S_TX_CHAN_SEL(channels)); regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_SEL_REG, @@ -563,7 +564,7 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, SUN8I_I2S_FMT0_LRCK_PERIOD_MASK, SUN8I_I2S_FMT0_LRCK_PERIOD(lrck_period)); - regmap_update_bits(i2s->regmap, SUN8I_I2S_TX_CHAN_SEL_REG, + regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), SUN50I_H6_I2S_TX_CHAN_EN_MASK, SUN50I_H6_I2S_TX_CHAN_EN(channels)); @@ -1210,9 +1211,9 @@ static const struct reg_default sun50i_h6_i2s_reg_defaults[] = { { SUN4I_I2S_DMA_INT_CTRL_REG, 0x00000000 }, { SUN4I_I2S_CLK_DIV_REG, 0x00000000 }, { SUN8I_I2S_CHAN_CFG_REG, 0x00000000 }, - { SUN8I_I2S_TX_CHAN_SEL_REG, 0x00000000 }, - { SUN50I_H6_I2S_TX_CHAN_MAP0_REG, 0x00000000 }, - { SUN50I_H6_I2S_TX_CHAN_MAP1_REG, 0x00000000 }, + { SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), 0x00000000 }, + { SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0x00000000 }, + { SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x00000000 }, { SUN50I_H6_I2S_RX_CHAN_SEL_REG, 0x00000000 }, { SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x00000000 }, { SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x00000000 }, From 2455f652713c7976b8cfc9a741543cead216d6ec Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:50:57 -0500 Subject: [PATCH 099/120] ASoC: sun4i-i2s: Also set capture DMA width Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun4i-i2s.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 98878b31de3741..17797f196b7b80 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -616,6 +616,7 @@ static int sun4i_i2s_hw_params(struct snd_pcm_substream *substream, params_physical_width(params)); return -EINVAL; } + i2s->capture_dma_data.addr_width = width; i2s->playback_dma_data.addr_width = width; sr = i2s->variant->get_sr(word_size); From 601976dd8e39842b1df10a233bd0bd11eb66a4c7 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:51:37 -0500 Subject: [PATCH 100/120] ASoC: sun4i-i2s: Add D1 variant Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun4i-i2s.c | 42 ++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 17797f196b7b80..c9d9af5092a4af 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -145,6 +145,8 @@ #define SUN50I_H6_I2S_RX_CHAN_SEL_REG 0x64 #define SUN50I_H6_I2S_RX_CHAN_MAP0_REG 0x68 #define SUN50I_H6_I2S_RX_CHAN_MAP1_REG 0x6c +#define SUN50I_H6_I2S_RX_CHAN_MAP2_REG 0x70 +#define SUN50I_H6_I2S_RX_CHAN_MAP3_REG 0x74 struct sun4i_i2s; @@ -176,6 +178,9 @@ struct sun4i_i2s_quirks { struct reg_field field_fmt_wss; struct reg_field field_fmt_sr; + unsigned int num_din_pins; + unsigned int num_dout_pins; + const struct sun4i_i2s_clk_div *bclk_dividers; unsigned int num_bclk_dividers; const struct sun4i_i2s_clk_div *mclk_dividers; @@ -526,8 +531,15 @@ static int sun50i_h6_i2s_set_chan_cfg(const struct sun4i_i2s *i2s, /* Map the channels for playback and capture */ regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP0_REG(0), 0xFEDCBA98); regmap_write(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_MAP1_REG(0), 0x76543210); - regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); - regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); + if (i2s->variant->num_din_pins > 1) { + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0x0F0E0D0C); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x0B0A0908); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP2_REG, 0x07060504); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP3_REG, 0x03020100); + } else { + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP0_REG, 0xFEDCBA98); + regmap_write(i2s->regmap, SUN50I_H6_I2S_RX_CHAN_MAP1_REG, 0x76543210); + } /* Configure the channels */ regmap_update_bits(i2s->regmap, SUN50I_H6_I2S_TX_CHAN_SEL_REG(0), @@ -1251,7 +1263,7 @@ static const struct regmap_config sun50i_h6_i2s_regmap_config = { .reg_bits = 32, .reg_stride = 4, .val_bits = 32, - .max_register = SUN50I_H6_I2S_RX_CHAN_MAP1_REG, + .max_register = SUN50I_H6_I2S_RX_CHAN_MAP3_REG, .cache_type = REGCACHE_FLAT, .reg_defaults = sun50i_h6_i2s_reg_defaults, .num_reg_defaults = ARRAY_SIZE(sun50i_h6_i2s_reg_defaults), @@ -1400,6 +1412,26 @@ static const struct sun4i_i2s_quirks sun8i_h3_i2s_quirks = { .set_fmt = sun8i_i2s_set_soc_fmt, }; +static const struct sun4i_i2s_quirks sun20i_d1_i2s_quirks = { + .has_reset = true, + .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, + .sun4i_i2s_regmap = &sun50i_h6_i2s_regmap_config, + .field_clkdiv_mclk_en = REG_FIELD(SUN4I_I2S_CLK_DIV_REG, 8, 8), + .field_fmt_wss = REG_FIELD(SUN4I_I2S_FMT0_REG, 0, 2), + .field_fmt_sr = REG_FIELD(SUN4I_I2S_FMT0_REG, 4, 6), + .num_din_pins = 4, + .num_dout_pins = 4, + .bclk_dividers = sun8i_i2s_clk_div, + .num_bclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), + .mclk_dividers = sun8i_i2s_clk_div, + .num_mclk_dividers = ARRAY_SIZE(sun8i_i2s_clk_div), + .get_bclk_parent_rate = sun8i_i2s_get_bclk_parent_rate, + .get_sr = sun8i_i2s_get_sr_wss, + .get_wss = sun8i_i2s_get_sr_wss, + .set_chan_cfg = sun50i_h6_i2s_set_chan_cfg, + .set_fmt = sun50i_h6_i2s_set_soc_fmt, +}; + static const struct sun4i_i2s_quirks sun50i_a64_codec_i2s_quirks = { .has_reset = true, .reg_offset_txdata = SUN8I_I2S_FIFO_TX_REG, @@ -1600,6 +1632,10 @@ static const struct of_device_id sun4i_i2s_match[] = { .compatible = "allwinner,sun8i-h3-i2s", .data = &sun8i_h3_i2s_quirks, }, + { + .compatible = "allwinner,sun20i-d1-i2s", + .data = &sun20i_d1_i2s_quirks, + }, { .compatible = "allwinner,sun50i-a64-codec-i2s", .data = &sun50i_a64_codec_i2s_quirks, From 125137686e8b8ceb02949c7fdd00b39c02438809 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:52:47 -0500 Subject: [PATCH 101/120] [WIP] ASoC: sun4i-spdif: Add support for separate resets Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun4i-spdif.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index a10949bf0ca1ed..c513efc86d9bed 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -26,10 +26,11 @@ #include #define SUN4I_SPDIF_CTL (0x00) + #define SUN4I_SPDIF_CTL_RST_RX BIT(12) #define SUN4I_SPDIF_CTL_MCLKDIV(v) ((v) << 4) /* v even */ #define SUN4I_SPDIF_CTL_MCLKOUTEN BIT(2) #define SUN4I_SPDIF_CTL_GEN BIT(1) - #define SUN4I_SPDIF_CTL_RESET BIT(0) + #define SUN4I_SPDIF_CTL_RST_TX BIT(0) #define SUN4I_SPDIF_TXCFG (0x04) #define SUN4I_SPDIF_TXCFG_SINGLEMOD BIT(31) @@ -193,7 +194,7 @@ static void sun4i_spdif_configure(struct sun4i_spdif_dev *host) const struct sun4i_spdif_quirks *quirks = host->quirks; /* soft reset SPDIF */ - regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RESET); + regmap_write(host->regmap, SUN4I_SPDIF_CTL, SUN4I_SPDIF_CTL_RST_TX); /* flush TX FIFO */ regmap_update_bits(host->regmap, SUN4I_SPDIF_FCTL, From 8d7e577f43c4c6bb740a4d9c5585e72bb86568e5 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:53:16 -0500 Subject: [PATCH 102/120] [WIP] ASoC: sun4i-spdif: Add support for separate clocks Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun4i-spdif.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index c513efc86d9bed..fd9580ff24ec21 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -173,6 +173,8 @@ * @val_fctl_ftx: TX FIFO flush bitmask. */ struct sun4i_spdif_quirks { + const char *rx_clk_name; + const char *tx_clk_name; unsigned int reg_dac_txdata; bool has_reset; unsigned int val_fctl_ftx; @@ -180,8 +182,9 @@ struct sun4i_spdif_quirks { struct sun4i_spdif_dev { struct platform_device *pdev; - struct clk *spdif_clk; struct clk *apb_clk; + struct clk *rx_clk; + struct clk *tx_clk; struct reset_control *rst; struct snd_soc_dai_driver cpu_dai_drv; struct regmap *regmap; @@ -313,7 +316,7 @@ static int sun4i_spdif_hw_params(struct snd_pcm_substream *substream, return -EINVAL; } - ret = clk_set_rate(host->spdif_clk, mclk); + ret = clk_set_rate(host->tx_clk, mclk); if (ret < 0) { dev_err(&pdev->dev, "Setting SPDIF clock rate for %d Hz failed!\n", mclk); @@ -426,23 +429,27 @@ static struct snd_soc_dai_driver sun4i_spdif_dai = { }; static const struct sun4i_spdif_quirks sun4i_a10_spdif_quirks = { + .tx_clk_name = "spdif", .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, }; static const struct sun4i_spdif_quirks sun6i_a31_spdif_quirks = { + .tx_clk_name = "spdif", .reg_dac_txdata = SUN4I_SPDIF_TXFIFO, .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, }; static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { + .tx_clk_name = "spdif", .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, .val_fctl_ftx = SUN4I_SPDIF_FCTL_FTX, .has_reset = true, }; static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = { + .tx_clk_name = "spdif", .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, .has_reset = true, @@ -477,7 +484,7 @@ static int sun4i_spdif_runtime_suspend(struct device *dev) { struct sun4i_spdif_dev *host = dev_get_drvdata(dev); - clk_disable_unprepare(host->spdif_clk); + clk_disable_unprepare(host->tx_clk); clk_disable_unprepare(host->apb_clk); return 0; @@ -488,12 +495,12 @@ static int sun4i_spdif_runtime_resume(struct device *dev) struct sun4i_spdif_dev *host = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(host->spdif_clk); + ret = clk_prepare_enable(host->tx_clk); if (ret) return ret; ret = clk_prepare_enable(host->apb_clk); if (ret) - clk_disable_unprepare(host->spdif_clk); + clk_disable_unprepare(host->tx_clk); return ret; } @@ -540,10 +547,11 @@ static int sun4i_spdif_probe(struct platform_device *pdev) return PTR_ERR(host->apb_clk); } - host->spdif_clk = devm_clk_get(&pdev->dev, "spdif"); - if (IS_ERR(host->spdif_clk)) { - dev_err(&pdev->dev, "failed to get a spdif clock.\n"); - return PTR_ERR(host->spdif_clk); + if (quirks->tx_clk_name) + host->tx_clk = devm_clk_get(&pdev->dev, quirks->tx_clk_name); + if (IS_ERR(host->tx_clk)) { + dev_err(&pdev->dev, "failed to get transmit clock.\n"); + return PTR_ERR(host->tx_clk); } host->dma_params_tx.addr = res->start + quirks->reg_dac_txdata; From 527e685cd79664cb4e787c2d398ae1c6d4fd7934 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:53:26 -0500 Subject: [PATCH 103/120] [WIP] ASoC: sun4i-spdif: Add D1 variant Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun4i-spdif.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index fd9580ff24ec21..6f5b3ad894746d 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -448,6 +448,14 @@ static const struct sun4i_spdif_quirks sun8i_h3_spdif_quirks = { .has_reset = true, }; +static const struct sun4i_spdif_quirks sun20i_d1_spdif_quirks = { + .rx_clk_name = "rx", + .tx_clk_name = "tx", + .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, + .val_fctl_ftx = SUN50I_H6_SPDIF_FCTL_FTX, + .has_reset = true, +}; + static const struct sun4i_spdif_quirks sun50i_h6_spdif_quirks = { .tx_clk_name = "spdif", .reg_dac_txdata = SUN8I_SPDIF_TXFIFO, @@ -468,6 +476,10 @@ static const struct of_device_id sun4i_spdif_of_match[] = { .compatible = "allwinner,sun8i-h3-spdif", .data = &sun8i_h3_spdif_quirks, }, + { + .compatible = "allwinner,sun20i-d1-spdif", + .data = &sun20i_d1_spdif_quirks, + }, { .compatible = "allwinner,sun50i-h6-spdif", .data = &sun50i_h6_spdif_quirks, From 5087f1fd63008e16d559fb4aca423e6373014922 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 12 Jun 2021 23:42:48 -0500 Subject: [PATCH 104/120] ASoC: sun20i-codec: New driver for D1 internal codec Signed-off-by: Samuel Holland --- sound/soc/sunxi/Kconfig | 6 + sound/soc/sunxi/Makefile | 1 + sound/soc/sunxi/sun20i-codec.c | 939 +++++++++++++++++++++++++++++++++ 3 files changed, 946 insertions(+) create mode 100644 sound/soc/sunxi/sun20i-codec.c diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index ddcaaa98d3cb33..d10a7f2ffaf986 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig @@ -30,6 +30,12 @@ config SND_SUN8I_CODEC_ANALOG Say Y or M if you want to add support for the analog controls for the codec embedded in newer Allwinner SoCs. +config SND_SUN20I_CODEC + tristate "Allwinner D1 (sun20i) Audio Codec" + depends on SOC_SUNXI || COMPILE_TEST + help + Say Y or M to add support for the audio codec in Allwinner D1 SoC. + config SND_SUN50I_CODEC_ANALOG tristate "Allwinner sun50i Codec Analog Controls Support" depends on (ARM64 && ARCH_SUNXI) || COMPILE_TEST diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile index a86be340a07610..7bbe2526e16ee3 100644 --- a/sound/soc/sunxi/Makefile +++ b/sound/soc/sunxi/Makefile @@ -3,6 +3,7 @@ obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o +obj-$(CONFIG_SND_SUN20I_CODEC) += sun20i-codec.o obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) += sun50i-codec-analog.o obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o diff --git a/sound/soc/sunxi/sun20i-codec.c b/sound/soc/sunxi/sun20i-codec.c new file mode 100644 index 00000000000000..f99e81f93a1bf6 --- /dev/null +++ b/sound/soc/sunxi/sun20i-codec.c @@ -0,0 +1,939 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SUN20I_CODEC_DAC_DPC 0x0000 +#define SUN20I_CODEC_DAC_DPC_EN_DA 31 +#define SUN20I_CODEC_DAC_DPC_HPF_EN 18 +#define SUN20I_CODEC_DAC_DPC_DVOL 12 +#define SUN20I_CODEC_DAC_VOL_CTRL 0x0004 +#define SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_SEL 16 +#define SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_L 8 +#define SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_R 0 +#define SUN20I_CODEC_DAC_FIFOC 0x0010 +#define SUN20I_CODEC_DAC_FIFOC_FS 29 +#define SUN20I_CODEC_DAC_FIFOC_FIFO_MODE 24 +#define SUN20I_CODEC_DAC_FIFOC_DRQ_CLR_CNT 21 +#define SUN20I_CODEC_DAC_FIFOC_TRIG_LEVEL 8 +#define SUN20I_CODEC_DAC_FIFOC_MONO_EN 6 +#define SUN20I_CODEC_DAC_FIFOC_SAMPLE_BITS 5 +#define SUN20I_CODEC_DAC_FIFOC_DRQ_EN 4 +#define SUN20I_CODEC_DAC_FIFOC_FIFO_FLUSH 0 +#define SUN20I_CODEC_DAC_TXDATA 0x0020 +#define SUN20I_CODEC_DAC_DEBUG 0x0028 +#define SUN20I_CODEC_DAC_DEBUG_DA_SWP 6 +#define SUN20I_CODEC_DAC_ADDA_LOOP_MODE 0 + +#define SUN20I_CODEC_ADC_FIFOC 0x0030 +#define SUN20I_CODEC_ADC_FIFOC_FS 29 +#define SUN20I_CODEC_ADC_FIFOC_EN_AD 28 +#define SUN20I_CODEC_ADC_FIFOC_FIFO_MODE 24 +#define SUN20I_CODEC_ADC_FIFOC_SAMPLE_BITS 16 +#define SUN20I_CODEC_ADC_FIFOC_TRIG_LEVEL 4 +#define SUN20I_CODEC_ADC_FIFOC_DRQ_EN 3 +#define SUN20I_CODEC_ADC_FIFOC_FIFO_FLUSH 0 +#define SUN20I_CODEC_ADC_VOL_CTRL 0x0034 +#define SUN20I_CODEC_ADC_VOL_CTRL_ADC3_VOL 16 +#define SUN20I_CODEC_ADC_VOL_CTRL_ADC2_VOL 8 +#define SUN20I_CODEC_ADC_VOL_CTRL_ADC1_VOL 0 +#define SUN20I_CODEC_ADC_RXDATA 0x0040 +#define SUN20I_CODEC_ADC_DEBUG 0x004c +#define SUN20I_CODEC_ADC_DEBUG_AD_SWP1 24 +#define SUN20I_CODEC_ADC_DIG_CTRL 0x0050 +#define SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN 16 +#define SUN20I_CODEC_ADC_DIG_CTRL_ADC_EN 0 + +#define SUN20I_CODEC_DAC_DAP_CTRL 0x00f0 +#define SUN20I_CODEC_DAC_DAP_CTRL_DAP_EN 31 +#define SUN20I_CODEC_DAC_DAP_CTRL_DAP_DRC_EN 29 +#define SUN20I_CODEC_DAC_DAP_CTRL_DAP_HPF_EN 28 + +#define SUN20I_CODEC_ADC_DAP_CTRL 0x00f8 +#define SUN20I_CODEC_ADC_DAP_CTRL_DAP0_EN 31 +#define SUN20I_CODEC_ADC_DAP_CTRL_DAP0_DRC_EN 29 +#define SUN20I_CODEC_ADC_DAP_CTRL_DAP0_HPF_EN 28 +#define SUN20I_CODEC_ADC_DAP_CTRL_DAP1_EN 27 +#define SUN20I_CODEC_ADC_DAP_CTRL_DAP1_DRC_EN 25 +#define SUN20I_CODEC_ADC_DAP_CTRL_DAP1_HPF_EN 24 + +#define SUN20I_CODEC_ADC1 0x0300 +#define SUN20I_CODEC_ADC1_ADC1_EN 31 +#define SUN20I_CODEC_ADC1_MICIN1_PGA_EN 30 +#define SUN20I_CODEC_ADC1_ADC1_DITHER_EN 29 +#define SUN20I_CODEC_ADC1_MICIN1_SIN_EN 28 +#define SUN20I_CODEC_ADC1_FMINL_EN 27 +#define SUN20I_CODEC_ADC1_FMINL_GAIN 26 +#define SUN20I_CODEC_ADC1_DITHER_LEVEL 24 +#define SUN20I_CODEC_ADC1_LINEINL_EN 23 +#define SUN20I_CODEC_ADC1_LINEINL_GAIN 22 +#define SUN20I_CODEC_ADC1_ADC1_PGA_GAIN 8 +#define SUN20I_CODEC_ADC2 0x0304 +#define SUN20I_CODEC_ADC2_ADC2_EN 31 +#define SUN20I_CODEC_ADC2_MICIN2_PGA_EN 30 +#define SUN20I_CODEC_ADC2_ADC2_DITHER_EN 29 +#define SUN20I_CODEC_ADC2_MICIN2_SIN_EN 28 +#define SUN20I_CODEC_ADC2_FMINR_EN 27 +#define SUN20I_CODEC_ADC2_FMINR_GAIN 26 +#define SUN20I_CODEC_ADC2_DITHER_LEVEL 24 +#define SUN20I_CODEC_ADC2_LINEINR_EN 23 +#define SUN20I_CODEC_ADC2_LINEINR_GAIN 22 +#define SUN20I_CODEC_ADC2_ADC2_PGA_GAIN 8 +#define SUN20I_CODEC_ADC3 0x0308 +#define SUN20I_CODEC_ADC3_ADC3_EN 31 +#define SUN20I_CODEC_ADC3_MICIN3_PGA_EN 30 +#define SUN20I_CODEC_ADC3_ADC3_DITHER_EN 29 +#define SUN20I_CODEC_ADC3_MICIN3_SIN_EN 28 +#define SUN20I_CODEC_ADC3_DITHER_LEVEL 24 +#define SUN20I_CODEC_ADC3_ADC3_PGA_GAIN 8 + +#define SUN20I_CODEC_DAC 0x0310 +#define SUN20I_CODEC_DAC_DACL_EN 15 +#define SUN20I_CODEC_DAC_DACR_EN 14 +#define SUN20I_CODEC_DAC_LINEOUTL_EN 13 +#define SUN20I_CODEC_DAC_LMUTE 12 +#define SUN20I_CODEC_DAC_LINEOUTR_EN 11 +#define SUN20I_CODEC_DAC_RMUTE 10 +#define SUN20I_CODEC_DAC_LINEOUTL_DIFFEN 6 +#define SUN20I_CODEC_DAC_LINEOUTR_DIFFEN 5 +#define SUN20I_CODEC_DAC_LINEOUT_VOL_CTRL 0 + +#define SUN20I_CODEC_MICBIAS 0x0318 +#define SUN20I_CODEC_MICBIAS_SELDETADCFS 28 +#define SUN20I_CODEC_MICBIAS_SELDETADCDB 26 +#define SUN20I_CODEC_MICBIAS_SELDETADCBF 24 +#define SUN20I_CODEC_MICBIAS_JACKDETEN 23 +#define SUN20I_CODEC_MICBIAS_SELDETADCDY 21 +#define SUN20I_CODEC_MICBIAS_MICADCEN 20 +#define SUN20I_CODEC_MICBIAS_POPFREE 19 +#define SUN20I_CODEC_MICBIAS_DET_MODE 18 +#define SUN20I_CODEC_MICBIAS_AUTOPLEN 17 +#define SUN20I_CODEC_MICBIAS_MICDETPL 16 +#define SUN20I_CODEC_MICBIAS_HMICBIASEN 15 +#define SUN20I_CODEC_MICBIAS_HMICBIASSEL 13 +#define SUN20I_CODEC_MICBIAS_HMIC_CHOPPER_EN 12 +#define SUN20I_CODEC_MICBIAS_HMIC_CHOPPER_CLK 10 +#define SUN20I_CODEC_MICBIAS_MMICBIASEN 7 +#define SUN20I_CODEC_MICBIAS_MMICBIASSEL 5 +#define SUN20I_CODEC_MICBIAS_MMIC_CHOPPER_EN 4 +#define SUN20I_CODEC_MICBIAS_MMIC_CHOPPER_CLK 2 + +/* TODO */ +#define SUN20I_CODEC_RAMP 0x031c +#define SUN20I_CODEC_RAMP_HP_PULL_OUT_EN 15 + +#define SUN20I_CODEC_HMIC_CTRL 0x0328 +#define SUN20I_CODEC_HMIC_CTRL_SAMPLE_SELECT 21 +#define SUN20I_CODEC_HMIC_CTRL_MDATA_THRESHOLD 16 +#define SUN20I_CODEC_HMIC_CTRL_SF 14 +#define SUN20I_CODEC_HMIC_CTRL_M 10 +#define SUN20I_CODEC_HMIC_CTRL_N 6 +#define SUN20I_CODEC_HMIC_CTRL_THRESH_DEBOUNCE 3 +#define SUN20I_CODEC_HMIC_CTRL_JACK_OUT_IRQ_EN 2 +#define SUN20I_CODEC_HMIC_CTRL_JACK_IN_IRQ_EN 1 +#define SUN20I_CODEC_HMIC_CTRL_MIC_DET_IRQ_EN 0 +#define SUN20I_CODEC_HMIC_STS 0x032c +#define SUN20I_CODEC_HMIC_STS_MDATA_DISCARD 13 +#define SUN20I_CODEC_HMIC_STS_HMIC_DATA 8 +#define SUN20I_CODEC_HMIC_STS_JACK_OUT_IRQ 4 +#define SUN20I_CODEC_HMIC_STS_JACK_IN_IRQ 3 +#define SUN20I_CODEC_HMIC_STS_MIC_DET_IRQ 0 + +#define SUN20I_CODEC_HP2 0x0340 +#define SUN20I_CODEC_HP2_HPFB_BUF_EN 31 +#define SUN20I_CODEC_HP2_HEADPHONE_GAIN 28 +#define SUN20I_CODEC_HP2_HPFB_RES 26 +#define SUN20I_CODEC_HP2_HP_DRVEN 21 +#define SUN20I_CODEC_HP2_HP_DRVOUTEN 20 +#define SUN20I_CODEC_HP2_RSWITCH 19 +#define SUN20I_CODEC_HP2_RAMPEN 18 +#define SUN20I_CODEC_HP2_HPFB_IN_EN 17 +#define SUN20I_CODEC_HP2_RAMP_FINAL_CONTROL 16 +#define SUN20I_CODEC_HP2_RAMP_OUT_EN 15 +#define SUN20I_CODEC_HP2_RAMP_FINAL_STATE_RES 13 + +/* Not affected by codec bus clock/reset */ +#define SUN20I_CODEC_POWER 0x0348 +#define SUN20I_CODEC_POWER_ALDO_EN_MASK BIT(31) +#define SUN20I_CODEC_POWER_HPLDO_EN_MASK BIT(30) +#define SUN20I_CODEC_POWER_ALDO_VOLTAGE_MASK GENMASK(14, 12) +#define SUN20I_CODEC_POWER_HPLDO_VOLTAGE_MASK GENMASK(10, 8) + +#define SUN20I_CODEC_ADC_CUR 0x034c + +#define SUN20I_CODEC_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE|\ + SNDRV_PCM_FMTBIT_S20_LE|\ + SNDRV_PCM_FMTBIT_S32_LE) + +#define DRIVER_NAME "sun20i-codec" +#define PREFIX "allwinner," + +/* snd_soc_register_card() takes over drvdata, so the card must be first! */ +struct sun20i_codec { + struct snd_soc_card card; + struct snd_soc_dai_link dai_link; + struct snd_soc_dai_link_component dlcs[3]; + struct snd_dmaengine_dai_dma_data dma_data[2]; + + struct clk *bus_clk; + struct clk *adc_clk; + struct clk *dac_clk; + struct reset_control *reset; +}; + +static int sun20i_codec_dai_probe(struct snd_soc_dai *dai) +{ + struct sun20i_codec *codec = snd_soc_dai_get_drvdata(dai); + + snd_soc_dai_init_dma_data(dai, + &codec->dma_data[SNDRV_PCM_STREAM_PLAYBACK], + &codec->dma_data[SNDRV_PCM_STREAM_CAPTURE]); + + return 0; +} + +static struct clk *sun20i_codec_get_clk(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sun20i_codec *codec = snd_soc_dai_get_drvdata(dai); + + return substream->stream == SNDRV_PCM_STREAM_CAPTURE ? + codec->adc_clk : codec->dac_clk; +} + +static const unsigned int sun20i_codec_rates[] = { + 7350, 8000, 11025, 12000, 14700, 16000, 22050, 24000, + 29400, 32000, 44100, 48000, 88200, 96000, 176400, 192000, +}; + +static const struct snd_pcm_hw_constraint_list sun20i_codec_rate_lists[] = { + [SNDRV_PCM_STREAM_PLAYBACK] = { + .list = sun20i_codec_rates, + .count = ARRAY_SIZE(sun20i_codec_rates), + }, + [SNDRV_PCM_STREAM_CAPTURE] = { + .list = sun20i_codec_rates, + .count = ARRAY_SIZE(sun20i_codec_rates) - 4, /* max 48 kHz */ + }, +}; + +static int sun20i_codec_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + const struct snd_pcm_hw_constraint_list *list; + int ret; + + list = &sun20i_codec_rate_lists[substream->stream]; + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, list); + if (ret) + return ret; + + ret = clk_prepare_enable(sun20i_codec_get_clk(substream, dai)); + if (ret) + return ret; + + return 0; +} + +static void sun20i_codec_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + clk_disable_unprepare(sun20i_codec_get_clk(substream, dai)); +} + +static unsigned int sun20i_codec_get_clk_rate(unsigned int sample_rate) +{ + return (sample_rate % 4000) ? 22579200 : 24576000; +} + +static const unsigned short sun20i_codec_divisors[] = { + 512, 1024, 2048, 128, + 768, 1536, 3072, 256, +}; + +static int sun20i_codec_get_fs(unsigned int clk_rate, unsigned int sample_rate) +{ + unsigned int divisor = clk_rate / sample_rate; + int i; + + for (i = 0; i < ARRAY_SIZE(sun20i_codec_divisors); ++i) + if (sun20i_codec_divisors[i] == divisor) + return i; + + return -EINVAL; +} + +static int sun20i_codec_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct sun20i_codec *codec = snd_soc_dai_get_drvdata(dai); + struct snd_soc_component *component = dai->component; + unsigned int channels = params_channels(params); + unsigned int sample_bits = params_width(params); + unsigned int sample_rate = params_rate(params); + unsigned int clk_rate = sun20i_codec_get_clk_rate(sample_rate); + enum dma_slave_buswidth dma_width; + unsigned int reg; + int ret, val; + + switch (params_physical_width(params)) { + case 16: + dma_width = DMA_SLAVE_BUSWIDTH_2_BYTES; + break; + case 32: + dma_width = DMA_SLAVE_BUSWIDTH_4_BYTES; + break; + default: + dev_err(dai->dev, "Unsupported physical sample width: %d\n", + params_physical_width(params)); + return -EINVAL; + } + codec->dma_data[substream->stream].addr_width = dma_width; + + ret = clk_set_rate(sun20i_codec_get_clk(substream, dai), + sun20i_codec_get_clk_rate(sample_rate)); + if (ret) + return ret; + + reg = substream->stream == SNDRV_PCM_STREAM_CAPTURE ? + SUN20I_CODEC_ADC_FIFOC : SUN20I_CODEC_DAC_FIFOC; + + val = sun20i_codec_get_fs(clk_rate, sample_rate); + if (val < 0) + return val; + snd_soc_component_update_bits(component, reg, + 0x7 << SUN20I_CODEC_DAC_FIFOC_FS, + val << SUN20I_CODEC_DAC_FIFOC_FS); + + /* Data is at MSB for full 4-byte samples, otherwise at LSB. */ + val = sample_bits != 32; + snd_soc_component_update_bits(component, reg, + 0x1 << SUN20I_CODEC_DAC_FIFOC_FIFO_MODE, + val << SUN20I_CODEC_DAC_FIFOC_FIFO_MODE); + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + val = sample_bits > 16; + snd_soc_component_update_bits(component, reg, + 0x1 << SUN20I_CODEC_ADC_FIFOC_SAMPLE_BITS, + val << SUN20I_CODEC_ADC_FIFOC_SAMPLE_BITS); + + val = BIT(channels) - 1; + snd_soc_component_update_bits(component, SUN20I_CODEC_ADC_DIG_CTRL, + 0xf << SUN20I_CODEC_ADC_DIG_CTRL_ADC_EN, + val << SUN20I_CODEC_ADC_DIG_CTRL_ADC_EN); + } else { + val = sample_bits > 16; + snd_soc_component_update_bits(component, reg, + 0x1 << SUN20I_CODEC_DAC_FIFOC_SAMPLE_BITS, + val << SUN20I_CODEC_DAC_FIFOC_SAMPLE_BITS); + + val = channels == 1; + snd_soc_component_update_bits(component, reg, + 0x1 << SUN20I_CODEC_DAC_FIFOC_MONO_EN, + val << SUN20I_CODEC_DAC_FIFOC_MONO_EN); + } + + return 0; +} + +static int sun20i_codec_trigger(struct snd_pcm_substream *substream, int cmd, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + unsigned int reg, mask; + + if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { + reg = SUN20I_CODEC_ADC_FIFOC; + mask = BIT(SUN20I_CODEC_ADC_FIFOC_DRQ_EN); + } else { + reg = SUN20I_CODEC_DAC_FIFOC; + mask = BIT(SUN20I_CODEC_DAC_FIFOC_DRQ_EN); + } + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + case SNDRV_PCM_TRIGGER_RESUME: + mask |= BIT(SUN20I_CODEC_DAC_FIFOC_FIFO_FLUSH); + snd_soc_component_update_bits(component, reg, mask, mask); + break; + case SNDRV_PCM_TRIGGER_STOP: + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + case SNDRV_PCM_TRIGGER_SUSPEND: + snd_soc_component_update_bits(component, reg, mask, 0); + break; + default: + return -EINVAL; + } + + return 0; +} + +static const struct snd_soc_dai_ops sun20i_codec_dai_ops = { + .startup = sun20i_codec_startup, + .shutdown = sun20i_codec_shutdown, + .hw_params = sun20i_codec_hw_params, + .trigger = sun20i_codec_trigger, +}; + +static struct snd_soc_dai_driver sun20i_codec_dai = { + .name = DRIVER_NAME, + .probe = sun20i_codec_dai_probe, + .ops = &sun20i_codec_dai_ops, + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 3, /* ??? */ + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .formats = SUN20I_CODEC_PCM_FORMATS, + .sig_bits = 20, + }, + .playback = { + .stream_name = "Playback", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_CONTINUOUS, + .formats = SUN20I_CODEC_PCM_FORMATS, + .sig_bits = 20, + }, +}; + +static const DECLARE_TLV_DB_SCALE(sun20i_codec_boost_vol_scale, 0, 600, 0); +static const DECLARE_TLV_DB_SCALE(sun20i_codec_digital_vol_scale, -12000, 75, 1); +static const DECLARE_TLV_DB_SCALE(sun20i_codec_headphone_vol_scale, -4200, 600, 0); +/* FIXME */ +static const DECLARE_TLV_DB_SCALE(sun20i_codec_line_out_vol_scale, -4650, 150, 1); +/* FIXME */ +static const DECLARE_TLV_DB_SCALE(sun20i_codec_pga_vol_scale, 500, 100, 0); + +static const char *const sun20i_codec_line_out_mode_enum_text[] = { + "Single-Ended", "Differential" +}; + +static const SOC_ENUM_DOUBLE_DECL(sun20i_codec_line_out_mode_enum, + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_LINEOUTL_DIFFEN, + SUN20I_CODEC_DAC_LINEOUTR_DIFFEN, + sun20i_codec_line_out_mode_enum_text); + +static const struct snd_kcontrol_new sun20i_codec_controls[] = { + /* Digital Controls */ + SOC_DOUBLE_TLV("DAC Playback Volume", + SUN20I_CODEC_DAC_VOL_CTRL, + SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_L, + SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_R, + 0xc0, 0, sun20i_codec_digital_vol_scale), + SOC_SINGLE_TLV("ADC3 Capture Volume", + SUN20I_CODEC_ADC_VOL_CTRL, + SUN20I_CODEC_ADC_VOL_CTRL_ADC3_VOL, + 0xc0, 0, sun20i_codec_digital_vol_scale), + SOC_SINGLE_TLV("ADC2 Capture Volume", + SUN20I_CODEC_ADC_VOL_CTRL, + SUN20I_CODEC_ADC_VOL_CTRL_ADC2_VOL, + 0xc0, 0, sun20i_codec_digital_vol_scale), + SOC_SINGLE_TLV("ADC1 Capture Volume", + SUN20I_CODEC_ADC_VOL_CTRL, + SUN20I_CODEC_ADC_VOL_CTRL_ADC1_VOL, + 0xc0, 0, sun20i_codec_digital_vol_scale), + + /* Analog Controls */ + SOC_DOUBLE_R_TLV("FM Capture Volume", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC1_FMINL_GAIN, + 0x1, 0, sun20i_codec_boost_vol_scale), + SOC_DOUBLE_R_TLV("Line In Capture Volume", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC1_LINEINL_GAIN, + 0x1, 0, sun20i_codec_boost_vol_scale), + SOC_ENUM("Line Out Mode Playback Enum", + sun20i_codec_line_out_mode_enum), + SOC_SINGLE_TLV("Line Out Playback Volume", + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_LINEOUT_VOL_CTRL, + 0x1f, 0, sun20i_codec_line_out_vol_scale), + SOC_SINGLE_TLV("Headphone Playback Volume", + SUN20I_CODEC_HP2, + SUN20I_CODEC_HP2_HEADPHONE_GAIN, + 0x7, 1, sun20i_codec_headphone_vol_scale), +}; + +static const struct snd_kcontrol_new sun20i_codec_line_out_switch = + SOC_DAPM_DOUBLE("Line Out Playback Switch", + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_LMUTE, + SUN20I_CODEC_DAC_RMUTE, 1, 1); + +static const struct snd_kcontrol_new sun20i_codec_hp_switch = + SOC_DAPM_SINGLE("Headphone Playback Switch", + SUN20I_CODEC_HP2, + SUN20I_CODEC_HP2_HP_DRVOUTEN, 1, 0); + +static const struct snd_kcontrol_new sun20i_codec_adc12_mixer_controls[] = { + /* ADC1 Only */ + SOC_DAPM_SINGLE("Mic1 Capture Switch", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC1_MICIN1_SIN_EN, 1, 0), + /* Shared */ + SOC_DAPM_DOUBLE_R("FM Capture Switch", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC1_FMINL_EN, 1, 0), + /* Shared */ + SOC_DAPM_DOUBLE_R("Line In Capture Switch", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC1_LINEINL_EN, 1, 0), + /* ADC2 Only */ + SOC_DAPM_SINGLE("Mic2 Capture Switch", + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC2_MICIN2_SIN_EN, 1, 0), +}; + +static const struct snd_kcontrol_new sun20i_codec_adc3_mixer_controls[] = { + SOC_DAPM_SINGLE("Mic3 Capture Switch", + SUN20I_CODEC_ADC3, + SUN20I_CODEC_ADC3_MICIN3_SIN_EN, 1, 0), +}; + +static const struct snd_kcontrol_new sun20i_codec_mic1_volume = + SOC_DAPM_SINGLE_TLV("Capture Volume", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC1_ADC1_PGA_GAIN, + 0x1f, 0, sun20i_codec_pga_vol_scale); + +static const struct snd_kcontrol_new sun20i_codec_mic2_volume = + SOC_DAPM_SINGLE_TLV("Capture Volume", + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC2_ADC2_PGA_GAIN, + 0x1f, 0, sun20i_codec_pga_vol_scale); + +static const struct snd_kcontrol_new sun20i_codec_mic3_volume = + SOC_DAPM_SINGLE_TLV("Capture Volume", + SUN20I_CODEC_ADC3, + SUN20I_CODEC_ADC3_ADC3_PGA_GAIN, + 0x1f, 0, sun20i_codec_pga_vol_scale); + +static const struct snd_soc_dapm_widget sun20i_codec_widgets[] = { + /* Playback */ + SND_SOC_DAPM_OUTPUT("LINEOUTL"), + SND_SOC_DAPM_OUTPUT("LINEOUTR"), + + SND_SOC_DAPM_SWITCH("LINEOUTL Switch", + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_LINEOUTL_EN, 0, + &sun20i_codec_line_out_switch), + SND_SOC_DAPM_SWITCH("LINEOUTR Switch", + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_LINEOUTR_EN, 0, + &sun20i_codec_line_out_switch), + + SND_SOC_DAPM_OUTPUT("HPOUTL"), + SND_SOC_DAPM_OUTPUT("HPOUTR"), + + SND_SOC_DAPM_SWITCH("HPOUTL Switch", + SND_SOC_NOPM, 0, 0, &sun20i_codec_hp_switch), + SND_SOC_DAPM_SWITCH("HPOUTR Switch", + SND_SOC_NOPM, 0, 0, &sun20i_codec_hp_switch), + SND_SOC_DAPM_SUPPLY("Headphone Driver", + SUN20I_CODEC_HP2, + SUN20I_CODEC_HP2_HP_DRVEN, 0, NULL, 0), + + SND_SOC_DAPM_DAC("DACL", NULL, + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_DACL_EN, 0), + SND_SOC_DAPM_DAC("DACR", NULL, + SUN20I_CODEC_DAC, + SUN20I_CODEC_DAC_DACR_EN, 0), + SND_SOC_DAPM_SUPPLY("DAC", + SUN20I_CODEC_DAC_DPC, + SUN20I_CODEC_DAC_DPC_EN_DA, 0, NULL, 0), + + SND_SOC_DAPM_AIF_IN("DACL FIFO", "Playback", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_IN("DACR FIFO", "Playback", 1, + SND_SOC_NOPM, 0, 0), + + /* Capture */ + SND_SOC_DAPM_AIF_OUT("ADC1 FIFO", "Capture", 0, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("ADC2 FIFO", "Capture", 1, + SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("ADC3 FIFO", "Capture", 2, + SND_SOC_NOPM, 0, 0), + + SND_SOC_DAPM_ADC("ADC1", NULL, + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC1_ADC1_EN, 0), + SND_SOC_DAPM_ADC("ADC2", NULL, + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC2_ADC2_EN, 0), + SND_SOC_DAPM_ADC("ADC3", NULL, + SUN20I_CODEC_ADC3, + SUN20I_CODEC_ADC3_ADC3_EN, 0), + SND_SOC_DAPM_SUPPLY("ADC", + SUN20I_CODEC_ADC_FIFOC, + SUN20I_CODEC_ADC_FIFOC_EN_AD, 0, NULL, 0), + + SND_SOC_DAPM_MIXER_NAMED_CTL("ADC1 Mixer", SND_SOC_NOPM, 0, 0, + sun20i_codec_adc12_mixer_controls, 3), + SND_SOC_DAPM_MIXER_NAMED_CTL("ADC2 Mixer", SND_SOC_NOPM, 0, 0, + sun20i_codec_adc12_mixer_controls + 1, 3), + SND_SOC_DAPM_MIXER_NAMED_CTL("ADC3 Mixer", SND_SOC_NOPM, 0, 0, + sun20i_codec_adc3_mixer_controls, + ARRAY_SIZE(sun20i_codec_adc3_mixer_controls)), + + SND_SOC_DAPM_PGA("Mic1", + SUN20I_CODEC_ADC1, + SUN20I_CODEC_ADC1_MICIN1_PGA_EN, 0, + &sun20i_codec_mic1_volume, 1), + SND_SOC_DAPM_PGA("Mic2", + SUN20I_CODEC_ADC2, + SUN20I_CODEC_ADC2_MICIN2_PGA_EN, 0, + &sun20i_codec_mic2_volume, 1), + SND_SOC_DAPM_PGA("Mic3", + SUN20I_CODEC_ADC3, + SUN20I_CODEC_ADC3_MICIN3_PGA_EN, 0, + &sun20i_codec_mic3_volume, 1), + + SND_SOC_DAPM_INPUT("MICIN1"), + SND_SOC_DAPM_INPUT("MICIN2"), + SND_SOC_DAPM_INPUT("MICIN3"), + + SND_SOC_DAPM_INPUT("FMINL"), + SND_SOC_DAPM_INPUT("FMINR"), + + SND_SOC_DAPM_INPUT("LINEINL"), + SND_SOC_DAPM_INPUT("LINEINR"), + + SND_SOC_DAPM_SUPPLY("HBIAS", + SUN20I_CODEC_MICBIAS, + SUN20I_CODEC_MICBIAS_HMICBIASEN, 0, NULL, 0), + SND_SOC_DAPM_SUPPLY("MBIAS", + SUN20I_CODEC_MICBIAS, + SUN20I_CODEC_MICBIAS_MMICBIASEN, 0, NULL, 0), + + SND_SOC_DAPM_REGULATOR_SUPPLY("avcc", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("hpvcc", 0, 0), + SND_SOC_DAPM_REGULATOR_SUPPLY("vdd33", 0, 0), +}; + +static const struct snd_soc_dapm_route sun20i_codec_routes[] = { + /* Playback */ + { "LINEOUTL", NULL, "LINEOUTL Switch" }, + { "LINEOUTR", NULL, "LINEOUTR Switch" }, + + { "LINEOUTL Switch", "Line Out Playback Switch", "DACL" }, + { "LINEOUTR Switch", "Line Out Playback Switch", "DACR" }, + + { "HPOUTL", NULL, "HPOUTL Switch" }, + { "HPOUTR", NULL, "HPOUTR Switch" }, + + { "HPOUTL Switch", "Headphone Playback Switch", "DACL" }, + { "HPOUTR Switch", "Headphone Playback Switch", "DACR" }, + { "HPOUTL Switch", NULL, "Headphone Driver" }, + { "HPOUTR Switch", NULL, "Headphone Driver" }, + { "Headphone Driver", NULL, "hpvcc" }, + + { "DACL", NULL, "DACL FIFO" }, + { "DACR", NULL, "DACR FIFO" }, + { "DACL", NULL, "DAC" }, + { "DACR", NULL, "DAC" }, + { "DACL", NULL, "avcc" }, + { "DACR", NULL, "avcc" }, + + /* Capture */ + { "ADC1 FIFO", NULL, "ADC1" }, + { "ADC2 FIFO", NULL, "ADC2" }, + { "ADC3 FIFO", NULL, "ADC3" }, + + { "ADC1", NULL, "ADC1 Mixer" }, + { "ADC2", NULL, "ADC2 Mixer" }, + { "ADC3", NULL, "ADC3 Mixer" }, + { "ADC1", NULL, "ADC" }, + { "ADC2", NULL, "ADC" }, + { "ADC3", NULL, "ADC" }, + { "ADC1", NULL, "avcc" }, + { "ADC2", NULL, "avcc" }, + { "ADC3", NULL, "avcc" }, + + { "ADC1 Mixer", "Mic1 Capture Switch", "Mic1" }, + { "ADC2 Mixer", "Mic2 Capture Switch", "Mic2" }, + { "ADC3 Mixer", "Mic3 Capture Switch", "Mic3" }, + { "ADC1 Mixer", "FM Capture Switch", "FMINL" }, + { "ADC2 Mixer", "FM Capture Switch", "FMINR" }, + { "ADC1 Mixer", "Line In Capture Switch", "LINEINL" }, + { "ADC2 Mixer", "Line In Capture Switch", "LINEINR" }, + + { "Mic1", NULL, "MICIN1" }, + { "Mic2", NULL, "MICIN2" }, + { "Mic3", NULL, "MICIN3" }, + + { "HBIAS", NULL, "vdd33" }, + { "MBIAS", NULL, "vdd33" }, +}; + +static int sun20i_codec_component_probe(struct snd_soc_component *component) +{ + struct sun20i_codec *codec = snd_soc_component_get_drvdata(component); + int ret; + + ret = reset_control_deassert(codec->reset); + if (ret) + return ret; + + ret = clk_prepare_enable(codec->bus_clk); + if (ret) + goto err_assert_reset; + + /* Enable digital volume control. */ + snd_soc_component_update_bits(component, SUN20I_CODEC_DAC_VOL_CTRL, + 0x1 << SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_SEL, + 0x1 << SUN20I_CODEC_DAC_VOL_CTRL_DAC_VOL_SEL); + snd_soc_component_update_bits(component, SUN20I_CODEC_ADC_DIG_CTRL, + 0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN, + 0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN); + + return 0; + +err_assert_reset: + reset_control_assert(codec->reset); + + return ret; +} + +static void sun20i_codec_component_remove(struct snd_soc_component *component) +{ + struct sun20i_codec *codec = snd_soc_component_get_drvdata(component); + + clk_disable_unprepare(codec->bus_clk); + reset_control_assert(codec->reset); +} + +static const struct snd_soc_component_driver sun20i_codec_component = { + .controls = sun20i_codec_controls, + .num_controls = ARRAY_SIZE(sun20i_codec_controls), + .dapm_widgets = sun20i_codec_widgets, + .num_dapm_widgets = ARRAY_SIZE(sun20i_codec_widgets), + .dapm_routes = sun20i_codec_routes, + .num_dapm_routes = ARRAY_SIZE(sun20i_codec_routes), + .probe = sun20i_codec_component_probe, + .remove = sun20i_codec_component_remove, +}; + +static int sun20i_codec_init_card(struct device *dev, + struct sun20i_codec *codec) +{ + struct snd_soc_dai_link *dai_link = &codec->dai_link; + struct snd_soc_card *card = &codec->card; + int ret; + + codec->dlcs[0].of_node = dev->of_node; + codec->dlcs[0].dai_name = DRIVER_NAME; + codec->dlcs[1].name = "snd-soc-dummy"; + codec->dlcs[1].dai_name = "snd-soc-dummy-dai"; + codec->dlcs[2].of_node = dev->of_node; + + dai_link->name = DRIVER_NAME; + dai_link->stream_name = DRIVER_NAME; + dai_link->cpus = &codec->dlcs[0]; + dai_link->num_cpus = 1; + dai_link->codecs = &codec->dlcs[1]; + dai_link->num_codecs = 1; + dai_link->platforms = &codec->dlcs[2]; + dai_link->num_platforms = 1; + + card->name = DRIVER_NAME; + card->dev = dev; + card->owner = THIS_MODULE; + card->dai_link = dai_link; + card->num_links = 1; + card->fully_routed = true; + + ret = snd_soc_of_parse_audio_simple_widgets(card, PREFIX "widgets"); + if (ret) + return ret; + + ret = snd_soc_of_parse_audio_routing(card, PREFIX "routing"); + if (ret) + return ret; + + ret = snd_soc_of_parse_aux_devs(card, PREFIX "aux-devs"); + if (ret) + return ret; + + return 0; +} + +static const struct regmap_config sun20i_codec_regmap_config = { + .reg_bits = 32, + .reg_stride = 4, + .val_bits = 32, + .max_register = SUN20I_CODEC_ADC_CUR, +}; + +static const struct regulator_ops sun20i_codec_ldo_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_voltage_sel = regulator_get_voltage_sel_regmap, + .enable = regulator_enable_regmap, + .disable = regulator_disable_regmap, + .is_enabled = regulator_is_enabled_regmap, +}; + +static const struct regulator_desc sun20i_codec_ldos[] = { + { + .name = "aldo", + .supply_name = "vdd33", + .of_match = "aldo", + .regulators_node = "regulators", + .ops = &sun20i_codec_ldo_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = BIT(3), + .min_uV = 1650000, + .uV_step = 50000, + .vsel_reg = SUN20I_CODEC_POWER, + .vsel_mask = SUN20I_CODEC_POWER_ALDO_VOLTAGE_MASK, + .enable_reg = SUN20I_CODEC_POWER, + .enable_mask = SUN20I_CODEC_POWER_ALDO_EN_MASK, + }, + { + .name = "hpldo", + .supply_name = "hpldoin", + .of_match = "hpldo", + .regulators_node = "regulators", + .ops = &sun20i_codec_ldo_ops, + .type = REGULATOR_VOLTAGE, + .owner = THIS_MODULE, + .n_voltages = BIT(3), + .min_uV = 1650000, + .uV_step = 50000, + .vsel_reg = SUN20I_CODEC_POWER, + .vsel_mask = SUN20I_CODEC_POWER_HPLDO_VOLTAGE_MASK, + .enable_reg = SUN20I_CODEC_POWER, + .enable_mask = SUN20I_CODEC_POWER_HPLDO_EN_MASK, + }, +}; + +static int sun20i_codec_probe(struct platform_device *pdev) +{ + struct regulator_config config = { .dev = &pdev->dev }; + struct device *dev = &pdev->dev; + struct sun20i_codec *codec; + struct regulator_dev *rdev; + struct regmap *regmap; + struct resource *res; + void __iomem *base; + int i, ret; + + codec = devm_kzalloc(dev, sizeof(*codec), GFP_KERNEL); + if (!codec) + return -ENOMEM; + + dev_set_drvdata(dev, codec); + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return dev_err_probe(dev, PTR_ERR(base), + "Failed to map registers\n"); + + regmap = devm_regmap_init_mmio(dev, base, + &sun20i_codec_regmap_config); + if (IS_ERR(regmap)) + return dev_err_probe(dev, PTR_ERR(regmap), + "Failed to create regmap\n"); + + codec->bus_clk = devm_clk_get(dev, "bus"); + if (IS_ERR(codec->bus_clk)) + return dev_err_probe(dev, PTR_ERR(codec->bus_clk), + "Failed to get bus clock\n"); + + codec->adc_clk = devm_clk_get(dev, "adc"); + if (IS_ERR(codec->adc_clk)) + return dev_err_probe(dev, PTR_ERR(codec->adc_clk), + "Failed to get ADC clock\n"); + + codec->dac_clk = devm_clk_get(dev, "dac"); + if (IS_ERR(codec->dac_clk)) + return dev_err_probe(dev, PTR_ERR(codec->dac_clk), + "Failed to get DAC clock\n"); + + codec->reset = devm_reset_control_get_exclusive(dev, NULL); + if (IS_ERR(codec->reset)) + return dev_err_probe(dev, PTR_ERR(codec->reset), + "Failed to get reset\n"); + + for (i = 0; i < ARRAY_SIZE(sun20i_codec_ldos); ++i) { + const struct regulator_desc *desc = &sun20i_codec_ldos[i]; + + rdev = devm_regulator_register(dev, desc, &config); + if (IS_ERR(rdev)) + return PTR_ERR(rdev); + } + + ret = devm_snd_soc_register_component(dev, &sun20i_codec_component, + &sun20i_codec_dai, 1); + if (ret) + return dev_err_probe(dev, ret, "Failed to register component\n"); + + codec->dma_data[SNDRV_PCM_STREAM_PLAYBACK].addr = + res->start + SUN20I_CODEC_DAC_TXDATA; + codec->dma_data[SNDRV_PCM_STREAM_PLAYBACK].maxburst = 8; + codec->dma_data[SNDRV_PCM_STREAM_CAPTURE].addr = + res->start + SUN20I_CODEC_ADC_RXDATA; + codec->dma_data[SNDRV_PCM_STREAM_CAPTURE].maxburst = 8; + + ret = devm_snd_dmaengine_pcm_register(dev, NULL, 0); + if (ret) + return dev_err_probe(dev, ret, "Failed to register PCM\n"); + + ret = sun20i_codec_init_card(dev, codec); + if (ret) + return dev_err_probe(dev, ret, "Failed to initialize card\n"); + + ret = devm_snd_soc_register_card(dev, &codec->card); + if (ret) + return dev_err_probe(dev, ret, "Failed to register card\n"); + + return 0; +} + +static const struct of_device_id sun20i_codec_of_match[] = { + { .compatible = "allwinner,sun20i-d1-audio-codec" }, + {} +}; +MODULE_DEVICE_TABLE(of, sun20i_codec_of_match); + +static struct platform_driver sun20i_codec_driver = { + .driver = { + .name = DRIVER_NAME, + .of_match_table = sun20i_codec_of_match, + }, + .probe = sun20i_codec_probe, +}; +module_platform_driver(sun20i_codec_driver); + +MODULE_DESCRIPTION("Allwinner D1 (sun20i) codec driver"); +MODULE_AUTHOR("Samuel Holland "); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:sun20i-codec"); From 589dbedbbb856bdef576771529125022e725afe9 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Wed, 23 Jun 2021 21:18:47 -0500 Subject: [PATCH 105/120] [WIP] ASoC: sun20i-codec: What is this ramp thing? Signed-off-by: Samuel Holland --- sound/soc/sunxi/sun20i-codec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/sunxi/sun20i-codec.c b/sound/soc/sunxi/sun20i-codec.c index f99e81f93a1bf6..18551f5ef14eb3 100644 --- a/sound/soc/sunxi/sun20i-codec.c +++ b/sound/soc/sunxi/sun20i-codec.c @@ -711,6 +711,10 @@ static int sun20i_codec_component_probe(struct snd_soc_component *component) 0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN, 0x3 << SUN20I_CODEC_ADC_DIG_CTRL_ADC_VOL_EN); + /* Maaagic... */ + snd_soc_component_update_bits(component, SUN20I_CODEC_RAMP, + BIT(1) | BIT(0), BIT(0)); + return 0; err_assert_reset: From 407dfbe73bc78b800a527e0bf3e17b0878ea344e Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:37:01 -0500 Subject: [PATCH 106/120] [SPLIT] dt-bindings: Add compatibles for D1 Signed-off-by: Samuel Holland --- .../allwinner,sun6i-a31-hwspinlock.yaml | 9 +++- .../bindings/i2c/marvell,mv64xxx-i2c.yaml | 1 + .../nvmem/allwinner,sun4i-a10-sid.yaml | 5 +- .../sound/allwinner,sun4i-a10-i2s.yaml | 2 + .../sound/allwinner,sun4i-a10-spdif.yaml | 47 +++++++++++++++---- .../bindings/spi/allwinner,sun6i-a31-spi.yaml | 1 + .../allwinner,sun4i-a10-system-control.yaml | 5 ++ .../timer/allwinner,sun5i-a13-hstimer.yaml | 13 ++++- .../usb/allwinner,sun4i-a10-musb.yaml | 1 + 9 files changed, 71 insertions(+), 13 deletions(-) diff --git a/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml b/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml index 10e5a53e447b57..7b532d6ed951ff 100644 --- a/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml +++ b/Documentation/devicetree/bindings/hwlock/allwinner,sun6i-a31-hwspinlock.yaml @@ -15,7 +15,11 @@ description: properties: compatible: - const: allwinner,sun6i-a31-hwspinlock + oneOf: + - const: allwinner,sun6i-a31-hwspinlock + - items: + - const: allwinner,sun20i-d1-hwspinlock + - const: allwinner,sun6i-a31-hwspinlock reg: maxItems: 1 @@ -26,6 +30,9 @@ properties: resets: maxItems: 1 + interrupts: + maxItems: 1 + required: - compatible - reg diff --git a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml index f771c09aabfccd..e37ddad03439ee 100644 --- a/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml +++ b/Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml @@ -21,6 +21,7 @@ properties: - enum: - allwinner,sun8i-a23-i2c - allwinner,sun8i-a83t-i2c + - allwinner,sun20i-d1-i2c - allwinner,sun50i-a64-i2c - allwinner,sun50i-a100-i2c - allwinner,sun50i-h6-i2c diff --git a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml index 6687ab7203049a..e20381812ad3e3 100644 --- a/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml +++ b/Documentation/devicetree/bindings/nvmem/allwinner,sun4i-a10-sid.yaml @@ -22,7 +22,10 @@ properties: - const: allwinner,sun8i-h3-sid - const: allwinner,sun50i-a64-sid - items: - - const: allwinner,sun50i-a100-sid + - enum: + - allwinner,sun20i-d1-sid + - allwinner,sun50i-a100-sid + - allwinner,sun50i-h5-sid - const: allwinner,sun50i-a64-sid - const: allwinner,sun50i-h5-sid - const: allwinner,sun50i-h6-sid diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml index 39b66e9ce3e3a2..a9befbde9fa58f 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-i2s.yaml @@ -23,6 +23,7 @@ properties: - items: - const: allwinner,sun8i-v3-i2s - const: allwinner,sun8i-h3-i2s + - const: allwinner,sun20i-d1-i2s - const: allwinner,sun50i-a64-codec-i2s - items: - const: allwinner,sun50i-a64-i2s @@ -62,6 +63,7 @@ allOf: - allwinner,sun6i-a31-i2s - allwinner,sun8i-a83t-i2s - allwinner,sun8i-h3-i2s + - allwinner,sun20i-d1-i2s - allwinner,sun50i-a64-codec-i2s - allwinner,sun50i-h6-i2s diff --git a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml index 444a432912bb4e..1711cc14c74cbf 100644 --- a/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml +++ b/Documentation/devicetree/bindings/sound/allwinner,sun4i-a10-spdif.yaml @@ -21,6 +21,7 @@ properties: - const: allwinner,sun4i-a10-spdif - const: allwinner,sun6i-a31-spdif - const: allwinner,sun8i-h3-spdif + - const: allwinner,sun20i-d1-spdif - const: allwinner,sun50i-h6-spdif - items: - const: allwinner,sun8i-a83t-spdif @@ -35,25 +36,49 @@ properties: interrupts: maxItems: 1 - clocks: - items: - - description: Bus Clock - - description: Module Clock - - clock-names: - items: - - const: apb - - const: spdif - # Even though it only applies to subschemas under the conditionals, # not listing them here will trigger a warning because of the # additionalsProperties set to false. + clocks: true + clock-names: true dmas: true dma-names: true resets: maxItems: 1 allOf: + - if: + properties: + compatible: + contains: + enum: + - allwinner,sun20i-d1-spdif + + then: + clocks: + items: + - description: Bus Clock + - description: Receive Clock + - description: Transmit Clock + + clock-names: + items: + - const: apb + - const: rx + - const: tx + + else: + properties: + clocks: + items: + - description: Bus Clock + - description: Module Clock + + clock-names: + items: + - const: apb + - const: spdif + - if: properties: compatible: @@ -61,6 +86,8 @@ allOf: enum: - allwinner,sun6i-a31-spdif - allwinner,sun8i-h3-spdif + - allwinner,sun20i-d1-spdif + - allwinner,sun50i-h6-spdif then: required: diff --git a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml index 908248260afa3e..cbfa6ce5864acf 100644 --- a/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml +++ b/Documentation/devicetree/bindings/spi/allwinner,sun6i-a31-spi.yaml @@ -24,6 +24,7 @@ properties: - items: - enum: - allwinner,sun8i-r40-spi + - allwinner,sun20i-d1-spi - allwinner,sun50i-h6-spi - allwinner,sun50i-h616-spi - const: allwinner,sun8i-h3-spi diff --git a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml index 1c426c211e3668..54290131bed13c 100644 --- a/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml +++ b/Documentation/devicetree/bindings/sram/allwinner,sun4i-a10-system-control.yaml @@ -39,6 +39,7 @@ properties: - items: - const: allwinner,sun8i-r40-system-control - const: allwinner,sun4i-a10-system-control + - const: allwinner,sun20i-d1-system-control - const: allwinner,sun50i-a64-sram-controller deprecated: true - const: allwinner,sun50i-a64-system-control @@ -74,6 +75,7 @@ patternProperties: - const: allwinner,sun4i-a10-sram-a3-a4 - const: allwinner,sun4i-a10-sram-c1 - const: allwinner,sun4i-a10-sram-d + - const: allwinner,sun20i-d1-dsp-sram - const: allwinner,sun50i-a64-sram-c - items: - const: allwinner,sun5i-a13-sram-a3-a4 @@ -96,6 +98,9 @@ patternProperties: - items: - const: allwinner,sun8i-r40-sram-c1 - const: allwinner,sun4i-a10-sram-c1 + - items: + - const: allwinner,sun20i-d1-sram-c1 + - const: allwinner,sun4i-a10-sram-c1 - items: - const: allwinner,sun50i-a64-sram-c1 - const: allwinner,sun4i-a10-sram-c1 diff --git a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.yaml b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.yaml index 2ecac754e1cd00..124c34e152565e 100644 --- a/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.yaml +++ b/Documentation/devicetree/bindings/timer/allwinner,sun5i-a13-hstimer.yaml @@ -18,6 +18,13 @@ properties: - items: - const: allwinner,sun6i-a31-hstimer - const: allwinner,sun7i-a20-hstimer + - const: allwinner,sun50i-h6-hstimer + description: one interrupt, different register layout + - items: + - enum: + - allwinner,sun20i-d1-hstimer + - allwinner,sun50i-h616-hstimer + - const: allwinner,sun50i-h6-hstimer reg: maxItems: 1 @@ -45,7 +52,11 @@ required: if: properties: compatible: - const: allwinner,sun5i-a13-hstimer + contains: + enum: + - allwinner,sun5i-a13-hstimer + - allwinner,sun20i-d1-hstimer + - allwinner,sun50i-h616-hstimer then: properties: diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml index 933fa356d2ce04..e5dbf4169bc9e3 100644 --- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml +++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml @@ -20,6 +20,7 @@ properties: - items: - enum: - allwinner,sun8i-a83t-musb + - allwinner,sun20i-d1-musb - allwinner,sun50i-h6-musb - const: allwinner,sun8i-a33-musb - items: From 7841e5c323665784e8b3bbf76bc6c46c4b8e6a24 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 21:17:16 -0500 Subject: [PATCH 107/120] [SPLIT] treewide: ARCH_SUNXI += SOC_SUNXI Signed-off-by: Samuel Holland --- drivers/bus/Kconfig | 4 ++-- drivers/clk/sunxi-ng/Kconfig | 4 ++-- drivers/crypto/allwinner/Kconfig | 5 ++--- drivers/dma/Kconfig | 2 +- drivers/gpu/drm/sun4i/Kconfig | 2 +- drivers/hwspinlock/Kconfig | 2 +- drivers/i2c/busses/Kconfig | 2 +- drivers/input/keyboard/Kconfig | 2 +- drivers/iommu/Kconfig | 3 +-- drivers/media/platform/Kconfig | 2 +- drivers/media/rc/Kconfig | 2 +- drivers/mfd/Kconfig | 2 +- drivers/mmc/host/Kconfig | 2 +- drivers/net/ethernet/stmicro/stmmac/Kconfig | 4 ++-- drivers/nvmem/Kconfig | 2 +- drivers/phy/allwinner/Kconfig | 4 ++-- drivers/pwm/Kconfig | 2 +- drivers/reset/Kconfig | 2 +- drivers/rtc/Kconfig | 2 +- drivers/soc/sunxi/Kconfig | 2 +- drivers/spi/Kconfig | 2 +- drivers/staging/media/sunxi/Kconfig | 2 +- drivers/thermal/Kconfig | 2 +- drivers/usb/musb/Kconfig | 2 +- drivers/watchdog/Kconfig | 2 +- sound/soc/sunxi/Kconfig | 2 +- 26 files changed, 31 insertions(+), 33 deletions(-) diff --git a/drivers/bus/Kconfig b/drivers/bus/Kconfig index e7f7eee6ee9a72..9b810446fa3086 100644 --- a/drivers/bus/Kconfig +++ b/drivers/bus/Kconfig @@ -155,8 +155,8 @@ config SIMPLE_PM_BUS config SUN50I_DE2_BUS bool "Allwinner A64 DE2 Bus Driver" - default ARM64 - depends on ARCH_SUNXI + default (ARM64 && ARCH_SUNXI) || SOC_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST select SUNXI_SRAM help Say y here to enable support for Allwinner A64 DE2 bus driver. It's diff --git a/drivers/clk/sunxi-ng/Kconfig b/drivers/clk/sunxi-ng/Kconfig index 9ec2ffcf783021..48a54b5e072391 100644 --- a/drivers/clk/sunxi-ng/Kconfig +++ b/drivers/clk/sunxi-ng/Kconfig @@ -1,9 +1,9 @@ # SPDX-License-Identifier: GPL-2.0-only config SUNXI_CCU bool "Clock support for Allwinner SoCs" - depends on ARCH_SUNXI || COMPILE_TEST + default ARCH_SUNXI || SOC_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST select RESET_CONTROLLER - default ARCH_SUNXI if SUNXI_CCU diff --git a/drivers/crypto/allwinner/Kconfig b/drivers/crypto/allwinner/Kconfig index b8e75210a0e315..3d52e77822bd30 100644 --- a/drivers/crypto/allwinner/Kconfig +++ b/drivers/crypto/allwinner/Kconfig @@ -1,13 +1,12 @@ config CRYPTO_DEV_ALLWINNER bool "Support for Allwinner cryptographic offloader" - depends on ARCH_SUNXI || COMPILE_TEST - default y if ARCH_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST + default y if ARCH_SUNXI || SOC_SUNXI help Say Y here to get to see options for Allwinner hardware crypto devices config CRYPTO_DEV_SUN4I_SS tristate "Support for Allwinner Security System cryptographic accelerator" - depends on ARCH_SUNXI depends on PM depends on CRYPTO_DEV_ALLWINNER select CRYPTO_MD5 diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig index 39b5b46e880f29..30d7edc5545b80 100644 --- a/drivers/dma/Kconfig +++ b/drivers/dma/Kconfig @@ -163,7 +163,7 @@ config DMA_SUN4I config DMA_SUN6I tristate "Allwinner A31 SoCs DMA support" - depends on MACH_SUN6I || MACH_SUN8I || (ARM64 && ARCH_SUNXI) || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on RESET_CONTROLLER select DMA_ENGINE select DMA_VIRTUAL_CHANNELS diff --git a/drivers/gpu/drm/sun4i/Kconfig b/drivers/gpu/drm/sun4i/Kconfig index 5755f0432e7743..8466404df1c817 100644 --- a/drivers/gpu/drm/sun4i/Kconfig +++ b/drivers/gpu/drm/sun4i/Kconfig @@ -2,7 +2,7 @@ config DRM_SUN4I tristate "DRM Support for Allwinner A10 Display Engine" depends on DRM && (ARM || ARM64) && COMMON_CLK - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST select DRM_GEM_CMA_HELPER select DRM_KMS_HELPER select DRM_KMS_CMA_HELPER diff --git a/drivers/hwspinlock/Kconfig b/drivers/hwspinlock/Kconfig index 3874d15b0e9b71..ddd31350a0265e 100644 --- a/drivers/hwspinlock/Kconfig +++ b/drivers/hwspinlock/Kconfig @@ -46,7 +46,7 @@ config HWSPINLOCK_STM32 config HWSPINLOCK_SUN6I tristate "SUN6I Hardware Spinlock device" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help Say y here to support the SUN6I Hardware Spinlock device which can be found in most of the sun6i compatible Allwinner SoCs. diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 10acece9d7b938..180616410aa110 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -786,7 +786,7 @@ config I2C_MT7621 config I2C_MV64XXX tristate "Marvell mv64xxx I2C Controller" - depends on PLAT_ORION || ARCH_SUNXI || ARCH_MVEBU || COMPILE_TEST + depends on PLAT_ORION || ARCH_MVEBU || ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help If you say yes to this option, support will be included for the built-in I2C interface on the Marvell 64xxx line of host bridges. diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 40a070a2e7f5b7..57c4da30cfc4c9 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -632,7 +632,7 @@ config KEYBOARD_STMPE config KEYBOARD_SUN4I_LRADC tristate "Allwinner sun4i low res adc attached tablet keys support" - depends on ARCH_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help This selects support for the Allwinner low res adc attached tablet keys found on Allwinner sunxi SoCs. diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 07b7c25cbed8a1..425ad6ff7201ed 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig @@ -179,8 +179,7 @@ config ROCKCHIP_IOMMU config SUN50I_IOMMU bool "Allwinner H6 IOMMU Support" depends on HAS_DMA - depends on ARCH_SUNXI || COMPILE_TEST - select ARM_DMA_USE_IOMMU + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST select IOMMU_API help Support for the IOMMU introduced in the Allwinner H6 SoCs. diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig index 157c924686e4b6..542283b86ab534 100644 --- a/drivers/media/platform/Kconfig +++ b/drivers/media/platform/Kconfig @@ -577,7 +577,7 @@ config VIDEO_QCOM_VENUS config VIDEO_SUN8I_DEINTERLACE tristate "Allwinner Deinterlace driver" depends on VIDEO_DEV && VIDEO_V4L2 - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on COMMON_CLK && OF depends on PM select VIDEOBUF2_DMA_CONTIG diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index d0a8326b75c22b..effa5a8cf6edd6 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig @@ -421,7 +421,7 @@ config RC_ST config IR_SUNXI tristate "SUNXI IR remote control" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help Say Y if you want to use sunXi internal IR Controller diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 6a3fd2d75f964a..3e45b704bba57a 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -56,7 +56,7 @@ config MFD_SUN4I_GPADC select MFD_CORE select REGMAP_MMIO select REGMAP_IRQ - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on !TOUCHSCREEN_SUN4I help Select this to get support for Allwinner SoCs (A10, A13 and A31) ADC. diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index 71313961cc54db..a3999dc47ebe3e 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig @@ -963,7 +963,7 @@ config MMC_REALTEK_USB config MMC_SUNXI tristate "Allwinner sunxi SD/MMC Host Controller support" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help This selects support for the SD/MMC Host Controller on Allwinner sunxi SoCs. diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig index ac3c248d4f9bc8..555e8f644d68ec 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Kconfig +++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig @@ -199,8 +199,8 @@ config DWMAC_SUNXI config DWMAC_SUN8I tristate "Allwinner sun8i GMAC support" - default ARCH_SUNXI - depends on OF && (ARCH_SUNXI || COMPILE_TEST) + default ARCH_SUNXI || SOC_SUNXI + depends on OF && (ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST) select MDIO_BUS_MUX help Support for Allwinner H3 A83T A64 EMAC ethernet controllers. diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig index dd20190068387c..27d42077438e99 100644 --- a/drivers/nvmem/Kconfig +++ b/drivers/nvmem/Kconfig @@ -172,7 +172,7 @@ config NVMEM_STM32_ROMEM config NVMEM_SUNXI_SID tristate "Allwinner SoCs SID support" - depends on ARCH_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help This is a driver for the 'security ID' available on various Allwinner devices. diff --git a/drivers/phy/allwinner/Kconfig b/drivers/phy/allwinner/Kconfig index fb584518b2d0fd..c2b820e33b4e09 100644 --- a/drivers/phy/allwinner/Kconfig +++ b/drivers/phy/allwinner/Kconfig @@ -4,7 +4,7 @@ # config PHY_SUN4I_USB tristate "Allwinner sunxi SoC USB PHY driver" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on HAS_IOMEM depends on RESET_CONTROLLER depends on EXTCON @@ -21,7 +21,7 @@ config PHY_SUN4I_USB config PHY_SUN6I_MIPI_DPHY tristate "Allwinner A31 MIPI D-PHY Support" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on HAS_IOMEM && COMMON_CLK depends on RESET_CONTROLLER select GENERIC_PHY diff --git a/drivers/pwm/Kconfig b/drivers/pwm/Kconfig index 738bb194fa3b01..beadca961b9f5e 100644 --- a/drivers/pwm/Kconfig +++ b/drivers/pwm/Kconfig @@ -561,7 +561,7 @@ config PWM_STMPE config PWM_SUN4I tristate "Allwinner PWM support" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on HAS_IOMEM && COMMON_CLK help Generic PWM framework driver for Allwinner SoCs. diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 328f70f633eb10..db498ce56cfcf7 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -194,7 +194,7 @@ config RESET_SCMI config RESET_SIMPLE bool "Simple Reset Controller Driver" if COMPILE_TEST - default ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC + default ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC || SOC_SUNXI help This enables a simple reset controller driver for reset lines that that can be asserted and deasserted by toggling bits in a contiguous, diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 12153d5801ce1b..8b1b6bd121d784 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig @@ -1558,7 +1558,7 @@ config RTC_DRV_SUN6I bool "Allwinner A31 RTC" default MACH_SUN6I || MACH_SUN8I depends on COMMON_CLK - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help If you say Y here you will get support for the RTC found in some Allwinner SoCs like the A31 or the A64. diff --git a/drivers/soc/sunxi/Kconfig b/drivers/soc/sunxi/Kconfig index 1fef0e71105616..7a81fa455e1a1b 100644 --- a/drivers/soc/sunxi/Kconfig +++ b/drivers/soc/sunxi/Kconfig @@ -12,7 +12,7 @@ config SUNXI_MBUS config SUNXI_SRAM bool - default ARCH_SUNXI + default ARCH_SUNXI || SOC_SUNXI select REGMAP_MMIO help Say y here to enable the SRAM controller support. This diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index e71a4c514f7bd5..de8aa1396d94c5 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -827,7 +827,7 @@ config SPI_SUN4I config SPI_SUN6I tristate "Allwinner A31 SPI controller" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on RESET_CONTROLLER help This enables using the SPI controller on the Allwinner A31 SoCs. diff --git a/drivers/staging/media/sunxi/Kconfig b/drivers/staging/media/sunxi/Kconfig index 4549a135741f44..ed81e2ddf1eb12 100644 --- a/drivers/staging/media/sunxi/Kconfig +++ b/drivers/staging/media/sunxi/Kconfig @@ -1,7 +1,7 @@ # SPDX-License-Identifier: GPL-2.0 config VIDEO_SUNXI bool "Allwinner sunXi family Video Devices" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST help If you have an Allwinner SoC based on the sunXi family, say Y. diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig index d7f44deab5b1d5..f0836770d0468c 100644 --- a/drivers/thermal/Kconfig +++ b/drivers/thermal/Kconfig @@ -314,7 +314,7 @@ config SPEAR_THERMAL config SUN8I_THERMAL tristate "Allwinner sun8i thermal driver" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on HAS_IOMEM depends on NVMEM depends on OF diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 8de143807c1aec..98dd1d750b8660 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig @@ -63,7 +63,7 @@ comment "Platform Glue Layer" config USB_MUSB_SUNXI tristate "Allwinner (sunxi)" - depends on ARCH_SUNXI + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST depends on NOP_USB_XCEIV depends on PHY_SUN4I_USB depends on EXTCON diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 546dfc1e2349c2..46a95fb1564a1c 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig @@ -633,7 +633,7 @@ config RN5T618_WATCHDOG config SUNXI_WATCHDOG tristate "Allwinner SoCs watchdog support" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST select WATCHDOG_CORE help Say Y here to include support for the watchdog timer diff --git a/sound/soc/sunxi/Kconfig b/sound/soc/sunxi/Kconfig index d10a7f2ffaf986..9443d077343d5d 100644 --- a/sound/soc/sunxi/Kconfig +++ b/sound/soc/sunxi/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only menu "Allwinner SoC Audio support" - depends on ARCH_SUNXI || COMPILE_TEST + depends on ARCH_SUNXI || SOC_SUNXI || COMPILE_TEST config SND_SUN4I_CODEC tristate "Allwinner A10 Codec Support" From 9451b65062e2588862e42750f74ffea0fd101734 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:04:42 -0500 Subject: [PATCH 108/120] dt-bindings: riscv: Add compatible for D1 PLIC Signed-off-by: Samuel Holland --- .../bindings/interrupt-controller/sifive,plic-1.0.0.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml index 08d5a57ce00ff4..67333956531361 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml +++ b/Documentation/devicetree/bindings/interrupt-controller/sifive,plic-1.0.0.yaml @@ -44,6 +44,7 @@ properties: compatible: items: - enum: + - allwinner,sun20i-d1-plic - sifive,fu540-c000-plic - canaan,k210-plic - const: sifive,plic-1.0.0 From 139b576c24004f401019e911653ad87f129f98a6 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:05:17 -0500 Subject: [PATCH 109/120] dt-bindings: riscv: Add compatible for T-HEAD C906 Signed-off-by: Samuel Holland --- Documentation/devicetree/bindings/riscv/cpus.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/riscv/cpus.yaml b/Documentation/devicetree/bindings/riscv/cpus.yaml index 4829366305259e..1183b46e6e702b 100644 --- a/Documentation/devicetree/bindings/riscv/cpus.yaml +++ b/Documentation/devicetree/bindings/riscv/cpus.yaml @@ -40,6 +40,7 @@ properties: - sifive,u5 - sifive,u7 - canaan,k210 + - thead,c906 - const: riscv - const: riscv # Simulator only description: From 4bb15bbe59ab3d4b6a6ebc7335a8eee11e2c8d85 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:17:45 -0500 Subject: [PATCH 110/120] [WIP] riscv: Add Allwinner D1 SoC support Signed-off-by: Samuel Holland --- arch/riscv/Kconfig.socs | 8 ++++++++ arch/riscv/boot/dts/Makefile | 1 + arch/riscv/boot/dts/allwinner/Makefile | 1 + 3 files changed, 10 insertions(+) create mode 100644 arch/riscv/boot/dts/allwinner/Makefile diff --git a/arch/riscv/Kconfig.socs b/arch/riscv/Kconfig.socs index 56bafc3dad4c6f..017b7893a0a3b9 100644 --- a/arch/riscv/Kconfig.socs +++ b/arch/riscv/Kconfig.socs @@ -1,5 +1,13 @@ menu "SoC selection" +config SOC_SUNXI + bool "Allwinner sunXi SoCs" + select SIFIVE_PLIC + select SUN4I_TIMER + select SUN5I_HSTIMER + help + This enables support for Allwinner sunXi SoC platforms. + config SOC_MICROCHIP_POLARFIRE bool "Microchip PolarFire SoCs" select MCHP_CLK_MPFS diff --git a/arch/riscv/boot/dts/Makefile b/arch/riscv/boot/dts/Makefile index fe996b88319eb7..05b36b76eaac85 100644 --- a/arch/riscv/boot/dts/Makefile +++ b/arch/riscv/boot/dts/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 +subdir-y += allwinner subdir-y += sifive subdir-$(CONFIG_SOC_CANAAN_K210_DTB_BUILTIN) += canaan subdir-y += microchip diff --git a/arch/riscv/boot/dts/allwinner/Makefile b/arch/riscv/boot/dts/allwinner/Makefile new file mode 100644 index 00000000000000..f66554cd5c4518 --- /dev/null +++ b/arch/riscv/boot/dts/allwinner/Makefile @@ -0,0 +1 @@ +# SPDX-License-Identifier: GPL-2.0 From 7e062d967f3244a8987558fd305609237a88e98f Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:18:17 -0500 Subject: [PATCH 111/120] [WIP] riscv: Add Allwinner D1 SoC device tree Signed-off-by: Samuel Holland --- arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 1151 ++++++++++++++++++ 1 file changed, 1151 insertions(+) create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi new file mode 100644 index 00000000000000..60e3b3d2a9546b --- /dev/null +++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi @@ -0,0 +1,1151 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +// Copyright (C) 2021 Samuel Holland + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + // FIXME: no riscv architecture support for cpufreq + cpu_opp_table: cpu-opp-table { + compatible = "allwinner,sun20i-d1-operating-points", + "allwinner,sun50i-h6-operating-points"; + nvmem-cells = <&cpu_speed_grade>; + + opp-1080000000 { + // FIXME: this is probably wrong now. + clock-latency-ns = <244144>; /* 8 32k periods */ + opp-hz = /bits/ 64 <1008000000>; + + // FIXME: derive a real voltage range. + opp-microvolt-speed0 = <1100000>; + }; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + timebase-frequency = <24000000>; + + cpu0: cpu@0 { + // FIXME: is this the right compatible? + compatible = "thead,c906", "riscv"; + device_type = "cpu"; + reg = <0>; + clocks = <&ccu CLK_RISCV>; + clock-frequency = <24000000>; + #cooling-cells = <2>; + d-cache-block-size = <64>; + d-cache-sets = <256>; + d-cache-size = <32768>; + i-cache-block-size = <64>; + i-cache-sets = <128>; + i-cache-size = <32768>; + mmu-type = "riscv,sv39"; + operating-points-v2 = <&cpu_opp_table>; + riscv,isa = "rv64imafdc"; + + cpu0_intc: interrupt-controller { + compatible = "riscv,cpu-intc"; + #address-cells = <0>; + interrupt-controller; + #interrupt-cells = <1>; + }; + }; + }; + + // FIXME: depends on what T-HEAD tries to upstream. + pmu { + compatible = "thead,c900-pmu"; + }; + + thermal-zones { + cpu-thermal { + polling-delay = <0>; + polling-delay-passive = <0>; + thermal-sensors = <&ths 0>; + + trips { + cpu_target: cpu-target { + hysteresis = <3000>; + temperature = <85000>; + type = "passive"; + }; + + cpu-crit { + hysteresis = <0>; + temperature = <110000>; + type = "critical"; + }; + }; + + cooling-maps { + map0 { + trip = <&cpu_target>; + cooling-device = <&cpu0 THERMAL_NO_LIMIT THERMAL_NO_LIMIT>; + }; + }; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + interrupt-parent = <&intc>; + + // TODO: write a binding and driver. + dsp: dsp@1700000 { + compatible = "allwinner,sun20i-d1-dsp"; + reg = <0x1700000 0x400>; + reg-names = "cfg"; + clocks = <&ccu CLK_BUS_DSP_CFG>, + <&ccu CLK_DSP>; + clock-names = "cfg", "dsp"; + resets = <&ccu RST_BUS_DSP_CFG>, + <&ccu RST_BUS_DSP_DBG>, + <&ccu RST_DSP>; + allwinner,sram = <&dsp_sram 1>; + interrupts = <136 IRQ_TYPE_LEVEL_HIGH>, + <137 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "dee", "pfe"; + // FIXME: this will be different for R528 (CPUX). + mboxes = <&riscv_msgbox MBOX_USER_DSP MBOX_RX>, + <&dsp_msgbox MBOX_USER_RISCV MBOX_TX>; + mbox-names = "rx", "tx"; + }; + + dsp_wdt: watchdog@1700400 { + compatible = "allwinner,sun20i-d1-wdt"; + reg = <0x1700400 0x20>; + clocks = <&rtc CLK_DCXO24M>; + interrupts = <138 IRQ_TYPE_LEVEL_HIGH>; + status = "reserved"; + }; + + // TODO: write a binding and driver. + dsp_msgbox: mailbox@1701000 { + compatible = "allwinner,sun20i-d1-msgbox"; + reg = <0x1701000 0x1000>; + clocks = <&ccu CLK_BUS_MSGBOX1>; + resets = <&ccu RST_BUS_MSGBOX1>; + interrupts = <139 IRQ_TYPE_LEVEL_HIGH>, + <140 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "rx", "tx"; + #mbox-cells = <2>; + }; + + ve: video-codec@1c0e000 { + compatible = "allwinner,sun20i-d1-video-engine"; + reg = <0x1c0e000 0x2000>; + clocks = <&ccu CLK_BUS_VE>, + <&ccu CLK_VE>, + <&ccu CLK_MBUS_VE>; + clock-names = "ahb", "mod", "ram"; + resets = <&ccu RST_BUS_VE>; + allwinner,sram = <&ve_sram 1>; + interconnects = <&mbus 4>; + interconnect-names = "dma-mem"; + interrupts = <82 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&iommu 0>; + }; + + gpio: pinctrl@2000000 { + compatible = "allwinner,sun20i-d1-pinctrl"; + #address-cells = <0>; + reg = <0x2000000 0x800>; + clocks = <&ccu CLK_APB0>, + <&rtc CLK_DCXO24M>, + <&rtc CLK_OSC32K>; + clock-names = "apb", "hosc", "losc"; + gpio-controller; + #gpio-cells = <3>; + interrupts = <85 IRQ_TYPE_LEVEL_HIGH>, + <87 IRQ_TYPE_LEVEL_HIGH>, + <89 IRQ_TYPE_LEVEL_HIGH>, + <91 IRQ_TYPE_LEVEL_HIGH>, + <93 IRQ_TYPE_LEVEL_HIGH>, + <95 IRQ_TYPE_LEVEL_HIGH>; + // FIXME: not in binding, should we add these? + interrupt-names = "pb", "pc", "pd", "pe", "pf", "pg"; + interrupt-controller; + #interrupt-cells = <3>; + + /omit-if-no-ref/ + i2c0_pb10_pins: i2c0-pb10-pins { + pins = "PB10", "PB11"; + function = "i2c0"; + }; + + /omit-if-no-ref/ + i2c2_pb0_pins: i2c2-pb0-pins { + pins = "PB0", "PB1"; + function = "i2c2"; + }; + + /omit-if-no-ref/ + i2c3_pb6_pins: i2c3-pb6-pins { + pins = "PB6", "PB7"; + function = "i2c3"; + }; + + /omit-if-no-ref/ + mmc0_pins: mmc0-pins { + pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5"; + function = "sdc0"; + }; + + /omit-if-no-ref/ + mmc1_pins: mmc1-pins { + pins = "PG0", "PG1", "PG2", "PG3", "PG4", "PG5"; + function = "sdc1"; + }; + + /omit-if-no-ref/ + mmc2_pins: mmc2-pins { + pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7"; + function = "sdc2"; + }; + + /omit-if-no-ref/ + rgmii_pe_pins: rgmii-pe-pins { + pins = "PE0", "PE1", "PE2", "PE3", "PE4", + "PE5", "PE6", "PE7", "PE8", "PE9", + "PE11", "PE12", "PE13", "PE14", "PE15"; + function = "emac"; + }; + + /omit-if-no-ref/ + spi0_pins: spi0-pins { + pins = "PC2", "PC3", "PC4", "PC5", "PC6", "PC7"; + function = "spi0"; + }; + + /omit-if-no-ref/ + spi1_pb_pins: spi1-pb-pins { + pins = "PB0", "PB8", "PB9", "PB10", "PB11", "PB12"; + function = "spi1"; + }; + + /omit-if-no-ref/ + spi1_pd_pins: spi1-pd-pins { + pins = "PD10", "PD11", "PD12", "PD13", "PD14", "PD15"; + function = "spi1"; + }; + + /omit-if-no-ref/ + uart0_pb8_pins: uart0-pb8-pins { + pins = "PB8", "PB9"; + function = "uart0"; + }; + + /omit-if-no-ref/ + uart1_pg6_pins: uart1-pg6-pins { + pins = "PG6", "PG7"; + function = "uart1"; + }; + + /omit-if-no-ref/ + uart1_pg8_rts_cts_pins: uart1-pg8-rts-cts-pins { + pins = "PG8", "PG9"; + function = "uart1"; + }; + }; + + pwm: pwm@2000c00 { + compatible = "allwinner,sun20i-d1-pwm"; + reg = <0x2000c00 0x400>; + clocks = <&ccu CLK_BUS_PWM>, <&rtc CLK_DCXO24M>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_PWM>; + interrupts = <34 IRQ_TYPE_LEVEL_HIGH>; + #pwm-cells = <3>; + status = "disabled"; + }; + + ccu: clock-controller@2001000 { + compatible = "allwinner,sun20i-d1-ccu"; + reg = <0x2001000 0x1000>; + clocks = <&rtc CLK_DCXO24M>, + <&rtc CLK_OSC32K>, + <&rtc CLK_IOSC>; + clock-names = "hosc", "losc", "iosc"; + #clock-cells = <1>; + #reset-cells = <1>; + }; + + // TODO: write a binding and driver. + ir_tx: irled@2003000 { + compatible = "allwinner,sun20i-d1-ir-tx"; + reg = <0x2003000 0x400>; + clocks = <&ccu CLK_BUS_IR_TX>, + <&rtc CLK_DCXO24M>, + <&ccu CLK_IR_TX>; + clock-names = "bus", "pclk", "mclk"; + resets = <&ccu RST_BUS_IR_TX>; + dmas = <&dma 13>; + dma-names = "tx"; + interrupts = <35 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a binding and driver. + ledc: led-controller@2008000 { + compatible = "allwinner,sun20i-d1-ledc"; + reg = <0x2008000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_LEDC>, <&ccu CLK_LEDC>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_LEDC>; + dmas = <&dma 42>; + dma-names = "tx"; + interrupts = <36 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a binding and driver. + gpadc: adc@2009000 { + compatible = "allwinner,sun20i-d1-gpadc"; + reg = <0x2009000 0x400>; + clocks = <&ccu CLK_BUS_GPADC>; + resets = <&ccu RST_BUS_GPADC>; + dmas = <&dma 12>; + dma-names = "rx"; + interrupts = <73 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + ths: temperature-sensor@2009400 { + compatible = "allwinner,sun20i-d1-ths"; + reg = <0x2009400 0x400>; + clocks = <&ccu CLK_BUS_THS>, <&rtc CLK_DCXO24M>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_THS>; + interrupts = <74 IRQ_TYPE_LEVEL_HIGH>; + nvmem-cells = <&ths_calib>; + nvmem-cell-names = "calibration"; + #thermal-sensor-cells = <0>; + }; + + lradc: keys@2009800 { + compatible = "allwinner,sun20i-d1-lradc"; + reg = <0x2009800 0x400>; + clocks = <&ccu CLK_BUS_LRADC>; + resets = <&ccu RST_BUS_LRADC>; + interrupts = <77 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a binding and driver. + tpadc: touchscreen@2009c00 { + compatible = "allwinner,sun20i-d1-ts"; + reg = <0x2009c00 0x400>; + clocks = <&ccu CLK_BUS_TPADC>, <&ccu CLK_TPADC>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_TPADC>; + dmas = <&dma 13>; + dma-names = "rx"; + interrupts = <78 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // FIXME: this driver probably needs updates. + iommu: iommu@2010000 { + compatible = "allwinner,sun20i-d1-iommu"; + reg = <0x2010000 0x10000>; + clocks = <&ccu CLK_BUS_IOMMU>; + interrupts = <80 IRQ_TYPE_LEVEL_HIGH>; + #iommu-cells = <1>; + }; + + codec: audio-codec@2030000 { + compatible = "allwinner,sun20i-d1-audio-codec"; + reg = <0x2030000 0x1000>; + clocks = <&ccu CLK_BUS_AUDIO>, + <&ccu CLK_AUDIO_ADC>, + <&ccu CLK_AUDIO_DAC>, + <&rtc CLK_DCXO24M>, + <&rtc CLK_OSC32K>; + clock-names = "bus", "adc", "dac", "hosc", "losc"; + resets = <&ccu RST_BUS_AUDIO>; + dmas = <&dma 7>, <&dma 7>; + dma-names = "rx", "tx"; + interrupts = <41 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + status = "disabled"; + + regulators { + reg_aldo: aldo { + regulator-name = "aldo"; + }; + + reg_hpldo: hpldo { + regulator-name = "hpldo"; + }; + }; + + }; + + // TODO: try the posted driver. + dmic: dmic@2031000 { + compatible = "allwinner,sun20i-d1-dmic"; + reg = <0x2031000 0x400>; + clocks = <&ccu CLK_BUS_DMIC>, + <&ccu CLK_DMIC>; + clock-names = "bus", "mod"; + resets = <&ccu RST_BUS_DMIC>; + dmas = <&dma 8>; + dma-names = "rx"; + interrupts = <40 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s0: i2s@2032000 { + compatible = "allwinner,sun20i-d1-i2s"; + reg = <0x2032000 0x1000>; + clocks = <&ccu CLK_BUS_I2S0>, + <&ccu CLK_I2S0>; + clock-names = "apb", "mod"; + resets = <&ccu RST_BUS_I2S0>; + dmas = <&dma 3>, <&dma 3>; + dma-names = "rx", "tx"; + interrupts = <42 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + i2s1: i2s@2033000 { + compatible = "allwinner,sun20i-d1-i2s"; + reg = <0x2033000 0x1000>; + clocks = <&ccu CLK_BUS_I2S1>, + <&ccu CLK_I2S1>; + clock-names = "apb", "mod"; + resets = <&ccu RST_BUS_I2S1>; + dmas = <&dma 4>, <&dma 4>; + dma-names = "rx", "tx"; + interrupts = <43 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + // TODO: how to integrate ASRC? same or separate node? + i2s2: i2s@2034000 { + compatible = "allwinner,sun20i-d1-i2s"; + reg = <0x2034000 0x1000>; + clocks = <&ccu CLK_BUS_I2S2>, + <&ccu CLK_I2S2>; + clock-names = "apb", "mod"; + resets = <&ccu RST_BUS_I2S2>; + dmas = <&dma 5>, <&dma 5>; + dma-names = "rx", "tx"; + interrupts = <44 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + // TODO: add receive functionality + spdif: spdif@2036000 { + compatible = "allwinner,sun20i-d1-spdif"; + reg = <0x2036000 0x400>; + clocks = <&ccu CLK_BUS_SPDIF>, + <&ccu CLK_SPDIF_RX>, + <&ccu CLK_SPDIF_TX>; + clock-names = "apb", "rx", "tx"; + resets = <&ccu RST_BUS_SPDIF>; + dmas = <&dma 2>, <&dma 2>; + dma-names = "rx", "tx"; + interrupts = <39 IRQ_TYPE_LEVEL_HIGH>; + #sound-dai-cells = <0>; + status = "disabled"; + }; + + timer: timer@2050000 { + compatible = "allwinner,sun20i-d1-timer", + "allwinner,sun8i-a23-timer"; + reg = <0x2050000 0xa0>; + clocks = <&rtc CLK_DCXO24M>; + interrupts = <75 IRQ_TYPE_LEVEL_HIGH>, + <76 IRQ_TYPE_LEVEL_HIGH>; + }; + + wdt: watchdog@20500a0 { + compatible = "allwinner,sun20i-d1-wdt-reset", + "allwinner,sun20i-d1-wdt"; + reg = <0x20500a0 0x20>; + clocks = <&rtc CLK_DCXO24M>; + interrupts = <79 IRQ_TYPE_LEVEL_HIGH>; + status = "reserved"; + }; + + // TODO: write a driver. + uart0: serial@2500000 { + compatible = "allwinner,sun20i-d1-uart", + "snps,dw-apb-uart"; + reg = <0x2500000 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&ccu CLK_BUS_UART0>; + resets = <&ccu RST_BUS_UART0>; + dmas = <&dma 14>, <&dma 14>; + dma-names = "rx", "tx"; + fifo-size = <64>; + interrupts = <18 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a driver, add IDMA? + uart1: serial@2500400 { + compatible = "allwinner,sun20i-d1-uart1", + "allwinner,sun20i-d1-uart", + "snps,dw-apb-uart"; + reg = <0x2500400 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&ccu CLK_BUS_UART1>; + resets = <&ccu RST_BUS_UART1>; + dmas = <&dma 15>, <&dma 15>; + dma-names = "rx", "tx"; + fifo-size = <256>; + interrupts = <19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a driver. + uart2: serial@2500800 { + compatible = "allwinner,sun20i-d1-uart", + "snps,dw-apb-uart"; + reg = <0x2500800 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&ccu CLK_BUS_UART2>; + resets = <&ccu RST_BUS_UART2>; + dmas = <&dma 16>, <&dma 16>; + dma-names = "rx", "tx"; + fifo-size = <256>; + interrupts = <20 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a driver. + uart3: serial@2500c00 { + compatible = "allwinner,sun20i-d1-uart", + "snps,dw-apb-uart"; + reg = <0x2500c00 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&ccu CLK_BUS_UART3>; + resets = <&ccu RST_BUS_UART3>; + dmas = <&dma 17>, <&dma 17>; + dma-names = "rx", "tx"; + fifo-size = <256>; + interrupts = <21 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a driver. + uart4: serial@2501000 { + compatible = "allwinner,sun20i-d1-uart", + "snps,dw-apb-uart"; + reg = <0x2501000 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&ccu CLK_BUS_UART4>; + resets = <&ccu RST_BUS_UART4>; + dmas = <&dma 18>, <&dma 18>; + dma-names = "rx", "tx"; + fifo-size = <256>; + interrupts = <22 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + // TODO: write a driver. + uart5: serial@2501400 { + compatible = "allwinner,sun20i-d1-uart", + "snps,dw-apb-uart"; + reg = <0x2501400 0x400>; + reg-io-width = <4>; + reg-shift = <2>; + clocks = <&ccu CLK_BUS_UART5>; + resets = <&ccu RST_BUS_UART5>; + dmas = <&dma 19>, <&dma 19>; + dma-names = "rx", "tx"; + fifo-size = <256>; + interrupts = <23 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + i2c0: i2c@2502000 { + compatible = "allwinner,sun20i-d1-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x2502000 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_I2C0>; + resets = <&ccu RST_BUS_I2C0>; + dmas = <&dma 43>, <&dma 43>; + dma-names = "rx", "tx"; + interrupts = <25 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + i2c1: i2c@2502400 { + compatible = "allwinner,sun20i-d1-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x2502400 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_I2C1>; + resets = <&ccu RST_BUS_I2C1>; + dmas = <&dma 44>, <&dma 44>; + dma-names = "rx", "tx"; + interrupts = <26 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + i2c2: i2c@2502800 { + compatible = "allwinner,sun20i-d1-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x2502800 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_I2C2>; + resets = <&ccu RST_BUS_I2C2>; + dmas = <&dma 45>, <&dma 45>; + dma-names = "rx", "tx"; + interrupts = <27 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + i2c3: i2c@2502c00 { + compatible = "allwinner,sun20i-d1-i2c", + "allwinner,sun6i-a31-i2c"; + reg = <0x2502c00 0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_I2C3>; + resets = <&ccu RST_BUS_I2C3>; + dmas = <&dma 46>, <&dma 46>; + dma-names = "rx", "tx"; + interrupts = <28 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + syscon: syscon@3000000 { + compatible = "allwinner,sun20i-d1-system-control"; + reg = <0x3000000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + regulators { + reg_ldoa: ldoa { + regulator-name = "ldoa"; + }; + + reg_ldob: ldob { + regulator-name = "ldob"; + }; + }; + + sram@400000 { + compatible = "mmio-sram"; + reg = <0x400000 0x20000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x400000 0x20000>; + + /* + * This can be further divided into DSP IRAM, + * DSP DRAM0, and DSP DRAM1, but the mapping + * of all three is controlled by a single bit. + */ + dsp_sram: sram-section@0 { + compatible = "allwinner,sun20i-d1-dsp-sram"; + reg = <0 0x20000>; + }; + }; + + // FIXME: Address is not verified. It is copied from A64/H6. + sram@1d00000 { + compatible = "mmio-sram"; + reg = <0x1d00000 0x40000>; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x1d00000 0x40000>; + + ve_sram: sram-section@0 { + compatible = "allwinner,sun20i-d1-sram-c1", + "allwinner,sun4i-a10-sram-c1"; + reg = <0 0x40000>; + }; + }; + }; + + dma: dma-controller@3002000 { + compatible = "allwinner,sun20i-d1-dma"; + reg = <0x3002000 0x1000>; + clocks = <&ccu CLK_BUS_DMA>, <&ccu CLK_MBUS_DMA>; + clock-names = "bus", "mbus"; + resets = <&ccu RST_BUS_DMA>; + #dma-cells = <1>; + dma-channels = <16>; + dma-requests = <48>; + interrupts = <66 IRQ_TYPE_LEVEL_HIGH>, + <142 IRQ_TYPE_LEVEL_HIGH>; + }; + + msgbox: mailbox@3003000 { + compatible = "allwinner,sun20i-d1-msgbox"; + reg = <0x3003000 0x1000>; + clocks = <&ccu CLK_BUS_MSGBOX0>; + resets = <&ccu RST_BUS_MSGBOX0>; + interrupts = <101 IRQ_TYPE_LEVEL_HIGH>, + <102 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "rx", "tx"; + #mbox-cells = <2>; + }; + + hwspinlock: hwlock@3005000 { + compatible = "allwinner,sun20i-d1-hwspinlock", + "allwinner,sun6i-a31-hwspinlock"; + reg = <0x3005000 0x1000>; + clocks = <&ccu CLK_BUS_SPINLOCK>; + resets = <&ccu RST_BUS_SPINLOCK>; + interrupts = <70 IRQ_TYPE_LEVEL_HIGH>; + }; + + sid: efuse@3006000 { + compatible = "allwinner,sun20i-d1-sid", + "allwinner,sun50i-a64-sid"; + reg = <0x3006000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + + cpu_speed_grade: cpu-speed-grade@0 { + reg = <0x0 0x2>; + }; + + ths_calib: ths-calib@14 { + reg = <0x14 0x4>; + }; + }; + + // TODO: write a binding and driver. + hstimer: timer@3008000 { + compatible = "allwinner,sun20i-d1-hstimer", + "allwinner,sun50i-h6-hstimer"; + reg = <0x3008000 0x1000>; + clocks = <&ccu CLK_BUS_HSTIMER>; + resets = <&ccu RST_BUS_HSTIMER>; + interrupts = <71 IRQ_TYPE_LEVEL_HIGH>, + <72 IRQ_TYPE_LEVEL_HIGH>; + }; + + crypto: crypto@3040000 { + compatible = "allwinner,sun20i-d1-crypto"; + reg = <0x3040000 0x800>; + clocks = <&ccu CLK_BUS_CE>, <&ccu CLK_CE>, <&ccu CLK_MBUS_CE>; + clock-names = "bus", "mod", "ram"; + resets = <&ccu RST_BUS_CE>; + interrupts = <68 IRQ_TYPE_LEVEL_HIGH>; + }; + + // TODO: write a binding and driver. + mbus: dram-controller@3102000 { + compatible = "allwinner,sun20i-d1-mbus"; + reg = <0x3102000 0x200000>; + #address-cells = <1>; + #size-cells = <1>; + clocks = <&ccu CLK_BUS_DRAM>, + <&ccu CLK_DRAM>, + <&ccu CLK_MBUS>; + clock-names = "bus", "dram", "mbus"; + dma-ranges = <0 0x40000000 0x80000000>; + #interconnect-cells = <1>; + interrupts = <59 IRQ_TYPE_LEVEL_HIGH>; + }; + + mmc0: mmc@4020000 { + compatible = "allwinner,sun20i-d1-mmc"; + reg = <0x4020000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_MMC0>, <&ccu CLK_MMC0>; + clock-names = "ahb", "mmc"; + resets = <&ccu RST_BUS_MMC0>; + reset-names = "ahb"; + cap-sd-highspeed; + interrupts = <56 IRQ_TYPE_LEVEL_HIGH>; + max-frequency = <150000000>; + no-mmc; + status = "disabled"; + }; + + mmc1: mmc@4021000 { + compatible = "allwinner,sun20i-d1-mmc"; + reg = <0x4021000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_MMC1>, <&ccu CLK_MMC1>; + clock-names = "ahb", "mmc"; + resets = <&ccu RST_BUS_MMC1>; + reset-names = "ahb"; + cap-sd-highspeed; + interrupts = <57 IRQ_TYPE_LEVEL_HIGH>; + max-frequency = <150000000>; + no-mmc; + status = "disabled"; + }; + + mmc2: mmc@4022000 { + compatible = "allwinner,sun20i-d1-emmc"; + reg = <0x4022000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_MMC2>, <&ccu CLK_MMC2>; + clock-names = "ahb", "mmc"; + resets = <&ccu RST_BUS_MMC2>; + reset-names = "ahb"; + cap-mmc-highspeed; + interrupts = <58 IRQ_TYPE_LEVEL_HIGH>; + max-frequency = <150000000>; + mmc-ddr-1_8v; + mmc-ddr-3_3v; + no-sd; + no-sdio; + status = "disabled"; + }; + + spi0: spi@4025000 { + compatible = "allwinner,sun20i-d1-spi", + "allwinner,sun50i-r329-spi"; + reg = <0x4025000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_SPI0>, <&ccu CLK_SPI0>; + clock-names = "ahb", "mod"; + resets = <&ccu RST_BUS_SPI0>; + dmas = <&dma 22>, <&dma 22>; + dma-names = "rx", "tx"; + interrupts = <31 IRQ_TYPE_LEVEL_HIGH>; + num-cs = <1>; + status = "disabled"; + }; + + spi1: spi@4026000 { + compatible = "allwinner,sun20i-d1-spi-dbi", + "allwinner,sun50i-r329-spi-dbi", + "allwinner,sun50i-r329-spi"; + reg = <0x4026000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&ccu CLK_BUS_SPI1>, <&ccu CLK_SPI1>; + clock-names = "ahb", "mod"; + resets = <&ccu RST_BUS_SPI1>; + dmas = <&dma 23>, <&dma 23>; + dma-names = "rx", "tx"; + interrupts = <32 IRQ_TYPE_LEVEL_HIGH>; + num-cs = <1>; + status = "disabled"; + }; + + usb_otg: usb@4100000 { + compatible = "allwinner,sun20i-d1-musb", + "allwinner,sun8i-a33-musb"; + reg = <0x4100000 0x400>; + clocks = <&ccu CLK_BUS_OTG>; + resets = <&ccu RST_BUS_OTG>; + dmas = <&dma 30>, <&dma 30>, + <&dma 31>, <&dma 31>, + <&dma 32>, <&dma 32>, + <&dma 33>, <&dma 33>, + <&dma 34>, <&dma 34>; + dma-names = "ep1_rx", "ep1_tx", + "ep2_rx", "ep2_tx", + "ep3_rx", "ep3_tx", + "ep4_rx", "ep4_tx", + "ep5_rx", "ep5_tx"; + extcon = <&usbphy 0>; + interrupts = <45 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "mc"; + phys = <&usbphy 0>; + phy-names = "usb"; + status = "disabled"; + }; + + usbphy: phy@4100400 { + compatible = "allwinner,sun20i-d1-usb-phy"; + reg = <0x4100400 0x100>, + <0x4101800 0x100>, + <0x4200800 0x100>; + reg-names = "phy_ctrl", + "pmu0", + "pmu1"; + clocks = <&rtc CLK_DCXO24M>, + <&rtc CLK_DCXO24M>; + clock-names = "usb0_phy", + "usb1_phy"; + resets = <&ccu RST_USB_PHY0>, + <&ccu RST_USB_PHY1>; + reset-names = "usb0_reset", + "usb1_reset"; + #phy-cells = <1>; + status = "disabled"; + }; + + ehci0: usb@4101000 { + compatible = "allwinner,sun20i-d1-ehci", + "generic-ehci"; + reg = <0x4101000 0x100>; + clocks = <&ccu CLK_BUS_OHCI0>, + <&ccu CLK_BUS_EHCI0>, + <&ccu CLK_USB_OHCI0>; + resets = <&ccu RST_BUS_OHCI0>, + <&ccu RST_BUS_EHCI0>; + interrupts = <46 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usbphy 0>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci0: usb@4101400 { + compatible = "allwinner,sun20i-d1-ohci", + "generic-ohci"; + reg = <0x4101400 0x100>; + clocks = <&ccu CLK_BUS_OHCI0>, + <&ccu CLK_USB_OHCI0>; + resets = <&ccu RST_BUS_OHCI0>; + interrupts = <47 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usbphy 0>; + phy-names = "usb"; + status = "disabled"; + }; + + ehci1: usb@4200000 { + compatible = "allwinner,sun20i-d1-ehci", + "generic-ehci"; + reg = <0x4200000 0x100>; + clocks = <&ccu CLK_BUS_OHCI1>, + <&ccu CLK_BUS_EHCI1>, + <&ccu CLK_USB_OHCI1>; + resets = <&ccu RST_BUS_OHCI1>, + <&ccu RST_BUS_EHCI1>; + interrupts = <49 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usbphy 1>; + phy-names = "usb"; + status = "disabled"; + }; + + ohci1: usb@4200400 { + compatible = "allwinner,sun20i-d1-ohci", + "generic-ohci"; + reg = <0x4200400 0x100>; + clocks = <&ccu CLK_BUS_OHCI1>, + <&ccu CLK_USB_OHCI1>; + resets = <&ccu RST_BUS_OHCI1>; + interrupts = <50 IRQ_TYPE_LEVEL_HIGH>; + phys = <&usbphy 1>; + phy-names = "usb"; + status = "disabled"; + }; + + emac: ethernet@4500000 { + compatible = "allwinner,sun20i-d1-emac", + "allwinner,sun50i-a64-emac"; + reg = <0x4500000 0x10000>; + clocks = <&ccu CLK_BUS_EMAC>; + clock-names = "stmmaceth"; + resets = <&ccu RST_BUS_EMAC>; + reset-names = "stmmaceth"; + interrupts = <62 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "macirq"; + syscon = <&syscon>; + status = "disabled"; + + mdio: mdio { + compatible = "snps,dwmac-mdio"; + #address-cells = <1>; + #size-cells = <0>; + }; + }; + + de: display-engine@5000000 { + reg = <0x5000000 0x400000>; + interrupts = <103 IRQ_TYPE_LEVEL_HIGH>; + interconnects = <&mbus 11>; + interconnect-names = "dma-mem"; + iommus = <&iommu 2>; + }; + + deinterlace: deinterlace@5400000 { + reg = <0x5400000 0x10000>; + interconnects = <&mbus 10>; + interconnect-names = "dma-mem"; + interrupts = <104 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&iommu 4>; + }; + + g2d: g2d@5410000 { + reg = <0x5410000 0x40000>; + interconnects = <&mbus 9>; + interconnect-names = "dma-mem"; + interrupts = <105 IRQ_TYPE_LEVEL_HIGH>; + iommus = <&iommu 3>; + }; + + dsi: dsi@5450000 { + reg = <0x5450000 0x2000>; + interrupts = <108 IRQ_TYPE_LEVEL_HIGH>; + }; + + tcon_top: tcon-top@5460000 { + reg = <0x5460000 0x1000>; + }; + + tcon_lcd: lcd-controller@5461000 { + reg = <0x5461000 0x1000>; + interrupts = <106 IRQ_TYPE_LEVEL_HIGH>; + }; + + tcon_tv: lcd-controller@5470000 { + reg = <0x5470000 0x1000>; + interrupts = <107 IRQ_TYPE_LEVEL_HIGH>; + }; + + hdmi: hdmi@5500000 { + reg = <0x5500000 0x100000>; + interrupts = <109 IRQ_TYPE_LEVEL_HIGH>; + }; + + tve_top: video-codec@5600000 { + reg = <0x5600000 0x4000>; + }; + + tve0: video-codec@5604000 { + reg = <0x5604000 0x4000>; + interrupts = <110 IRQ_TYPE_LEVEL_HIGH>; + }; + + csi: csi@5800000 { + reg = <0x5800000 0x400000>; + interrupts = <111 IRQ_TYPE_LEVEL_HIGH>, + <112 IRQ_TYPE_LEVEL_HIGH>, + <116 IRQ_TYPE_LEVEL_HIGH>, + <122 IRQ_TYPE_LEVEL_HIGH>; + interconnects = <&mbus 7>; + interconnect-names = "dma-mem"; + iommus = <&iommu 1>; + }; + + tvd_top: video-codec@5c00000 { + reg = <0x5c00000 0x1000>; + interconnects = <&mbus 6>; + interconnect-names = "dma-mem"; + }; + + tvd0: video-codec@5c01000 { + reg = <0x5c01000 0x1000>; + interrupts = <123 IRQ_TYPE_LEVEL_HIGH>; + }; + + intc: interrupt-controller@6010000 { + compatible = "allwinner,sun20i-d1-intc"; + reg = <0x6010000 0x100>; + #address-cells = <0>; + clocks = <&ccu CLK_BUS_RISCV_CFG>; + resets = <&ccu RST_BUS_RISCV_CFG>; + interrupt-parent = <&plic>; + interrupt-controller; + #interrupt-cells = <2>; + }; + + riscv_wdt: watchdog@6011000 { + compatible = "allwinner,sun20i-d1-wdt"; + reg = <0x6011000 0x20>; + clocks = <&rtc CLK_DCXO24M>; + interrupts = <147 IRQ_TYPE_LEVEL_HIGH>; + }; + + riscv_msgbox: mailbox@601f000 { + compatible = "allwinner,sun20i-d1-msgbox"; + reg = <0x601f000 0x1000>; + clocks = <&ccu CLK_BUS_MSGBOX2>; + resets = <&ccu RST_BUS_MSGBOX2>; + interrupts = <144 IRQ_TYPE_LEVEL_HIGH>, + <145 IRQ_TYPE_LEVEL_HIGH>; + interrupt-names = "rx", "tx"; + #mbox-cells = <2>; + }; + + r_ccu: clock-controller@7010000 { + compatible = "allwinner,sun20i-d1-r-ccu"; + reg = <0x7010000 0x400>; + clocks = <&rtc CLK_DCXO24M>, + <&rtc CLK_OSC32K>, + <&rtc CLK_IOSC>, + <&ccu CLK_PLL_PERIPH0_DIV3>; + clock-names = "hosc", "losc", "iosc", "pll-periph"; + #clock-cells = <1>; + #reset-cells = <1>; + interrupts = <64 IRQ_TYPE_LEVEL_HIGH>; + }; + + r_ir_rx: ir@7040000 { + compatible = "allwinner,sun20i-d1-ir", + "allwinner,sun6i-a31-ir"; + reg = <0x7040000 0x400>; + clocks = <&r_ccu CLK_BUS_R_IR_RX>, <&r_ccu CLK_R_IR_RX>; + clock-names = "apb", "ir"; + resets = <&r_ccu RST_BUS_R_IR_RX>; + interrupts = <167 IRQ_TYPE_LEVEL_HIGH>; + }; + + // TODO: audit all blocks for hidden use of CLK_DCXO24M + rtc: rtc@7090000 { + compatible = "allwinner,sun20i-d1-rtc", + "allwinner,sun50i-r329-rtc"; + reg = <0x7090000 0x400>; + clocks = <&r_ccu CLK_BUS_R_RTC>, + <&rtc CLK_RTC_1K>, + <&rtc CLK_RTC_SPI>; + clock-names = "bus", "mod", "spi"; + #clock-cells = <1>; + interrupts = <160 IRQ_TYPE_LEVEL_HIGH>; + }; + + plic: interrupt-controller@10000000 { + compatible = "allwinner,sun20i-d1-plic", + "sifive,plic-1.0.0"; + reg = <0x10000000 0x4000000>; + #address-cells = <0>; + interrupts-extended = <&cpu0_intc 11>, + <&cpu0_intc 9>; + interrupt-controller; + #interrupt-cells = <1>; + riscv,ndev = <176>; + }; + + clint: clint@14000000 { + compatible = "allwinner,sun20i-d1-clint", + "sifive,clint0"; + reg = <0x14000000 0xc000>; + reg-io-width = <4>; + interrupts-extended = <&cpu0_intc 3>, + <&cpu0_intc 7>; + }; + }; +}; From eccf985d40b303af071f132926f30bf9a54a15ca Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Mon, 31 May 2021 16:01:46 -0500 Subject: [PATCH 112/120] [TEMP] Add static memory info to the D1 device tree Signed-off-by: Samuel Holland --- arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi index 60e3b3d2a9546b..035d8d655c8abd 100644 --- a/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi +++ b/arch/riscv/boot/dts/allwinner/sun20i-d1.dtsi @@ -65,6 +65,12 @@ }; }; + // FIXME: this is temporary. + memory { + device_type = "memory"; + reg = <0x40000000 0x20000000>; /* 512 MB */ + }; + // FIXME: depends on what T-HEAD tries to upstream. pmu { compatible = "thead,c900-pmu"; From 29457d216ecfff65cffb22e043d6a5fde69881b9 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 16 May 2021 14:18:46 -0500 Subject: [PATCH 113/120] [WIP] riscv: Add D1 Nezha board device tree Signed-off-by: Samuel Holland --- arch/riscv/boot/dts/allwinner/Makefile | 1 + .../boot/dts/allwinner/sun20i-d1-nezha.dts | 372 ++++++++++++++++++ 2 files changed, 373 insertions(+) create mode 100644 arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts diff --git a/arch/riscv/boot/dts/allwinner/Makefile b/arch/riscv/boot/dts/allwinner/Makefile index f66554cd5c4518..77e3f7e63b5598 100644 --- a/arch/riscv/boot/dts/allwinner/Makefile +++ b/arch/riscv/boot/dts/allwinner/Makefile @@ -1 +1,2 @@ # SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_SOC_SUNXI) += sun20i-d1-nezha.dtb diff --git a/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts new file mode 100644 index 00000000000000..a902f958222d3f --- /dev/null +++ b/arch/riscv/boot/dts/allwinner/sun20i-d1-nezha.dts @@ -0,0 +1,372 @@ +// SPDX-License-Identifier: (GPL-2.0+ or MIT) +// Copyright (C) 2021 Samuel Holland + +/dts-v1/; + +#include "sun20i-d1.dtsi" + +#include +#include +#include +#include + +/ { + model = "Allwinner D1 NeZha"; + compatible = "allwinner,d1-nezha", "allwinner,sun20i-d1"; + + aliases { + ethernet0 = &emac; + mmc0 = &mmc0; + mmc1 = &mmc1; + mmc2 = &mmc2; + serial0 = &uart0; + spi0 = &spi0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + hdmi_connector: connector { + compatible = "hdmi-connector"; + type = "a"; + + port { + hdmi_con_in: endpoint { + // FIXME: remote-endpoint = <&hdmi_out_con>; + }; + }; + }; + + reg_usbvbus: usbvbus { + compatible = "regulator-fixed"; + regulator-name = "usbvbus"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + gpio = <&gpio 3 19 GPIO_ACTIVE_HIGH>; /* PD19 */ + enable-active-high; + vin-supply = <®_vcc>; + }; + + reg_vcc: vcc { + compatible = "regulator-fixed"; + regulator-name = "vcc"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + }; + + reg_vcc_3v3: vcc-3v3 { + compatible = "regulator-fixed"; + regulator-name = "vcc-3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + vin-supply = <®_vcc>; + }; + + reg_vdd_cpu: vdd-cpu { + compatible = "pwm-regulator"; + pwms = <&pwm 0 50000 0>; + pwm-supply = <®_vcc>; + regulator-name = "vdd-cpu"; + regulator-min-microvolt = <810000>; + regulator-max-microvolt = <1160000>; + }; + + wifi_pwrseq: wifi-pwrseq { + compatible = "mmc-pwrseq-simple"; + reset-gpios = <&gpio 6 12 GPIO_ACTIVE_LOW>; /* PG12 */ + }; +}; + +&codec { + allwinner,routing = "Headphone Jack", "HPOUTL", + "Headphone Jack", "HPOUTR", + "LINEINL", "HPOUTL", + "LINEINR", "HPOUTR", + "MICIN3", "Headset Microphone", + "Headset Microphone", "HBIAS"; + allwinner,widgets = "Microphone", "Headset Microphone", + "Headphone", "Headphone Jack"; + avcc-supply = <®_aldo>; + hpvcc-supply = <®_hpldo>; + vdd33-supply = <®_vcc_3v3>; + status = "okay"; +}; + +&cpu0 { + cpu-supply = <®_vdd_cpu>; +}; + +&ehci0 { + status = "okay"; +}; + +&ehci1 { + status = "okay"; +}; + +&emac { + pinctrl-0 = <&rgmii_pe_pins>; + pinctrl-names = "default"; + phy-handle = <&ext_rgmii_phy>; + phy-mode = "rgmii-id"; + phy-supply = <®_vcc_3v3>; + status = "okay"; +}; + +&gpio { + vcc-pa-supply = <®_vcc_3v3>; + vcc-pb-supply = <®_vcc_3v3>; + vcc-pc-supply = <®_vcc_3v3>; + vcc-pd-supply = <®_vcc_3v3>; + vcc-pe-supply = <®_vcc_3v3>; + vcc-pf-supply = <®_vcc_3v3>; + vcc-pg-supply = <®_vcc_3v3>; + + i2s2_pb_pins: i2s2-pb-pins { + pins = "PB5", "PB6", "PB7"; + function = "i2s2"; + }; + + i2s2_pb3_din_pin: i2s2-pb3-din-pin { + pins = "PB3"; + function = "i2s2_din"; + }; + + i2s2_pb4_dout_pin: i2s2-pb4-dout-pin { + pins = "PB4"; + function = "i2s2_dout"; + }; + + ledc_pc0_pin: ledc-pc0-pin { + pins = "PC0"; + function = "ledc"; + }; + + pwm0_pd16_pin: pwm0-pd16-pin { + pins = "PD16"; + function = "pwm0"; + }; + + pwm2_pd18_pin: pwm2-pd18-pin { + pins = "PD18"; + function = "pwm2"; + }; + + pwm7_pd22_pin: pwm7-pd22-pin { + pins = "PD22"; + function = "pwm7"; + }; + + spdif_pd22_pin: spdif-pd22-pin { + pins = "PD22"; + function = "spdif"; + }; +}; + +&i2c0 { + pinctrl-0 = <&i2c0_pb10_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c2 { + pinctrl-0 = <&i2c2_pb0_pins>; + pinctrl-names = "default"; + status = "okay"; + + pcf8574a: gpio@38 { + compatible = "nxp,pcf8574a"; + #address-cells = <0>; + reg = <0x38>; + gpio-controller; + #gpio-cells = <2>; + interrupts-extended = <&gpio 1 2 IRQ_TYPE_LEVEL_LOW>; /* PB2 */ + interrupt-controller; + #interrupt-cells = <2>; + }; +}; + +&i2s2 { + pinctrl-0 = <&i2s2_pb_pins>, <&i2s2_pb3_din_pin>, <&i2s2_pb4_dout_pin>; + pinctrl-names = "default"; + status = "okay"; +}; + +&ledc { + pinctrl-0 = <&ledc_pc0_pin>; + pinctrl-names = "default"; + status = "okay"; + + led@0 { + reg = <0x0>; + color = ; + function = LED_FUNCTION_INDICATOR; + }; +}; + +&lradc { + vref-supply = <®_aldo>; + wakeup-source; + status = "okay"; + + button-160 { + label = "OK"; + linux,code = ; + channel = <0>; + voltage = <160000>; + }; +}; + +&mdio { + ext_rgmii_phy: ethernet-phy@1 { + compatible = "ethernet-phy-ieee802.3-c22"; + reg = <1>; + }; +}; + +&mmc0 { + bus-width = <4>; + cd-gpios = <&gpio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 */ + disable-wp; + vmmc-supply = <®_vcc_3v3>; + vqmmc-supply = <®_vcc_3v3>; + pinctrl-0 = <&mmc0_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&mmc1 { + bus-width = <4>; + mmc-pwrseq = <&wifi_pwrseq>; + non-removable; + vmmc-supply = <®_vcc_3v3>; + vqmmc-supply = <®_vcc_3v3>; + pinctrl-0 = <&mmc1_pins>; + pinctrl-names = "default"; + status = "okay"; + + xr829: wifi@1 { + reg = <1>; + host-wake-gpios = <&gpio 6 10 GPIO_ACTIVE_LOW>; /* PG10 */ + }; +}; + +&ohci0 { + status = "okay"; +}; + +&ohci1 { + status = "okay"; +}; + +&pwm { + pinctrl-0 = <&pwm0_pd16_pin>, <&pwm2_pd18_pin>; + pinctrl-names = "default"; + status = "okay"; +}; + +®_aldo { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + vdd33-supply = <®_vcc_3v3>; +}; + +®_hpldo { + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + hpldoin-supply = <®_vcc_3v3>; +}; + +®_ldoa { + regulator-always-on; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + ldo-in-supply = <®_vcc_3v3>; +}; + +&spdif { + pinctrl-0 = <&spdif_pd22_pin>; + pinctrl-names = "default"; + status = "okay"; +}; + +&spi0 { + pinctrl-0 = <&spi0_pins>; + pinctrl-names = "default"; + status = "okay"; + + flash@0 { + compatible = "spi-nand"; + reg = <0>; + + partitions { + compatible = "fixed-partitions"; + #address-cells = <1>; + #size-cells = <1>; + + partition@0 { + label = "boot0"; + reg = <0x00000000 0x00100000>; + }; + + partition@100000 { + label = "uboot"; + reg = <0x00100000 0x00300000>; + }; + + partition@400000 { + label = "secure_storage"; + reg = <0x00400000 0x00100000>; + }; + + partition@500000 { + label = "sys"; + reg = <0x00500000 0x0fb00000>; + }; + }; + }; +}; + +&spi1 { + pinctrl-0 = <&spi1_pd_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&ths { + vref-supply = <®_aldo>; +}; + +&uart0 { + pinctrl-0 = <&uart0_pb8_pins>; + pinctrl-names = "default"; + status = "okay"; +}; + +&uart1 { + pinctrl-0 = <&uart1_pg6_pins>, <&uart1_pg8_rts_cts_pins>; + pinctrl-names = "default"; + status = "okay"; + + bluetooth { + compatible = "xradio,xr829-bt"; + device-wakeup-gpios = <&gpio 6 16 GPIO_ACTIVE_LOW>; /* PG16 */ + interrupts-extended = <&gpio 6 17 IRQ_TYPE_LEVEL_LOW>; /* PG17 */ + interrupt-names = "wakeup"; + reset-gpios = <&gpio 6 18 GPIO_ACTIVE_LOW>; /* PG18 */ + }; +}; + +&usb_otg { + dr_mode = "otg"; + status = "okay"; +}; + +&usbphy { + usb0_id_det-gpios = <&gpio 3 21 GPIO_ACTIVE_LOW>; /* PD21 */ + usb0_vbus_det-gpios = <&gpio 3 20 GPIO_ACTIVE_HIGH>; /* PD20 */ + usb0_vbus-supply = <®_usbvbus>; + usb1_vbus-supply = <®_vcc>; + status = "okay"; +}; From 8e6d0e61a2098a3b95a5d8c0876e7e1cdfffb5a4 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 13 Jun 2021 23:54:42 -0500 Subject: [PATCH 114/120] [DO NOT MERGE] misc changes Signed-off-by: Samuel Holland --- arch/riscv/Kconfig | 2 +- arch/riscv/mm/physaddr.c | 2 +- drivers/mmc/host/sunxi-mmc.c | 15 +++++++++++---- drivers/of/irq.c | 7 ++++--- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 8 ++++++++ include/linux/dmaengine.h | 2 +- sound/soc/soc-core.c | 3 +++ sound/soc/soc-dapm.c | 2 +- sound/soc/sunxi/Makefile | 4 ++-- sound/soc/sunxi/sun4i-i2s.c | 6 ------ sound/soc/sunxi/sun4i-spdif.c | 11 +++++++++-- 11 files changed, 41 insertions(+), 21 deletions(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index adb30fe10fa96e..c0a302f5858b42 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -261,7 +261,7 @@ config ARCH_RV64I select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL select HAVE_FUNCTION_GRAPH_TRACER select HAVE_FUNCTION_TRACER if !XIP_KERNEL - select SWIOTLB if MMU + # select SWIOTLB if MMU endchoice diff --git a/arch/riscv/mm/physaddr.c b/arch/riscv/mm/physaddr.c index e7fd0c253c7b29..917d9868bb9066 100644 --- a/arch/riscv/mm/physaddr.c +++ b/arch/riscv/mm/physaddr.c @@ -14,7 +14,7 @@ phys_addr_t __virt_to_phys(unsigned long x) * Boundary checking aginst the kernel linear mapping space. */ WARN(y >= KERN_VIRT_SIZE, - "virt_to_phys used for non-linear address: %pK (%pS)\n", + "virt_to_phys used for non-linear address: %p (%pS)\n", (void *)x, (void *)x); return __va_to_pa_nodebug(x); diff --git a/drivers/mmc/host/sunxi-mmc.c b/drivers/mmc/host/sunxi-mmc.c index e6a21bcc3b475e..09a85de3e5f2be 100644 --- a/drivers/mmc/host/sunxi-mmc.c +++ b/drivers/mmc/host/sunxi-mmc.c @@ -749,6 +749,17 @@ static int sunxi_mmc_calibrate(struct sunxi_mmc_host *host, int reg_off) */ writel(SDXC_CAL_DL_SW_EN, host->reg_base + reg_off); +#if 0 + writel(SDXC_CAL_START, host->reg_base + reg_off); + + unsigned long expire = jiffies + msecs_to_jiffies(250); + u32 rval; + + do { + rval = readl(host->reg_base + reg_off); + } while (time_before(jiffies, expire) && !(rval & SDXC_CAL_DONE)); +#endif + return 0; } @@ -1211,7 +1222,6 @@ static const struct sunxi_mmc_cfg sun20i_d1_cfg = { static const struct sunxi_mmc_cfg sun50i_a64_cfg = { .idma_des_size_bits = 16, - .clk_delays = NULL, .can_calibrate = true, .mask_data0 = true, .needs_new_timings = true, @@ -1219,7 +1229,6 @@ static const struct sunxi_mmc_cfg sun50i_a64_cfg = { static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = { .idma_des_size_bits = 13, - .clk_delays = NULL, .can_calibrate = true, .needs_new_timings = true, }; @@ -1227,7 +1236,6 @@ static const struct sunxi_mmc_cfg sun50i_a64_emmc_cfg = { static const struct sunxi_mmc_cfg sun50i_a100_cfg = { .idma_des_size_bits = 16, .idma_des_shift = 2, - .clk_delays = NULL, .can_calibrate = true, .mask_data0 = true, .needs_new_timings = true, @@ -1236,7 +1244,6 @@ static const struct sunxi_mmc_cfg sun50i_a100_cfg = { static const struct sunxi_mmc_cfg sun50i_a100_emmc_cfg = { .idma_des_size_bits = 13, .idma_des_shift = 2, - .clk_delays = NULL, .can_calibrate = true, .needs_new_timings = true, }; diff --git a/drivers/of/irq.c b/drivers/of/irq.c index d84d27fb22038d..33878ffb9a4917 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -511,6 +511,8 @@ void __init of_irq_init(const struct of_device_id *matches) desc->interrupt_parent = of_irq_find_parent(np); if (desc->interrupt_parent == np) desc->interrupt_parent = NULL; + pr_notice("of_irq_init: found %pOF with parent %pOF\n", + desc->dev, desc->interrupt_parent); list_add_tail(&desc->list, &intc_desc_list); } @@ -535,9 +537,8 @@ void __init of_irq_init(const struct of_device_id *matches) of_node_set_flag(desc->dev, OF_POPULATED); - pr_debug("of_irq_init: init %pOF (%p), parent %p\n", - desc->dev, - desc->dev, desc->interrupt_parent); + pr_notice("of_irq_init: init %pOF with parent %pOF\n", + desc->dev, desc->interrupt_parent); ret = desc->irq_init_cb(desc->dev, desc->interrupt_parent); if (ret) { diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index c0b80cdf241134..11f25106b45f63 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -10,6 +10,7 @@ * warranty of any kind, whether express or implied. */ +#define DEBUG #include #include #include @@ -1026,8 +1027,15 @@ static void sunxi_pinctrl_irq_ack(struct irq_data *d) u32 status_reg = sunxi_irq_status_reg(pctl->desc, d->hwirq); u8 status_idx = sunxi_irq_status_offset(d->hwirq); + u32 old = readl(pctl->membase + status_reg); + /* Clear the IRQ */ writel(1 << status_idx, pctl->membase + status_reg); + + u32 new = readl(pctl->membase + status_reg); + + pr_err("acked %ld in 0x%08x, was 0x%08x, now 0x%08x\n", + d->hwirq, status_reg, old, new); } static void sunxi_pinctrl_irq_mask(struct irq_data *d) diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 93c3ca5fdafdfc..881e9f645994a5 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -393,7 +393,7 @@ enum dma_slave_buswidth { * should be read (RX), if the source is memory this argument is * ignored. * @dst_addr: this is the physical address where DMA slave data - * should be written (TX), if the source is memory this argument + * should be written (TX), if the destination is memory this argument * is ignored. * @src_addr_width: this is the width in bytes of the source (RX) * register where DMA data shall be read. If the source diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 583f2381cfc823..37c4ff57f3901f 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -17,6 +17,7 @@ // o Add more codecs and platforms to ensure good API coverage. // o Support TDM on PCM and I2S +#define DEBUG #include #include #include @@ -1042,6 +1043,8 @@ int snd_soc_add_pcm_runtime(struct snd_soc_card *card, if (!snd_soc_is_matching_component(platform, component)) continue; + dev_warn(card->dev, "ASoC: Adding component %s for platform %pOF\n", + component->name, platform->of_node); snd_soc_rtd_add_component(rtd, component); } } diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 91bf939d5233ea..aff1590ab42416 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -2337,7 +2337,7 @@ static int soc_dapm_mixer_update_power(struct snd_soc_card *card, * right channel. * * A stereo control is signified by a valid 'rconnect' - * value, either 0 for unconnected, or >= 0 for connected. + * value, either 0 for unconnected, or > 0 for connected. * This is chosen instead of using snd_soc_volsw_is_stereo, * so that the behavior of snd_soc_dapm_mixer_update_power * doesn't change even when the kcontrol passed in is diff --git a/sound/soc/sunxi/Makefile b/sound/soc/sunxi/Makefile index 7bbe2526e16ee3..4392e0e49dd0c1 100644 --- a/sound/soc/sunxi/Makefile +++ b/sound/soc/sunxi/Makefile @@ -2,8 +2,8 @@ obj-$(CONFIG_SND_SUN4I_CODEC) += sun4i-codec.o obj-$(CONFIG_SND_SUN4I_I2S) += sun4i-i2s.o obj-$(CONFIG_SND_SUN4I_SPDIF) += sun4i-spdif.o +obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o +obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o obj-$(CONFIG_SND_SUN8I_CODEC_ANALOG) += sun8i-codec-analog.o obj-$(CONFIG_SND_SUN20I_CODEC) += sun20i-codec.o obj-$(CONFIG_SND_SUN50I_CODEC_ANALOG) += sun50i-codec-analog.o -obj-$(CONFIG_SND_SUN8I_CODEC) += sun8i-codec.o -obj-$(CONFIG_SND_SUN8I_ADDA_PR_REGMAP) += sun8i-adda-pr-regmap.o diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index c9d9af5092a4af..525a0d9c499323 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -38,10 +38,6 @@ #define SUN4I_I2S_FMT0_BCLK_POLARITY_MASK BIT(6) #define SUN4I_I2S_FMT0_BCLK_POLARITY_INVERTED (1 << 6) #define SUN4I_I2S_FMT0_BCLK_POLARITY_NORMAL (0 << 6) -#define SUN4I_I2S_FMT0_SR_MASK GENMASK(5, 4) -#define SUN4I_I2S_FMT0_SR(sr) ((sr) << 4) -#define SUN4I_I2S_FMT0_WSS_MASK GENMASK(3, 2) -#define SUN4I_I2S_FMT0_WSS(wss) ((wss) << 2) #define SUN4I_I2S_FMT0_FMT_MASK GENMASK(1, 0) #define SUN4I_I2S_FMT0_FMT_RIGHT_J (2 << 0) #define SUN4I_I2S_FMT0_FMT_LEFT_J (1 << 0) @@ -71,8 +67,6 @@ #define SUN4I_I2S_INT_STA_REG 0x20 #define SUN4I_I2S_CLK_DIV_REG 0x24 -#define SUN4I_I2S_CLK_DIV_MCLK_EN BIT(7) -#define SUN4I_I2S_CLK_DIV_BCLK_MASK GENMASK(6, 4) #define SUN4I_I2S_CLK_DIV_BCLK(bclk) ((bclk) << 4) #define SUN4I_I2S_CLK_DIV_MCLK_MASK GENMASK(3, 0) #define SUN4I_I2S_CLK_DIV_MCLK(mclk) ((mclk) << 0) diff --git a/sound/soc/sunxi/sun4i-spdif.c b/sound/soc/sunxi/sun4i-spdif.c index 6f5b3ad894746d..36a3d951128768 100644 --- a/sound/soc/sunxi/sun4i-spdif.c +++ b/sound/soc/sunxi/sun4i-spdif.c @@ -53,6 +53,8 @@ #define SUN4I_SPDIF_TXFIFO (0x0C) +#define SUN8I_SPDIF_ISTA (0x0C) + #define SUN4I_SPDIF_RXFIFO (0x10) #define SUN4I_SPDIF_FCTL (0x14) @@ -81,9 +83,14 @@ #define SUN4I_SPDIF_FSTA (0x18) #define SUN4I_SPDIF_FSTA_TXE BIT(14) - #define SUN4I_SPDIF_FSTA_TXECNTSHT (8) + #define SUN4I_SPDIF_FSTA_TXE_CNT (8) #define SUN4I_SPDIF_FSTA_RXA BIT(6) - #define SUN4I_SPDIF_FSTA_RXACNTSHT (0) + #define SUN4I_SPDIF_FSTA_RXA_CNT (0) + + #define SUN8I_SPDIF_FSTA_TXE BIT(31) + #define SUN8I_SPDIF_FSTA_TXE_CNT (16) + #define SUN8I_SPDIF_FSTA_RXA BIT(15) + #define SUN8I_SPDIF_FSTA_RXA_CNT (0) #define SUN4I_SPDIF_INT (0x1C) #define SUN4I_SPDIF_INT_RXLOCKEN BIT(18) From d895cf7f92e0371004514b89f12a813b1af2dca6 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sat, 17 Jul 2021 11:19:29 -0500 Subject: [PATCH 115/120] [WIP] spi: spi-sun6i: Dual/Quad RX Support Signed-off-by: Samuel Holland --- drivers/spi/spi-sun6i.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/spi/spi-sun6i.c b/drivers/spi/spi-sun6i.c index 77a9e0646f3f3a..a80ccf0973a8c2 100644 --- a/drivers/spi/spi-sun6i.c +++ b/drivers/spi/spi-sun6i.c @@ -82,6 +82,8 @@ #define SUN6I_XMIT_CNT_REG 0x34 #define SUN6I_BURST_CTL_CNT_REG 0x38 +#define SUN6I_BURST_CTL_CNT_QUAD_EN BIT(29) +#define SUN6I_BURST_CTL_CNT_DUAL_EN BIT(28) #define SUN6I_TXDATA_REG 0x200 #define SUN6I_RXDATA_REG 0x300 @@ -404,7 +406,17 @@ static int sun6i_spi_transfer_one(struct spi_master *master, /* Setup the counters */ sun6i_spi_write(sspi, SUN6I_BURST_CNT_REG, tfr->len); sun6i_spi_write(sspi, SUN6I_XMIT_CNT_REG, tx_len); - sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, tx_len); + + reg = tx_len; + switch (tfr->rx_nbits) { + case SPI_NBITS_QUAD: + reg |= SUN6I_BURST_CTL_CNT_QUAD_EN; + break; + case SPI_NBITS_DUAL: + reg |= SUN6I_BURST_CTL_CNT_DUAL_EN; + break; + } + sun6i_spi_write(sspi, SUN6I_BURST_CTL_CNT_REG, reg); if (!use_dma) { /* Fill the TX FIFO */ @@ -606,7 +618,8 @@ static int sun6i_spi_probe(struct platform_device *pdev) master->set_cs = sun6i_spi_set_cs; master->transfer_one = sun6i_spi_transfer_one; master->num_chipselect = 4; - master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST; + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH | SPI_LSB_FIRST + | SPI_RX_DUAL | SPI_RX_QUAD; master->bits_per_word_mask = SPI_BPW_MASK(8); master->dev.of_node = pdev->dev.of_node; master->auto_runtime_pm = true; From 319b62ec1d9ec8a3401998a411250f9cdb5c3e52 Mon Sep 17 00:00:00 2001 From: Samuel Holland Date: Sun, 8 Aug 2021 21:27:43 -0500 Subject: [PATCH 116/120] [DO NOT MERGE] Add a defconfig for the NeZha Signed-off-by: Samuel Holland --- arch/riscv/configs/nezha_defconfig | 231 +++++++++++++++++++++++++++++ 1 file changed, 231 insertions(+) create mode 100644 arch/riscv/configs/nezha_defconfig diff --git a/arch/riscv/configs/nezha_defconfig b/arch/riscv/configs/nezha_defconfig new file mode 100644 index 00000000000000..59e76fcadf2e93 --- /dev/null +++ b/arch/riscv/configs/nezha_defconfig @@ -0,0 +1,231 @@ +CONFIG_DEFAULT_HOSTNAME="nezha" +# CONFIG_SWAP is not set +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_EXPERT=y +# CONFIG_SYSFS_SYSCALL is not set +# CONFIG_VM_EVENT_COUNTERS is not set +# CONFIG_SLUB_DEBUG is not set +# CONFIG_COMPAT_BRK is not set +# CONFIG_SLAB_MERGE_DEFAULT is not set +CONFIG_SOC_SUNXI=y +# CONFIG_RISCV_ERRATA_ALTERNATIVE is not set +# CONFIG_RISCV_ISA_C is not set +# CONFIG_EFI is not set +CONFIG_PHYS_RAM_BASE=0x40000000 +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_PM_ADVANCED_DEBUG=y +CONFIG_JUMP_LABEL=y +# CONFIG_SECCOMP is not set +# CONFIG_STACKPROTECTOR is not set +# CONFIG_GCC_PLUGINS is not set +# CONFIG_BLK_DEV_BSG is not set +# CONFIG_MQ_IOSCHED_DEADLINE is not set +# CONFIG_MQ_IOSCHED_KYBER is not set +# CONFIG_COREDUMP is not set +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_UNIX=y +CONFIG_INET=y +# CONFIG_INET_DIAG is not set +# CONFIG_IPV6_SIT is not set +# CONFIG_WIRELESS is not set +# CONFIG_ETHTOOL_NETLINK is not set +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +# CONFIG_ALLOW_DEV_COREDUMP is not set +CONFIG_MTD=y +CONFIG_MTD_BLOCK=y +CONFIG_MTD_PARTITIONED_MASTER=y +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_BLOCK=y +# CONFIG_BLK_DEV is not set +CONFIG_NETDEVICES=y +# CONFIG_NET_CORE is not set +# CONFIG_NET_VENDOR_ALACRITECH is not set +# CONFIG_NET_VENDOR_AMAZON is not set +# CONFIG_NET_VENDOR_AQUANTIA is not set +# CONFIG_NET_VENDOR_ARC is not set +# CONFIG_NET_VENDOR_BROADCOM is not set +# CONFIG_NET_VENDOR_CADENCE is not set +# CONFIG_NET_VENDOR_CAVIUM is not set +# CONFIG_NET_VENDOR_CORTINA is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_GOOGLE is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MICROSOFT is not set +# CONFIG_NET_VENDOR_MARVELL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set +# CONFIG_NET_VENDOR_MICREL is not set +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +# CONFIG_NET_VENDOR_NATSEMI is not set +# CONFIG_NET_VENDOR_NETRONOME is not set +# CONFIG_NET_VENDOR_NI is not set +# CONFIG_NET_VENDOR_PENSANDO is not set +# CONFIG_NET_VENDOR_QUALCOMM is not set +# CONFIG_NET_VENDOR_RENESAS is not set +# CONFIG_NET_VENDOR_ROCKER is not set +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +# CONFIG_NET_VENDOR_SOCIONEXT is not set +CONFIG_STMMAC_ETH=y +# CONFIG_DWMAC_GENERIC is not set +# CONFIG_NET_VENDOR_SYNOPSYS is not set +# CONFIG_NET_VENDOR_VIA is not set +# CONFIG_NET_VENDOR_WIZNET is not set +# CONFIG_NET_VENDOR_XILINX is not set +CONFIG_REALTEK_PHY=y +# CONFIG_USB_NET_DRIVERS is not set +# CONFIG_WLAN is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_KEYBOARD_ATKBD is not set +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_SUN4I_LRADC=y +# CONFIG_INPUT_MOUSE is not set +# CONFIG_SERIO is not set +# CONFIG_VT is not set +# CONFIG_LEGACY_PTYS is not set +# CONFIG_LDISC_AUTOLOAD is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=6 +CONFIG_SERIAL_8250_RUNTIME_UARTS=6 +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_EARLYCON_RISCV_SBI=y +CONFIG_HVC_RISCV_SBI=y +CONFIG_I2C=y +# CONFIG_I2C_COMPAT is not set +CONFIG_I2C_CHARDEV=y +# CONFIG_I2C_HELPER_AUTO is not set +CONFIG_I2C_MV64XXX=y +CONFIG_SPI=y +CONFIG_SPI_SUN6I=y +CONFIG_SPI_SPIDEV=y +# CONFIG_PTP_1588_CLOCK is not set +CONFIG_PINCTRL=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_PCF857X=y +CONFIG_POWER_SUPPLY=y +CONFIG_THERMAL=y +CONFIG_THERMAL_STATISTICS=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_CPU_THERMAL=y +CONFIG_THERMAL_EMULATION=y +CONFIG_SUN8I_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_SYSFS=y +CONFIG_SUNXI_WATCHDOG=y +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_PWM=y +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_HRTIMER=y +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +# CONFIG_SND_DRIVERS is not set +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=y +CONFIG_SND_SOC=y +CONFIG_SND_SUN20I_CODEC=y +CONFIG_SND_SUN4I_I2S=y +CONFIG_SND_SUN4I_SPDIF=y +# CONFIG_USB_HID is not set +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_OTG=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SUNXI=y +CONFIG_USB_SERIAL=y +CONFIG_USB_SERIAL_CH341=y +CONFIG_NOP_USB_XCEIV=y +CONFIG_USB_GADGET=y +CONFIG_USB_ETH=y +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_USB_ETH_EEM=y +CONFIG_MMC=y +CONFIG_MMC_SUNXI=y +CONFIG_NEW_LEDS=y +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_MULTICOLOR=y +CONFIG_LEDS_SUN20I=y +CONFIG_LEDS_TRIGGERS=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_MTD=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=y +CONFIG_RTC_CLASS=y +CONFIG_DMADEVICES=y +CONFIG_DMA_SUN6I=y +# CONFIG_VIRTIO_MENU is not set +# CONFIG_VHOST_MENU is not set +CONFIG_SUN8I_DE2_CCU=y +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_SUN6I=y +CONFIG_MAILBOX=y +CONFIG_SUN50I_IOMMU=y +CONFIG_REMOTEPROC=y +CONFIG_REMOTEPROC_CDEV=y +CONFIG_SUN8I_DSP_REMOTEPROC=y +CONFIG_RPMSG_CHAR=y +CONFIG_RPMSG_VIRTIO=y +CONFIG_PWM=y +CONFIG_PWM_SUN8I_V536=y +CONFIG_PHY_SUN4I_USB=y +CONFIG_NVMEM_SUNXI_SID=y +CONFIG_EXT4_FS=y +# CONFIG_MANDATORY_FILE_LOCKING is not set +# CONFIG_DNOTIFY is not set +CONFIG_FANOTIFY=y +CONFIG_TMPFS=y +CONFIG_TMPFS_XATTR=y +CONFIG_TMPFS_INODE64=y +# CONFIG_MISC_FILESYSTEMS is not set +# CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_RNG=y +CONFIG_CRYPTO_USER_API_AEAD=y +# CONFIG_CRYPTO_USER_API_ENABLE_OBSOLETE is not set +CONFIG_CRYPTO_DEV_SUN8I_CE=y +CONFIG_CRYPTO_DEV_SUN8I_CE_HASH=y +CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG=y +CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG=y +CONFIG_PRINTK_TIME=y +CONFIG_DEBUG_INFO=y +CONFIG_DEBUG_INFO_REDUCED=y +CONFIG_DEBUG_INFO_SPLIT=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +# CONFIG_FRAME_POINTER is not set +CONFIG_VMLINUX_MAP=y +CONFIG_MAGIC_SYSRQ=y +# CONFIG_MAGIC_SYSRQ_SERIAL is not set +CONFIG_DEBUG_FS=y +# CONFIG_DEBUG_MISC is not set +# CONFIG_SCHED_DEBUG is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_STACKTRACE=y +# CONFIG_RCU_TRACE is not set +# CONFIG_FTRACE is not set +# CONFIG_RUNTIME_TESTING_MENU is not set From 012f5a3d01be6d44e32c74bb3637ec281790b297 Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Tue, 12 Oct 2021 10:41:58 +0200 Subject: [PATCH 117/120] pinctrl: sunxi: sunxi_pinctrl_irq_ack avoid build warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Avoid a build warning drivers/pinctrl/sunxi/pinctrl-sunxi.c: In function ‘sunxi_pinctrl_irq_ack’: drivers/pinctrl/sunxi/pinctrl-sunxi.c:1035:2: warning: ISO C90 forbids mixed declarations and code [-Wdeclaration-after-statement] 1035 | u32 new = readl(pctl->membase + status_reg); | ^~~ Signed-off-by: Heinrich Schuchardt --- drivers/pinctrl/sunxi/pinctrl-sunxi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/pinctrl/sunxi/pinctrl-sunxi.c b/drivers/pinctrl/sunxi/pinctrl-sunxi.c index 11f25106b45f63..818a202c2096a8 100644 --- a/drivers/pinctrl/sunxi/pinctrl-sunxi.c +++ b/drivers/pinctrl/sunxi/pinctrl-sunxi.c @@ -1026,13 +1026,14 @@ static void sunxi_pinctrl_irq_ack(struct irq_data *d) struct sunxi_pinctrl *pctl = irq_data_get_irq_chip_data(d); u32 status_reg = sunxi_irq_status_reg(pctl->desc, d->hwirq); u8 status_idx = sunxi_irq_status_offset(d->hwirq); + u32 new, old; - u32 old = readl(pctl->membase + status_reg); + old = readl(pctl->membase + status_reg); /* Clear the IRQ */ writel(1 << status_idx, pctl->membase + status_reg); - u32 new = readl(pctl->membase + status_reg); + new = readl(pctl->membase + status_reg); pr_err("acked %ld in 0x%08x, was 0x%08x, now 0x%08x\n", d->hwirq, status_reg, old, new); From 3821b2ea5bcae426ccf2e120de558ff4fe73ad1c Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Tue, 16 Nov 2021 01:11:34 +0800 Subject: [PATCH 118/120] riscv: configs: nezha_fedora_defconfig --- arch/riscv/configs/nezha_fedora_defconfig | 2429 +++++++++++++++++++++ 1 file changed, 2429 insertions(+) create mode 100644 arch/riscv/configs/nezha_fedora_defconfig diff --git a/arch/riscv/configs/nezha_fedora_defconfig b/arch/riscv/configs/nezha_fedora_defconfig new file mode 100644 index 00000000000000..91a5133e20c12d --- /dev/null +++ b/arch/riscv/configs/nezha_fedora_defconfig @@ -0,0 +1,2429 @@ +CONFIG_DEFAULT_HOSTNAME="nezha" +CONFIG_SYSVIPC=y +CONFIG_POSIX_MQUEUE=y +CONFIG_WATCH_QUEUE=y +# CONFIG_CROSS_MEMORY_ATTACH is not set +CONFIG_AUDIT=y +CONFIG_NO_HZ_IDLE=y +CONFIG_HIGH_RES_TIMERS=y +CONFIG_PREEMPT=y +CONFIG_BSD_PROCESS_ACCT=y +CONFIG_BSD_PROCESS_ACCT_V3=y +CONFIG_TASKSTATS=y +CONFIG_TASK_DELAY_ACCT=y +CONFIG_TASK_XACCT=y +CONFIG_TASK_IO_ACCOUNTING=y +CONFIG_PSI=y +CONFIG_IKCONFIG=m +CONFIG_IKCONFIG_PROC=y +CONFIG_IKHEADERS=m +CONFIG_LOG_BUF_SHIFT=18 +CONFIG_PRINTK_SAFE_LOG_BUF_SHIFT=12 +CONFIG_CGROUPS=y +CONFIG_MEMCG=y +CONFIG_BLK_CGROUP=y +CONFIG_CGROUP_SCHED=y +CONFIG_CFS_BANDWIDTH=y +CONFIG_CGROUP_PIDS=y +CONFIG_CGROUP_FREEZER=y +CONFIG_CGROUP_DEVICE=y +CONFIG_CGROUP_CPUACCT=y +CONFIG_CGROUP_PERF=y +CONFIG_CGROUP_BPF=y +CONFIG_CGROUP_MISC=y +CONFIG_NAMESPACES=y +CONFIG_USER_NS=y +CONFIG_BLK_DEV_INITRD=y +CONFIG_EXPERT=y +CONFIG_USERFAULTFD=y +# CONFIG_COMPAT_BRK is not set +CONFIG_SLAB_FREELIST_HARDENED=y +CONFIG_SHUFFLE_PAGE_ALLOCATOR=y +CONFIG_PROFILING=y +CONFIG_SOC_SUNXI=y +CONFIG_PHYS_RAM_BASE=0x40000000 +CONFIG_PM=y +CONFIG_PM_DEBUG=y +CONFIG_JUMP_LABEL=y +# CONFIG_SECCOMP is not set +# CONFIG_STACKPROTECTOR is not set +# CONFIG_GCC_PLUGINS is not set +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_COMPRESS_XZ=y +CONFIG_BLK_DEV_ZONED=y +CONFIG_BLK_DEV_THROTTLING=y +CONFIG_BLK_WBT=y +CONFIG_BLK_CGROUP_IOLATENCY=y +CONFIG_BLK_CGROUP_IOCOST=y +CONFIG_BLK_SED_OPAL=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_AIX_PARTITION=y +CONFIG_OSF_PARTITION=y +CONFIG_AMIGA_PARTITION=y +CONFIG_MAC_PARTITION=y +CONFIG_BSD_DISKLABEL=y +CONFIG_MINIX_SUBPARTITION=y +CONFIG_SOLARIS_X86_PARTITION=y +CONFIG_UNIXWARE_DISKLABEL=y +CONFIG_LDM_PARTITION=y +CONFIG_SGI_PARTITION=y +CONFIG_SUN_PARTITION=y +CONFIG_KARMA_PARTITION=y +CONFIG_IOSCHED_BFQ=y +CONFIG_BFQ_GROUP_IOSCHED=y +CONFIG_BINFMT_MISC=m +CONFIG_SPARSEMEM_MANUAL=y +CONFIG_KSM=y +CONFIG_CLEANCACHE=y +CONFIG_FRONTSWAP=y +CONFIG_ZSWAP=y +CONFIG_Z3FOLD=y +CONFIG_ZSMALLOC=y +CONFIG_NET=y +CONFIG_PACKET=y +CONFIG_PACKET_DIAG=m +CONFIG_UNIX=y +CONFIG_UNIX_DIAG=m +CONFIG_TLS=m +CONFIG_XFRM_USER=y +CONFIG_XFRM_INTERFACE=m +CONFIG_XFRM_SUB_POLICY=y +CONFIG_XFRM_STATISTICS=y +CONFIG_NET_KEY=m +CONFIG_NET_KEY_MIGRATE=y +CONFIG_XDP_SOCKETS=y +CONFIG_XDP_SOCKETS_DIAG=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +CONFIG_IP_ADVANCED_ROUTER=y +CONFIG_IP_FIB_TRIE_STATS=y +CONFIG_IP_MULTIPLE_TABLES=y +CONFIG_IP_ROUTE_MULTIPATH=y +CONFIG_IP_ROUTE_VERBOSE=y +CONFIG_NET_IPIP=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_BROADCAST=y +CONFIG_IP_MROUTE=y +CONFIG_IP_MROUTE_MULTIPLE_TABLES=y +CONFIG_IP_PIMSM_V1=y +CONFIG_IP_PIMSM_V2=y +CONFIG_NET_IPVTI=m +CONFIG_NET_FOU_IP_TUNNELS=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_ESP_OFFLOAD=m +CONFIG_INET_IPCOMP=m +CONFIG_INET_DIAG=m +CONFIG_INET_UDP_DIAG=m +CONFIG_INET_RAW_DIAG=m +CONFIG_INET_DIAG_DESTROY=y +CONFIG_TCP_CONG_ADVANCED=y +CONFIG_TCP_CONG_HSTCP=m +CONFIG_TCP_CONG_HYBLA=m +CONFIG_TCP_CONG_NV=m +CONFIG_TCP_CONG_SCALABLE=m +CONFIG_TCP_CONG_LP=m +CONFIG_TCP_CONG_VENO=m +CONFIG_TCP_CONG_YEAH=m +CONFIG_TCP_CONG_ILLINOIS=m +CONFIG_TCP_CONG_DCTCP=m +CONFIG_TCP_CONG_CDG=m +CONFIG_TCP_CONG_BBR=m +CONFIG_TCP_MD5SIG=y +CONFIG_IPV6_ROUTER_PREF=y +CONFIG_IPV6_ROUTE_INFO=y +CONFIG_IPV6_OPTIMISTIC_DAD=y +CONFIG_INET6_AH=m +CONFIG_INET6_ESP=m +CONFIG_INET6_ESP_OFFLOAD=m +CONFIG_INET6_IPCOMP=m +CONFIG_IPV6_MIP6=y +CONFIG_IPV6_ILA=m +CONFIG_IPV6_VTI=m +CONFIG_IPV6_SIT=m +CONFIG_IPV6_SIT_6RD=y +CONFIG_IPV6_GRE=m +CONFIG_IPV6_SUBTREES=y +CONFIG_IPV6_MROUTE=y +CONFIG_IPV6_MROUTE_MULTIPLE_TABLES=y +CONFIG_IPV6_PIMSM_V2=y +CONFIG_IPV6_SEG6_LWTUNNEL=y +CONFIG_IPV6_SEG6_HMAC=y +CONFIG_NETFILTER=y +CONFIG_BRIDGE_NETFILTER=m +CONFIG_NF_CONNTRACK=y +CONFIG_NF_CONNTRACK_SECMARK=y +CONFIG_NF_CONNTRACK_ZONES=y +CONFIG_NF_CONNTRACK_EVENTS=y +CONFIG_NF_CONNTRACK_TIMESTAMP=y +CONFIG_NF_CONNTRACK_AMANDA=m +CONFIG_NF_CONNTRACK_FTP=m +CONFIG_NF_CONNTRACK_H323=m +CONFIG_NF_CONNTRACK_IRC=m +CONFIG_NF_CONNTRACK_NETBIOS_NS=m +CONFIG_NF_CONNTRACK_SNMP=m +CONFIG_NF_CONNTRACK_PPTP=m +CONFIG_NF_CONNTRACK_SANE=m +CONFIG_NF_CONNTRACK_SIP=m +CONFIG_NF_CONNTRACK_TFTP=m +CONFIG_NF_CT_NETLINK=m +CONFIG_NF_TABLES=m +CONFIG_NF_TABLES_INET=y +CONFIG_NF_TABLES_NETDEV=y +CONFIG_NFT_NUMGEN=m +CONFIG_NFT_CT=m +CONFIG_NFT_FLOW_OFFLOAD=m +CONFIG_NFT_COUNTER=m +CONFIG_NFT_LOG=m +CONFIG_NFT_LIMIT=m +CONFIG_NFT_MASQ=m +CONFIG_NFT_REDIR=m +CONFIG_NFT_NAT=m +CONFIG_NFT_TUNNEL=m +CONFIG_NFT_OBJREF=m +CONFIG_NFT_QUEUE=m +CONFIG_NFT_QUOTA=m +CONFIG_NFT_REJECT=m +CONFIG_NFT_COMPAT=m +CONFIG_NFT_HASH=m +CONFIG_NFT_FIB_INET=m +CONFIG_NFT_XFRM=m +CONFIG_NFT_SOCKET=m +CONFIG_NFT_TPROXY=m +CONFIG_NFT_SYNPROXY=m +CONFIG_NFT_DUP_NETDEV=m +CONFIG_NFT_FWD_NETDEV=m +CONFIG_NFT_FIB_NETDEV=m +CONFIG_NF_FLOW_TABLE_INET=m +CONFIG_NF_FLOW_TABLE=m +CONFIG_NETFILTER_XT_SET=m +CONFIG_NETFILTER_XT_TARGET_AUDIT=m +CONFIG_NETFILTER_XT_TARGET_CHECKSUM=m +CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m +CONFIG_NETFILTER_XT_TARGET_CONNMARK=m +CONFIG_NETFILTER_XT_TARGET_CONNSECMARK=m +CONFIG_NETFILTER_XT_TARGET_DSCP=m +CONFIG_NETFILTER_XT_TARGET_HL=y +CONFIG_NETFILTER_XT_TARGET_HMARK=m +CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m +CONFIG_NETFILTER_XT_TARGET_LED=m +CONFIG_NETFILTER_XT_TARGET_LOG=m +CONFIG_NETFILTER_XT_TARGET_MARK=m +CONFIG_NETFILTER_XT_TARGET_NFLOG=m +CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m +CONFIG_NETFILTER_XT_TARGET_NOTRACK=m +CONFIG_NETFILTER_XT_TARGET_TEE=m +CONFIG_NETFILTER_XT_TARGET_TPROXY=m +CONFIG_NETFILTER_XT_TARGET_TRACE=m +CONFIG_NETFILTER_XT_TARGET_SECMARK=m +CONFIG_NETFILTER_XT_TARGET_TCPMSS=m +CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m +CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m +CONFIG_NETFILTER_XT_MATCH_BPF=m +CONFIG_NETFILTER_XT_MATCH_CGROUP=m +CONFIG_NETFILTER_XT_MATCH_CLUSTER=m +CONFIG_NETFILTER_XT_MATCH_COMMENT=m +CONFIG_NETFILTER_XT_MATCH_CONNBYTES=m +CONFIG_NETFILTER_XT_MATCH_CONNLABEL=m +CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=m +CONFIG_NETFILTER_XT_MATCH_CONNMARK=m +CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y +CONFIG_NETFILTER_XT_MATCH_CPU=m +CONFIG_NETFILTER_XT_MATCH_DCCP=m +CONFIG_NETFILTER_XT_MATCH_DEVGROUP=m +CONFIG_NETFILTER_XT_MATCH_DSCP=m +CONFIG_NETFILTER_XT_MATCH_ESP=m +CONFIG_NETFILTER_XT_MATCH_HASHLIMIT=m +CONFIG_NETFILTER_XT_MATCH_HELPER=m +CONFIG_NETFILTER_XT_MATCH_IPCOMP=m +CONFIG_NETFILTER_XT_MATCH_IPRANGE=m +CONFIG_NETFILTER_XT_MATCH_IPVS=m +CONFIG_NETFILTER_XT_MATCH_LENGTH=m +CONFIG_NETFILTER_XT_MATCH_LIMIT=m +CONFIG_NETFILTER_XT_MATCH_MAC=m +CONFIG_NETFILTER_XT_MATCH_MARK=m +CONFIG_NETFILTER_XT_MATCH_MULTIPORT=m +CONFIG_NETFILTER_XT_MATCH_NFACCT=m +CONFIG_NETFILTER_XT_MATCH_OSF=m +CONFIG_NETFILTER_XT_MATCH_OWNER=m +CONFIG_NETFILTER_XT_MATCH_POLICY=m +CONFIG_NETFILTER_XT_MATCH_PHYSDEV=m +CONFIG_NETFILTER_XT_MATCH_PKTTYPE=m +CONFIG_NETFILTER_XT_MATCH_QUOTA=m +CONFIG_NETFILTER_XT_MATCH_RATEEST=m +CONFIG_NETFILTER_XT_MATCH_REALM=m +CONFIG_NETFILTER_XT_MATCH_RECENT=m +CONFIG_NETFILTER_XT_MATCH_SOCKET=m +CONFIG_NETFILTER_XT_MATCH_STATE=y +CONFIG_NETFILTER_XT_MATCH_STATISTIC=m +CONFIG_NETFILTER_XT_MATCH_STRING=m +CONFIG_NETFILTER_XT_MATCH_TCPMSS=m +CONFIG_NETFILTER_XT_MATCH_TIME=m +CONFIG_NETFILTER_XT_MATCH_U32=m +CONFIG_IP_SET=m +CONFIG_IP_SET_BITMAP_IP=m +CONFIG_IP_SET_BITMAP_IPMAC=m +CONFIG_IP_SET_BITMAP_PORT=m +CONFIG_IP_SET_HASH_IP=m +CONFIG_IP_SET_HASH_IPMARK=m +CONFIG_IP_SET_HASH_IPPORT=m +CONFIG_IP_SET_HASH_IPPORTIP=m +CONFIG_IP_SET_HASH_IPPORTNET=m +CONFIG_IP_SET_HASH_IPMAC=m +CONFIG_IP_SET_HASH_MAC=m +CONFIG_IP_SET_HASH_NETPORTNET=m +CONFIG_IP_SET_HASH_NET=m +CONFIG_IP_SET_HASH_NETNET=m +CONFIG_IP_SET_HASH_NETPORT=m +CONFIG_IP_SET_HASH_NETIFACE=m +CONFIG_IP_SET_LIST_SET=m +CONFIG_IP_VS=m +CONFIG_IP_VS_IPV6=y +CONFIG_IP_VS_PROTO_TCP=y +CONFIG_IP_VS_PROTO_UDP=y +CONFIG_IP_VS_PROTO_ESP=y +CONFIG_IP_VS_PROTO_AH=y +CONFIG_IP_VS_PROTO_SCTP=y +CONFIG_IP_VS_RR=m +CONFIG_IP_VS_WRR=m +CONFIG_IP_VS_LC=m +CONFIG_IP_VS_WLC=m +CONFIG_IP_VS_FO=m +CONFIG_IP_VS_OVF=m +CONFIG_IP_VS_LBLC=m +CONFIG_IP_VS_LBLCR=m +CONFIG_IP_VS_DH=m +CONFIG_IP_VS_SH=m +CONFIG_IP_VS_MH=m +CONFIG_IP_VS_SED=m +CONFIG_IP_VS_NQ=m +CONFIG_IP_VS_FTP=m +CONFIG_IP_VS_PE_SIP=m +CONFIG_NF_SOCKET_IPV4=y +CONFIG_NFT_DUP_IPV4=m +CONFIG_NFT_FIB_IPV4=m +CONFIG_NF_TABLES_ARP=y +CONFIG_NF_FLOW_TABLE_IPV4=m +CONFIG_NF_LOG_ARP=m +CONFIG_IP_NF_IPTABLES=y +CONFIG_IP_NF_MATCH_AH=m +CONFIG_IP_NF_MATCH_ECN=m +CONFIG_IP_NF_MATCH_RPFILTER=m +CONFIG_IP_NF_MATCH_TTL=m +CONFIG_IP_NF_FILTER=y +CONFIG_IP_NF_TARGET_REJECT=y +CONFIG_IP_NF_TARGET_SYNPROXY=m +CONFIG_IP_NF_NAT=y +CONFIG_IP_NF_TARGET_MASQUERADE=m +CONFIG_IP_NF_TARGET_NETMAP=m +CONFIG_IP_NF_TARGET_REDIRECT=m +CONFIG_IP_NF_MANGLE=y +CONFIG_IP_NF_TARGET_CLUSTERIP=m +CONFIG_IP_NF_TARGET_ECN=m +CONFIG_IP_NF_TARGET_TTL=m +CONFIG_IP_NF_RAW=y +CONFIG_IP_NF_ARPTABLES=m +CONFIG_IP_NF_ARPFILTER=m +CONFIG_IP_NF_ARP_MANGLE=m +CONFIG_NF_SOCKET_IPV6=y +CONFIG_NFT_DUP_IPV6=m +CONFIG_NFT_FIB_IPV6=m +CONFIG_NF_FLOW_TABLE_IPV6=m +CONFIG_IP6_NF_IPTABLES=y +CONFIG_IP6_NF_MATCH_AH=m +CONFIG_IP6_NF_MATCH_EUI64=m +CONFIG_IP6_NF_MATCH_FRAG=m +CONFIG_IP6_NF_MATCH_OPTS=m +CONFIG_IP6_NF_MATCH_HL=m +CONFIG_IP6_NF_MATCH_IPV6HEADER=m +CONFIG_IP6_NF_MATCH_MH=m +CONFIG_IP6_NF_MATCH_RPFILTER=m +CONFIG_IP6_NF_MATCH_RT=m +CONFIG_IP6_NF_MATCH_SRH=m +CONFIG_IP6_NF_TARGET_HL=m +CONFIG_IP6_NF_FILTER=y +CONFIG_IP6_NF_TARGET_REJECT=y +CONFIG_IP6_NF_TARGET_SYNPROXY=m +CONFIG_IP6_NF_MANGLE=y +CONFIG_IP6_NF_RAW=y +CONFIG_IP6_NF_NAT=y +CONFIG_IP6_NF_TARGET_MASQUERADE=m +CONFIG_IP6_NF_TARGET_NPT=m +CONFIG_NF_TABLES_BRIDGE=m +CONFIG_NFT_BRIDGE_META=m +CONFIG_NFT_BRIDGE_REJECT=m +CONFIG_NF_CONNTRACK_BRIDGE=m +CONFIG_BRIDGE_NF_EBTABLES=m +CONFIG_BRIDGE_EBT_BROUTE=m +CONFIG_BRIDGE_EBT_T_FILTER=m +CONFIG_BRIDGE_EBT_T_NAT=m +CONFIG_BRIDGE_EBT_802_3=m +CONFIG_BRIDGE_EBT_AMONG=m +CONFIG_BRIDGE_EBT_ARP=m +CONFIG_BRIDGE_EBT_IP=m +CONFIG_BRIDGE_EBT_IP6=m +CONFIG_BRIDGE_EBT_LIMIT=m +CONFIG_BRIDGE_EBT_MARK=m +CONFIG_BRIDGE_EBT_PKTTYPE=m +CONFIG_BRIDGE_EBT_STP=m +CONFIG_BRIDGE_EBT_VLAN=m +CONFIG_BRIDGE_EBT_ARPREPLY=m +CONFIG_BRIDGE_EBT_DNAT=m +CONFIG_BRIDGE_EBT_MARK_T=m +CONFIG_BRIDGE_EBT_REDIRECT=m +CONFIG_BRIDGE_EBT_SNAT=m +CONFIG_BRIDGE_EBT_LOG=m +CONFIG_BRIDGE_EBT_NFLOG=m +CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1=y +CONFIG_SCTP_COOKIE_HMAC_MD5=y +CONFIG_RDS=m +CONFIG_RDS_TCP=m +CONFIG_TIPC=m +CONFIG_ATM=m +CONFIG_ATM_CLIP=m +CONFIG_ATM_LANE=m +CONFIG_ATM_BR2684=m +CONFIG_L2TP=m +CONFIG_L2TP_DEBUGFS=m +CONFIG_L2TP_V3=y +CONFIG_L2TP_IP=m +CONFIG_L2TP_ETH=m +CONFIG_BRIDGE=y +CONFIG_NET_DSA=m +CONFIG_NET_DSA_TAG_GSWIP=m +CONFIG_NET_DSA_TAG_SJA1105=m +CONFIG_NET_DSA_TAG_TRAILER=m +CONFIG_ATALK=m +CONFIG_DEV_APPLETALK=m +CONFIG_IPDDP=m +CONFIG_IPDDP_ENCAP=y +CONFIG_6LOWPAN=m +CONFIG_6LOWPAN_DEBUGFS=y +CONFIG_6LOWPAN_GHC_EXT_HDR_HOP=m +CONFIG_6LOWPAN_GHC_UDP=m +CONFIG_6LOWPAN_GHC_ICMPV6=m +CONFIG_6LOWPAN_GHC_EXT_HDR_DEST=m +CONFIG_6LOWPAN_GHC_EXT_HDR_FRAG=m +CONFIG_6LOWPAN_GHC_EXT_HDR_ROUTE=m +CONFIG_IEEE802154=m +CONFIG_IEEE802154_6LOWPAN=m +CONFIG_MAC802154=m +CONFIG_NET_SCHED=y +CONFIG_NET_SCH_CBQ=m +CONFIG_NET_SCH_HTB=m +CONFIG_NET_SCH_HFSC=m +CONFIG_NET_SCH_ATM=m +CONFIG_NET_SCH_PRIO=m +CONFIG_NET_SCH_MULTIQ=m +CONFIG_NET_SCH_RED=m +CONFIG_NET_SCH_SFB=m +CONFIG_NET_SCH_SFQ=m +CONFIG_NET_SCH_TEQL=m +CONFIG_NET_SCH_TBF=m +CONFIG_NET_SCH_CBS=m +CONFIG_NET_SCH_ETF=m +CONFIG_NET_SCH_TAPRIO=m +CONFIG_NET_SCH_GRED=m +CONFIG_NET_SCH_DSMARK=m +CONFIG_NET_SCH_NETEM=m +CONFIG_NET_SCH_DRR=m +CONFIG_NET_SCH_MQPRIO=m +CONFIG_NET_SCH_CHOKE=m +CONFIG_NET_SCH_QFQ=m +CONFIG_NET_SCH_CODEL=m +CONFIG_NET_SCH_FQ_CODEL=y +CONFIG_NET_SCH_CAKE=m +CONFIG_NET_SCH_FQ=m +CONFIG_NET_SCH_HHF=m +CONFIG_NET_SCH_PIE=m +CONFIG_NET_SCH_INGRESS=m +CONFIG_NET_SCH_PLUG=m +CONFIG_NET_CLS_BASIC=m +CONFIG_NET_CLS_TCINDEX=m +CONFIG_NET_CLS_ROUTE4=m +CONFIG_NET_CLS_FW=m +CONFIG_NET_CLS_U32=m +CONFIG_CLS_U32_PERF=y +CONFIG_CLS_U32_MARK=y +CONFIG_NET_CLS_RSVP=m +CONFIG_NET_CLS_RSVP6=m +CONFIG_NET_CLS_FLOW=m +CONFIG_NET_CLS_CGROUP=y +CONFIG_NET_CLS_BPF=m +CONFIG_NET_CLS_FLOWER=m +CONFIG_NET_CLS_MATCHALL=m +CONFIG_NET_EMATCH=y +CONFIG_NET_EMATCH_CMP=m +CONFIG_NET_EMATCH_NBYTE=m +CONFIG_NET_EMATCH_U32=m +CONFIG_NET_EMATCH_META=m +CONFIG_NET_EMATCH_TEXT=m +CONFIG_NET_EMATCH_CANID=m +CONFIG_NET_EMATCH_IPSET=m +CONFIG_NET_EMATCH_IPT=m +CONFIG_NET_CLS_ACT=y +CONFIG_NET_ACT_POLICE=m +CONFIG_NET_ACT_GACT=m +CONFIG_GACT_PROB=y +CONFIG_NET_ACT_MIRRED=m +CONFIG_NET_ACT_SAMPLE=m +CONFIG_NET_ACT_IPT=m +CONFIG_NET_ACT_NAT=m +CONFIG_NET_ACT_PEDIT=m +CONFIG_NET_ACT_SIMP=m +CONFIG_NET_ACT_SKBEDIT=m +CONFIG_NET_ACT_CSUM=m +CONFIG_NET_ACT_MPLS=m +CONFIG_NET_ACT_VLAN=m +CONFIG_NET_ACT_BPF=m +CONFIG_NET_ACT_CONNMARK=m +CONFIG_NET_ACT_CTINFO=m +CONFIG_NET_ACT_SKBMOD=m +CONFIG_NET_ACT_IFE=m +CONFIG_NET_ACT_TUNNEL_KEY=m +CONFIG_NET_ACT_CT=m +CONFIG_NET_IFE_SKBMARK=m +CONFIG_NET_IFE_SKBPRIO=m +CONFIG_NET_IFE_SKBTCINDEX=m +CONFIG_NET_TC_SKB_EXT=y +CONFIG_DCB=y +CONFIG_BATMAN_ADV=m +CONFIG_BATMAN_ADV_NC=y +CONFIG_OPENVSWITCH=m +CONFIG_VSOCKETS=m +CONFIG_VIRTIO_VSOCKETS=m +CONFIG_NETLINK_DIAG=m +CONFIG_MPLS_ROUTING=m +CONFIG_MPLS_IPTUNNEL=m +CONFIG_NET_NCSI=y +CONFIG_NCSI_OEM_CMD_GET_MAC=y +CONFIG_CGROUP_NET_PRIO=y +CONFIG_NET_PKTGEN=m +CONFIG_HAMRADIO=y +CONFIG_AX25=m +CONFIG_NETROM=m +CONFIG_ROSE=m +CONFIG_MKISS=m +CONFIG_6PACK=m +CONFIG_BPQETHER=m +CONFIG_BAYCOM_SER_FDX=m +CONFIG_BAYCOM_SER_HDX=m +CONFIG_YAM=m +CONFIG_CAN=m +CONFIG_CAN_VCAN=m +CONFIG_CAN_VXCAN=m +CONFIG_CAN_SLCAN=m +CONFIG_CAN_C_CAN=m +CONFIG_CAN_C_CAN_PLATFORM=m +CONFIG_CAN_C_CAN_PCI=m +CONFIG_CAN_CC770=m +CONFIG_CAN_CC770_PLATFORM=m +CONFIG_CAN_IFI_CANFD=m +CONFIG_CAN_M_CAN=m +CONFIG_CAN_PEAK_PCIEFD=m +CONFIG_CAN_SJA1000=m +CONFIG_CAN_EMS_PCI=m +CONFIG_CAN_KVASER_PCI=m +CONFIG_CAN_PEAK_PCI=m +CONFIG_CAN_PLX_PCI=m +CONFIG_CAN_SJA1000_PLATFORM=m +CONFIG_CAN_SOFTING=m +CONFIG_CAN_HI311X=m +CONFIG_CAN_8DEV_USB=m +CONFIG_CAN_EMS_USB=m +CONFIG_CAN_ESD_USB2=m +CONFIG_CAN_GS_USB=m +CONFIG_CAN_KVASER_USB=m +CONFIG_CAN_MCBA_USB=m +CONFIG_CAN_PEAK_USB=m +CONFIG_BT=m +CONFIG_BT_RFCOMM=m +CONFIG_BT_RFCOMM_TTY=y +CONFIG_BT_BNEP=m +CONFIG_BT_BNEP_MC_FILTER=y +CONFIG_BT_BNEP_PROTO_FILTER=y +CONFIG_BT_HIDP=m +CONFIG_BT_6LOWPAN=m +CONFIG_BT_LEDS=y +# CONFIG_BT_DEBUGFS is not set +CONFIG_BT_HCIBTUSB=m +CONFIG_BT_HCIBTUSB_AUTOSUSPEND=y +CONFIG_BT_HCIBTSDIO=m +CONFIG_BT_HCIUART=m +CONFIG_BT_HCIUART_BCSP=y +CONFIG_BT_HCIUART_ATH3K=y +CONFIG_BT_HCIUART_INTEL=y +CONFIG_BT_HCIUART_AG6XX=y +CONFIG_BT_HCIBCM203X=m +CONFIG_BT_HCIBPA10X=m +CONFIG_BT_HCIBFUSB=m +CONFIG_BT_HCIDTL1=m +CONFIG_BT_HCIBT3C=m +CONFIG_BT_HCIBLUECARD=m +CONFIG_BT_HCIVHCI=m +CONFIG_BT_MRVL=m +CONFIG_BT_MRVL_SDIO=m +CONFIG_BT_ATH3K=m +CONFIG_BT_MTKSDIO=m +CONFIG_AF_RXRPC_IPV6=y +CONFIG_AF_RXRPC_DEBUG=y +CONFIG_RXKAD=y +CONFIG_AF_KCM=m +CONFIG_CFG80211=m +CONFIG_CFG80211_DEBUGFS=y +CONFIG_MAC80211=m +CONFIG_MAC80211_MESH=y +CONFIG_MAC80211_DEBUGFS=y +CONFIG_RFKILL=y +CONFIG_RFKILL_INPUT=y +CONFIG_RFKILL_GPIO=m +CONFIG_NET_9P=m +CONFIG_NET_9P_VIRTIO=m +CONFIG_NFC=m +CONFIG_NFC_DIGITAL=m +CONFIG_NFC_NCI=m +CONFIG_NFC_NCI_SPI=m +CONFIG_NFC_HCI=m +CONFIG_NFC_SHDLC=y +CONFIG_NFC_TRF7970A=m +CONFIG_NFC_SIM=m +CONFIG_NFC_PORT100=m +CONFIG_NFC_PN544_I2C=m +CONFIG_NFC_PN533_USB=m +CONFIG_NFC_PN533_I2C=m +CONFIG_NFC_MICROREAD_I2C=m +CONFIG_NFC_MRVL_USB=m +CONFIG_NFC_ST21NFCA_I2C=m +CONFIG_NFC_NXP_NCI=m +CONFIG_NFC_NXP_NCI_I2C=m +CONFIG_PCI=y +CONFIG_PCIEPORTBUS=y +CONFIG_HOTPLUG_PCI_PCIE=y +CONFIG_PCIE_PTM=y +CONFIG_PCI_DEBUG=y +CONFIG_PCI_STUB=y +CONFIG_PCI_PF_STUB=m +CONFIG_PCI_IOV=y +CONFIG_PCI_PRI=y +CONFIG_PCI_PASID=y +CONFIG_HOTPLUG_PCI=y +CONFIG_PCI_HOST_GENERIC=y +CONFIG_PCIE_XILINX=y +CONFIG_PCI_ENDPOINT=y +CONFIG_PCI_SW_SWITCHTEC=y +CONFIG_PCCARD=y +CONFIG_YENTA=m +CONFIG_PD6729=m +CONFIG_I82092=m +CONFIG_RAPIDIO=m +CONFIG_RAPIDIO_TSI721=m +CONFIG_RAPIDIO_ENUM_BASIC=m +CONFIG_RAPIDIO_CHMAN=m +CONFIG_RAPIDIO_MPORT_CDEV=m +CONFIG_RAPIDIO_TSI57X=m +CONFIG_RAPIDIO_CPS_XX=m +CONFIG_RAPIDIO_TSI568=m +CONFIG_RAPIDIO_CPS_GEN2=m +CONFIG_RAPIDIO_RXS_GEN3=m +CONFIG_DEVTMPFS=y +CONFIG_DEVTMPFS_MOUNT=y +CONFIG_FW_LOADER_COMPRESS=y +CONFIG_DEBUG_DEVRES=y +CONFIG_MTD=y +CONFIG_MTD_OF_PARTS=m +CONFIG_MTD_BLOCK=y +CONFIG_MTD_PARTITIONED_MASTER=y +CONFIG_MTD_CFI=y +CONFIG_MTD_CFI_INTELEXT=y +CONFIG_MTD_CFI_AMDSTD=y +CONFIG_MTD_CFI_STAA=y +CONFIG_MTD_PHYSMAP=y +CONFIG_MTD_BLOCK2MTD=m +CONFIG_MTD_RAW_NAND=m +CONFIG_MTD_SPI_NAND=y +CONFIG_MTD_SPI_NOR=y +# CONFIG_MTD_SPI_NOR_USE_4K_SECTORS is not set +CONFIG_MTD_UBI=y +CONFIG_MTD_UBI_FASTMAP=y +CONFIG_MTD_UBI_BLOCK=y +CONFIG_BLK_DEV_NULL_BLK=m +CONFIG_ZRAM=m +CONFIG_BLK_DEV_LOOP=y +CONFIG_BLK_DEV_LOOP_MIN_COUNT=0 +CONFIG_BLK_DEV_DRBD=m +CONFIG_BLK_DEV_NBD=y +CONFIG_BLK_DEV_SX8=m +CONFIG_BLK_DEV_RAM=m +CONFIG_BLK_DEV_RAM_SIZE=16384 +CONFIG_CDROM_PKTCDVD=m +CONFIG_ATA_OVER_ETH=m +CONFIG_VIRTIO_BLK=y +CONFIG_BLK_DEV_RBD=m +CONFIG_BLK_DEV_NVME=m +CONFIG_NVME_MULTIPATH=y +CONFIG_NVME_FC=m +CONFIG_NVME_TCP=m +CONFIG_NVME_TARGET=m +CONFIG_NVME_TARGET_LOOP=m +CONFIG_NVME_TARGET_FC=m +CONFIG_NVME_TARGET_FCLOOP=m +CONFIG_NVME_TARGET_TCP=m +CONFIG_ENCLOSURE_SERVICES=m +CONFIG_APDS9802ALS=m +CONFIG_ISL29003=m +CONFIG_ISL29020=m +CONFIG_SENSORS_TSL2550=m +CONFIG_SENSORS_BH1770=m +CONFIG_SENSORS_APDS990X=m +CONFIG_EEPROM_AT24=m +CONFIG_EEPROM_LEGACY=m +CONFIG_EEPROM_MAX6875=m +CONFIG_EEPROM_IDT_89HPESX=m +CONFIG_EEPROM_EE1004=m +CONFIG_SENSORS_LIS3_I2C=m +CONFIG_ALTERA_STAPL=m +CONFIG_ECHO=m +CONFIG_MISC_ALCOR_PCI=m +CONFIG_MISC_RTSX_PCI=m +CONFIG_MISC_RTSX_USB=m +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=m +CONFIG_BLK_DEV_SR=y +CONFIG_CHR_DEV_SG=y +CONFIG_CHR_DEV_SCH=m +CONFIG_SCSI_ENCLOSURE=m +CONFIG_SCSI_CONSTANTS=y +CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_SCAN_ASYNC=y +CONFIG_SCSI_FC_ATTRS=m +CONFIG_SCSI_SAS_ATA=y +CONFIG_ISCSI_TCP=m +CONFIG_SCSI_CXGB3_ISCSI=m +CONFIG_SCSI_CXGB4_ISCSI=m +CONFIG_SCSI_BNX2_ISCSI=m +CONFIG_SCSI_BNX2X_FCOE=m +CONFIG_BE2ISCSI=m +CONFIG_BLK_DEV_3W_XXXX_RAID=m +CONFIG_SCSI_HPSA=m +CONFIG_SCSI_3W_9XXX=m +CONFIG_SCSI_3W_SAS=m +CONFIG_SCSI_ACARD=m +CONFIG_SCSI_AACRAID=m +CONFIG_SCSI_AIC7XXX=m +CONFIG_AIC7XXX_CMDS_PER_DEVICE=4 +CONFIG_AIC7XXX_RESET_DELAY_MS=15000 +# CONFIG_AIC7XXX_DEBUG_ENABLE is not set +# CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_AIC79XX=m +CONFIG_AIC79XX_CMDS_PER_DEVICE=4 +CONFIG_AIC79XX_RESET_DELAY_MS=15000 +# CONFIG_AIC79XX_DEBUG_ENABLE is not set +# CONFIG_AIC79XX_REG_PRETTY_PRINT is not set +CONFIG_SCSI_MVSAS=m +# CONFIG_SCSI_MVSAS_DEBUG is not set +CONFIG_SCSI_MVSAS_TASKLET=y +CONFIG_SCSI_MVUMI=m +CONFIG_SCSI_ARCMSR=m +CONFIG_SCSI_ESAS2R=m +CONFIG_MEGARAID_NEWGEN=y +CONFIG_MEGARAID_MM=m +CONFIG_MEGARAID_MAILBOX=m +CONFIG_MEGARAID_LEGACY=m +CONFIG_MEGARAID_SAS=m +CONFIG_SCSI_MPT2SAS=m +CONFIG_SCSI_SMARTPQI=m +CONFIG_SCSI_HPTIOP=m +CONFIG_SCSI_MYRB=m +CONFIG_SCSI_MYRS=m +CONFIG_LIBFC=m +CONFIG_LIBFCOE=m +CONFIG_FCOE=m +CONFIG_SCSI_SNIC=m +CONFIG_SCSI_DMX3191D=m +CONFIG_SCSI_FDOMAIN_PCI=m +CONFIG_SCSI_IPS=m +CONFIG_SCSI_INITIO=m +CONFIG_SCSI_INIA100=m +CONFIG_SCSI_STEX=m +CONFIG_SCSI_SYM53C8XX_2=m +CONFIG_SCSI_IPR=m +CONFIG_SCSI_QLOGIC_1280=m +CONFIG_SCSI_QLA_FC=m +CONFIG_TCM_QLA2XXX=m +CONFIG_SCSI_QLA_ISCSI=m +CONFIG_QEDI=m +CONFIG_QEDF=m +CONFIG_SCSI_DC395x=m +CONFIG_SCSI_AM53C974=m +CONFIG_SCSI_WD719X=m +CONFIG_SCSI_DEBUG=m +CONFIG_SCSI_PMCRAID=m +CONFIG_SCSI_PM8001=m +CONFIG_SCSI_BFA_FC=m +CONFIG_SCSI_VIRTIO=y +CONFIG_SCSI_CHELSIO_FCOE=m +CONFIG_SCSI_DH=y +CONFIG_SCSI_DH_RDAC=m +CONFIG_SCSI_DH_HP_SW=m +CONFIG_SCSI_DH_EMC=m +CONFIG_SCSI_DH_ALUA=m +CONFIG_ATA=y +CONFIG_SATA_AHCI=y +CONFIG_SATA_MOBILE_LPM_POLICY=3 +CONFIG_SATA_AHCI_PLATFORM=m +CONFIG_SATA_INIC162X=m +CONFIG_SATA_ACARD_AHCI=m +CONFIG_SATA_SIL24=m +CONFIG_PDC_ADMA=m +CONFIG_SATA_QSTOR=m +CONFIG_SATA_SX4=m +# CONFIG_ATA_BMDMA is not set +CONFIG_PATA_CMD640_PCI=m +CONFIG_PATA_NS87410=m +CONFIG_PATA_OPTI=m +CONFIG_PATA_PCMCIA=m +CONFIG_MD=y +CONFIG_MD_LINEAR=m +CONFIG_MD_MULTIPATH=m +CONFIG_MD_FAULTY=m +CONFIG_BCACHE=m +CONFIG_BLK_DEV_DM=y +CONFIG_DM_DEBUG=y +CONFIG_DM_DEBUG_BLOCK_MANAGER_LOCKING=y +CONFIG_DM_UNSTRIPED=y +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=y +CONFIG_DM_THIN_PROVISIONING=y +CONFIG_DM_CACHE=y +CONFIG_DM_WRITECACHE=m +CONFIG_DM_MIRROR=y +CONFIG_DM_LOG_USERSPACE=y +CONFIG_DM_RAID=y +CONFIG_DM_ZERO=y +CONFIG_DM_MULTIPATH=y +CONFIG_DM_MULTIPATH_QL=y +CONFIG_DM_MULTIPATH_ST=y +CONFIG_DM_DELAY=y +CONFIG_DM_DUST=m +CONFIG_DM_INIT=y +CONFIG_DM_UEVENT=y +CONFIG_DM_FLAKEY=y +CONFIG_DM_VERITY=y +CONFIG_DM_VERITY_FEC=y +CONFIG_DM_SWITCH=y +CONFIG_DM_LOG_WRITES=y +CONFIG_DM_INTEGRITY=y +CONFIG_DM_ZONED=y +CONFIG_TARGET_CORE=y +CONFIG_TCM_IBLOCK=y +CONFIG_TCM_FILEIO=y +CONFIG_TCM_PSCSI=y +CONFIG_TCM_USER2=m +CONFIG_LOOPBACK_TARGET=m +CONFIG_TCM_FC=m +CONFIG_ISCSI_TARGET=m +CONFIG_ISCSI_TARGET_CXGB4=m +CONFIG_SBP_TARGET=m +CONFIG_FUSION=y +CONFIG_FUSION_SPI=m +CONFIG_FUSION_FC=m +CONFIG_FUSION_SAS=m +CONFIG_FUSION_MAX_SGE=40 +CONFIG_FUSION_CTL=m +CONFIG_FUSION_LAN=m +CONFIG_FUSION_LOGGING=y +CONFIG_FIREWIRE=m +CONFIG_FIREWIRE_OHCI=m +CONFIG_FIREWIRE_SBP2=m +CONFIG_FIREWIRE_NET=m +CONFIG_FIREWIRE_NOSY=m +CONFIG_BONDING=m +CONFIG_DUMMY=m +CONFIG_EQUALIZER=m +CONFIG_NET_FC=y +CONFIG_IFB=m +CONFIG_NET_TEAM=m +CONFIG_NET_TEAM_MODE_BROADCAST=m +CONFIG_NET_TEAM_MODE_ROUNDROBIN=m +CONFIG_NET_TEAM_MODE_RANDOM=m +CONFIG_NET_TEAM_MODE_ACTIVEBACKUP=m +CONFIG_NET_TEAM_MODE_LOADBALANCE=m +CONFIG_MACVLAN=m +CONFIG_MACVTAP=m +CONFIG_IPVLAN=m +CONFIG_IPVTAP=m +CONFIG_GENEVE=m +CONFIG_GTP=m +CONFIG_MACSEC=m +CONFIG_NETCONSOLE=m +CONFIG_NETCONSOLE_DYNAMIC=y +CONFIG_RIONET=m +CONFIG_TUN=m +CONFIG_VETH=m +CONFIG_VIRTIO_NET=y +CONFIG_NLMON=m +CONFIG_NET_VRF=m +CONFIG_ATM_TCP=m +CONFIG_ATM_ENI=m +CONFIG_ATM_NICSTAR=m +CONFIG_ATM_HE=m +CONFIG_ATM_SOLOS=m +CONFIG_B53_SPI_DRIVER=m +CONFIG_B53_MDIO_DRIVER=m +CONFIG_B53_MMAP_DRIVER=m +CONFIG_B53_SRAB_DRIVER=m +CONFIG_B53_SERDES=m +CONFIG_NET_DSA_BCM_SF2=m +CONFIG_NET_DSA_LOOP=m +CONFIG_NET_DSA_MT7530=m +CONFIG_NET_DSA_MICROCHIP_KSZ9477=m +CONFIG_NET_DSA_MICROCHIP_KSZ9477_SPI=m +CONFIG_NET_DSA_MV88E6XXX=m +CONFIG_NET_DSA_MV88E6XXX_PTP=y +CONFIG_NET_DSA_QCA8K=m +CONFIG_NET_DSA_SMSC_LAN9303_I2C=m +CONFIG_NET_DSA_SMSC_LAN9303_MDIO=m +CONFIG_PCMCIA_3C574=m +CONFIG_PCMCIA_3C589=m +CONFIG_VORTEX=m +CONFIG_TYPHOON=m +CONFIG_ADAPTEC_STARFIRE=m +CONFIG_ET131X=m +# CONFIG_NET_VENDOR_ALACRITECH is not set +CONFIG_ACENIC=m +CONFIG_ALTERA_TSE=m +CONFIG_AMD8111_ETH=m +CONFIG_PCNET32=m +CONFIG_PCMCIA_NMCLAN=m +CONFIG_ATL2=m +CONFIG_ATL1=m +CONFIG_ATL1E=m +CONFIG_ATL1C=m +CONFIG_ALX=m +CONFIG_B44=m +CONFIG_BCMGENET=m +CONFIG_TIGON3=m +CONFIG_BNX2X=m +CONFIG_BNXT=m +CONFIG_BNXT_DCB=y +CONFIG_BNA=m +CONFIG_MACB=m +CONFIG_MACB_PCI=m +# CONFIG_NET_VENDOR_CAVIUM is not set +CONFIG_CHELSIO_T1=m +CONFIG_CHELSIO_T1_1G=y +CONFIG_CHELSIO_T4_DCB=y +CONFIG_CHELSIO_T4VF=m +CONFIG_CHELSIO_IPSEC_INLINE=m +CONFIG_ENIC=m +# CONFIG_NET_VENDOR_CORTINA is not set +CONFIG_DNET=m +CONFIG_NET_TULIP=y +CONFIG_DE2104X=m +CONFIG_TULIP=m +CONFIG_TULIP_MMIO=y +CONFIG_WINBOND_840=m +CONFIG_DM9102=m +CONFIG_ULI526X=m +CONFIG_PCMCIA_XIRCOM=m +CONFIG_DL2K=m +CONFIG_SUNDANCE=m +# CONFIG_BE2NET_HWMON is not set +# CONFIG_NET_VENDOR_EZCHIP is not set +# CONFIG_NET_VENDOR_FUJITSU is not set +# CONFIG_NET_VENDOR_HUAWEI is not set +# CONFIG_NET_VENDOR_I825XX is not set +CONFIG_E100=m +CONFIG_E1000=m +CONFIG_E1000E=m +CONFIG_IGB=m +CONFIG_IGBVF=m +CONFIG_IXGB=m +CONFIG_IXGBE=m +CONFIG_IXGBE_DCB=y +CONFIG_IXGBEVF=m +CONFIG_I40E=m +CONFIG_I40EVF=m +CONFIG_ICE=m +CONFIG_FM10K=m +CONFIG_IGC=m +CONFIG_JME=m +CONFIG_MVMDIO=m +CONFIG_SKGE=m +CONFIG_SKGE_GENESIS=y +CONFIG_SKY2=m +CONFIG_MLX4_EN=m +CONFIG_MLX5_CORE=m +CONFIG_MLX5_CORE_EN=y +CONFIG_MLX5_CORE_IPOIB=y +CONFIG_MLXSW_CORE=m +CONFIG_KSZ884X_PCI=m +# CONFIG_NET_VENDOR_MICROCHIP is not set +# CONFIG_NET_VENDOR_MICROSEMI is not set +CONFIG_MYRI10GE=m +CONFIG_FEALNX=m +CONFIG_NATSEMI=m +CONFIG_NS83820=m +CONFIG_S2IO=m +CONFIG_VXGE=m +CONFIG_NFP=m +# CONFIG_NFP_APP_ABM_NIC is not set +# CONFIG_NET_VENDOR_NI is not set +CONFIG_PCMCIA_AXNET=m +CONFIG_NE2K_PCI=m +CONFIG_PCMCIA_PCNET=m +CONFIG_FORCEDETH=m +CONFIG_ETHOC=m +CONFIG_HAMACHI=m +CONFIG_YELLOWFIN=m +CONFIG_QLA3XXX=m +CONFIG_QLCNIC=m +CONFIG_NETXEN_NIC=m +CONFIG_QED=m +CONFIG_QEDE=m +# CONFIG_NET_VENDOR_QUALCOMM is not set +CONFIG_R6040=m +CONFIG_8139CP=m +CONFIG_8139TOO=m +# CONFIG_8139TOO_PIO is not set +CONFIG_8139TOO_8129=y +CONFIG_R8169=m +# CONFIG_NET_VENDOR_RENESAS is not set +CONFIG_ROCKER=m +# CONFIG_NET_VENDOR_SAMSUNG is not set +# CONFIG_NET_VENDOR_SEEQ is not set +# CONFIG_NET_VENDOR_SOLARFLARE is not set +CONFIG_SC92031=m +CONFIG_SIS900=m +CONFIG_SIS190=m +CONFIG_PCMCIA_SMC91C92=m +CONFIG_EPIC100=m +CONFIG_SMSC911X=m +CONFIG_SMSC9420=m +# CONFIG_NET_VENDOR_SOCIONEXT is not set +CONFIG_HAPPYMEAL=m +CONFIG_SUNGEM=m +CONFIG_CASSINI=m +CONFIG_NIU=m +# CONFIG_NET_VENDOR_SYNOPSYS is not set +CONFIG_TEHUTI=m +CONFIG_TLAN=m +CONFIG_VIA_RHINE=m +CONFIG_VIA_RHINE_MMIO=y +CONFIG_VIA_VELOCITY=m +CONFIG_WIZNET_W5100=m +CONFIG_WIZNET_W5300=m +CONFIG_WIZNET_W5100_SPI=m +CONFIG_PCMCIA_XIRC2PS=m +CONFIG_LED_TRIGGER_PHY=y +CONFIG_SFP=m +CONFIG_AMD_PHY=m +CONFIG_ADIN_PHY=m +CONFIG_AQUANTIA_PHY=m +CONFIG_BROADCOM_PHY=m +CONFIG_BCM87XX_PHY=m +CONFIG_CICADA_PHY=m +CONFIG_CORTINA_PHY=m +CONFIG_DAVICOM_PHY=m +CONFIG_ICPLUS_PHY=m +CONFIG_LXT_PHY=m +CONFIG_INTEL_XWAY_PHY=m +CONFIG_LSI_ET1011C_PHY=m +CONFIG_MARVELL_PHY=m +CONFIG_MARVELL_10G_PHY=m +CONFIG_MICREL_PHY=m +CONFIG_MICROSEMI_PHY=m +CONFIG_NATIONAL_PHY=m +CONFIG_QSEMI_PHY=m +CONFIG_STE10XP=m +CONFIG_TERANETICS_PHY=m +CONFIG_DP83822_PHY=m +CONFIG_DP83848_PHY=m +CONFIG_VITESSE_PHY=m +CONFIG_XILINX_GMII2RGMII=m +CONFIG_MDIO_BITBANG=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_FILTER=y +CONFIG_PPP_MPPE=m +CONFIG_PPP_MULTILINK=y +CONFIG_PPPOATM=m +CONFIG_PPPOE=m +CONFIG_PPTP=m +CONFIG_PPPOL2TP=m +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_SLIP=m +CONFIG_SLIP_COMPRESSED=y +CONFIG_SLIP_SMART=y +CONFIG_USB_CATC=m +CONFIG_USB_KAWETH=m +CONFIG_USB_PEGASUS=m +CONFIG_USB_RTL8150=m +CONFIG_USB_RTL8152=m +CONFIG_USB_LAN78XX=m +CONFIG_USB_NET_CDC_EEM=m +CONFIG_USB_NET_HUAWEI_CDC_NCM=m +CONFIG_USB_NET_CDC_MBIM=m +CONFIG_USB_NET_DM9601=m +CONFIG_USB_NET_SR9700=m +CONFIG_USB_NET_SMSC75XX=m +CONFIG_USB_NET_SMSC95XX=m +CONFIG_USB_NET_GL620A=m +CONFIG_USB_NET_PLUSB=m +CONFIG_USB_NET_MCS7830=m +CONFIG_USB_ALI_M5632=y +CONFIG_USB_AN2720=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_KC2190=y +CONFIG_USB_NET_CX82310_ETH=m +CONFIG_USB_NET_KALMIA=m +CONFIG_USB_NET_QMI_WWAN=m +CONFIG_USB_HSO=m +CONFIG_USB_NET_INT51X1=m +CONFIG_USB_IPHETH=m +CONFIG_USB_SIERRA_NET=m +CONFIG_USB_VL600=m +CONFIG_USB_NET_CH9200=m +CONFIG_USB_NET_AQC111=m +# CONFIG_WLAN_VENDOR_ADMTEK is not set +CONFIG_ATH5K=m +CONFIG_ATH5K_DEBUG=y +CONFIG_ATH9K_HTC=m +CONFIG_CARL9170=m +CONFIG_ATH6KL=m +CONFIG_ATH6KL_SDIO=m +CONFIG_ATH6KL_USB=m +CONFIG_ATH6KL_DEBUG=y +CONFIG_AR5523=m +CONFIG_WIL6210=m +CONFIG_ATH10K=m +CONFIG_ATH10K_PCI=m +CONFIG_ATH10K_SDIO=m +CONFIG_ATH10K_USB=m +CONFIG_ATH10K_DEBUGFS=y +CONFIG_WCN36XX=m +# CONFIG_WLAN_VENDOR_ATMEL is not set +CONFIG_B43=m +CONFIG_B43_SDIO=y +CONFIG_B43LEGACY=m +# CONFIG_B43LEGACY_DEBUG is not set +CONFIG_BRCMSMAC=m +CONFIG_BRCMFMAC=m +CONFIG_BRCMFMAC_USB=y +CONFIG_BRCMFMAC_PCIE=y +# CONFIG_WLAN_VENDOR_CISCO is not set +CONFIG_IWL4965=m +CONFIG_IWL3945=m +CONFIG_IWLEGACY_DEBUG=y +CONFIG_IWLEGACY_DEBUGFS=y +CONFIG_IWLWIFI=m +CONFIG_IWLDVM=m +CONFIG_IWLMVM=m +CONFIG_IWLWIFI_DEBUG=y +CONFIG_IWLWIFI_DEBUGFS=y +CONFIG_HERMES=m +CONFIG_HERMES_PRISM=y +CONFIG_PLX_HERMES=m +CONFIG_NORTEL_HERMES=m +CONFIG_PCI_HERMES=m +CONFIG_PCMCIA_HERMES=m +CONFIG_ORINOCO_USB=m +CONFIG_P54_COMMON=m +CONFIG_P54_USB=m +CONFIG_P54_PCI=m +CONFIG_LIBERTAS=m +CONFIG_LIBERTAS_USB=m +CONFIG_LIBERTAS_CS=m +CONFIG_LIBERTAS_SDIO=m +CONFIG_LIBERTAS_MESH=y +CONFIG_MWIFIEX=m +CONFIG_MWIFIEX_SDIO=m +CONFIG_MWIFIEX_PCIE=m +CONFIG_MWIFIEX_USB=m +CONFIG_MWL8K=m +CONFIG_MT7601U=m +CONFIG_MT76x0U=m +CONFIG_MT76x0E=m +CONFIG_MT76x2E=m +CONFIG_MT76x2U=m +CONFIG_MT7603E=m +CONFIG_MT7615E=m +CONFIG_RT2X00=m +CONFIG_RT2400PCI=m +CONFIG_RT2500PCI=m +CONFIG_RT61PCI=m +CONFIG_RT2800PCI=m +CONFIG_RT2500USB=m +CONFIG_RT73USB=m +CONFIG_RT2800USB=m +CONFIG_RT2800USB_RT3573=y +CONFIG_RT2800USB_RT53XX=y +CONFIG_RT2800USB_RT55XX=y +CONFIG_RT2800USB_UNKNOWN=y +CONFIG_RT2X00_LIB_DEBUGFS=y +CONFIG_RTL8180=m +CONFIG_RTL8187=m +CONFIG_RTL8192CE=m +CONFIG_RTL8192SE=m +CONFIG_RTL8192DE=m +CONFIG_RTL8723AE=m +CONFIG_RTL8723BE=m +CONFIG_RTL8188EE=m +CONFIG_RTL8192EE=m +CONFIG_RTL8821AE=m +CONFIG_RTL8192CU=m +# CONFIG_RTLWIFI_DEBUG is not set +CONFIG_RTL8XXXU=m +CONFIG_RTL8XXXU_UNTESTED=y +CONFIG_RTW88=m +CONFIG_RTW88_8822BE=m +CONFIG_RTW88_8822CE=m +CONFIG_RSI_91X=m +CONFIG_CW1200=m +CONFIG_CW1200_WLAN_SDIO=m +CONFIG_CW1200_WLAN_SPI=m +CONFIG_WL1251=m +CONFIG_WL1251_SPI=m +CONFIG_WL1251_SDIO=m +CONFIG_WL12XX=m +CONFIG_WL18XX=m +CONFIG_WLCORE_SPI=m +CONFIG_WLCORE_SDIO=m +CONFIG_ZD1211RW=m +CONFIG_QTNFMAC_PCIE=m +CONFIG_MAC80211_HWSIM=m +CONFIG_USB_NET_RNDIS_WLAN=m +CONFIG_VIRT_WIFI=m +CONFIG_IEEE802154_FAKELB=m +CONFIG_IEEE802154_AT86RF230=m +CONFIG_IEEE802154_MRF24J40=m +CONFIG_IEEE802154_CC2520=m +CONFIG_IEEE802154_ATUSB=m +CONFIG_IEEE802154_ADF7242=m +CONFIG_IEEE802154_CA8210=m +CONFIG_IEEE802154_MCR20A=m +CONFIG_INPUT_SPARSEKMAP=m +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_JOYDEV=m +CONFIG_INPUT_EVDEV=y +CONFIG_KEYBOARD_QT1050=m +CONFIG_KEYBOARD_QT1070=m +CONFIG_KEYBOARD_GPIO=y +CONFIG_KEYBOARD_SUN4I_LRADC=y +CONFIG_KEYBOARD_TM2_TOUCHKEY=m +CONFIG_MOUSE_PS2_ELANTECH=y +CONFIG_MOUSE_PS2_SENTELIC=y +CONFIG_MOUSE_SERIAL=m +CONFIG_MOUSE_APPLETOUCH=m +CONFIG_MOUSE_BCM5974=m +CONFIG_MOUSE_CYAPA=m +CONFIG_MOUSE_ELAN_I2C=m +CONFIG_MOUSE_ELAN_I2C_SMBUS=y +CONFIG_MOUSE_VSXXXAA=m +CONFIG_MOUSE_SYNAPTICS_I2C=m +CONFIG_MOUSE_SYNAPTICS_USB=m +CONFIG_INPUT_JOYSTICK=y +CONFIG_JOYSTICK_ANALOG=m +CONFIG_JOYSTICK_A3D=m +CONFIG_JOYSTICK_ADI=m +CONFIG_JOYSTICK_COBRA=m +CONFIG_JOYSTICK_GF2K=m +CONFIG_JOYSTICK_GRIP=m +CONFIG_JOYSTICK_GRIP_MP=m +CONFIG_JOYSTICK_GUILLEMOT=m +CONFIG_JOYSTICK_INTERACT=m +CONFIG_JOYSTICK_SIDEWINDER=m +CONFIG_JOYSTICK_TMDC=m +CONFIG_JOYSTICK_IFORCE=m +CONFIG_JOYSTICK_IFORCE_USB=m +CONFIG_JOYSTICK_IFORCE_232=m +CONFIG_JOYSTICK_WARRIOR=m +CONFIG_JOYSTICK_MAGELLAN=m +CONFIG_JOYSTICK_SPACEORB=m +CONFIG_JOYSTICK_SPACEBALL=m +CONFIG_JOYSTICK_STINGER=m +CONFIG_JOYSTICK_TWIDJOY=m +CONFIG_JOYSTICK_ZHENHUA=m +CONFIG_JOYSTICK_JOYDUMP=m +CONFIG_JOYSTICK_XPAD=m +CONFIG_JOYSTICK_XPAD_FF=y +CONFIG_JOYSTICK_XPAD_LEDS=y +CONFIG_JOYSTICK_PSXPAD_SPI=m +CONFIG_JOYSTICK_PSXPAD_SPI_FF=y +CONFIG_JOYSTICK_PXRC=m +CONFIG_INPUT_TABLET=y +CONFIG_TABLET_USB_ACECAD=m +CONFIG_TABLET_USB_AIPTEK=m +CONFIG_TABLET_USB_HANWANG=m +CONFIG_TABLET_USB_KBTAB=m +CONFIG_TABLET_USB_PEGASUS=m +CONFIG_TABLET_SERIAL_WACOM4=m +CONFIG_INPUT_TOUCHSCREEN=y +CONFIG_TOUCHSCREEN_ATMEL_MXT=m +CONFIG_TOUCHSCREEN_AUO_PIXCIR=m +CONFIG_TOUCHSCREEN_DYNAPRO=m +CONFIG_TOUCHSCREEN_EETI=m +CONFIG_TOUCHSCREEN_EGALAX=m +CONFIG_TOUCHSCREEN_EGALAX_SERIAL=m +CONFIG_TOUCHSCREEN_FUJITSU=m +CONFIG_TOUCHSCREEN_ILI210X=m +CONFIG_TOUCHSCREEN_GUNZE=m +CONFIG_TOUCHSCREEN_ELAN=m +CONFIG_TOUCHSCREEN_ELO=m +CONFIG_TOUCHSCREEN_WACOM_W8001=m +CONFIG_TOUCHSCREEN_WACOM_I2C=m +CONFIG_TOUCHSCREEN_MCS5000=m +CONFIG_TOUCHSCREEN_MMS114=m +CONFIG_TOUCHSCREEN_MTOUCH=m +CONFIG_TOUCHSCREEN_INEXIO=m +CONFIG_TOUCHSCREEN_MK712=m +CONFIG_TOUCHSCREEN_PENMOUNT=m +CONFIG_TOUCHSCREEN_EDT_FT5X06=m +CONFIG_TOUCHSCREEN_TOUCHRIGHT=m +CONFIG_TOUCHSCREEN_TOUCHWIN=m +CONFIG_TOUCHSCREEN_PIXCIR=m +CONFIG_TOUCHSCREEN_USB_COMPOSITE=m +CONFIG_TOUCHSCREEN_TOUCHIT213=m +CONFIG_TOUCHSCREEN_TSC_SERIO=m +CONFIG_TOUCHSCREEN_TSC2007=m +CONFIG_TOUCHSCREEN_RM_TS=m +CONFIG_TOUCHSCREEN_SILEAD=m +CONFIG_TOUCHSCREEN_SIS_I2C=m +CONFIG_TOUCHSCREEN_ST1232=m +CONFIG_TOUCHSCREEN_ZET6223=m +CONFIG_TOUCHSCREEN_ZFORCE=m +CONFIG_TOUCHSCREEN_IQS5XX=m +CONFIG_INPUT_MISC=y +CONFIG_INPUT_E3X0_BUTTON=m +CONFIG_INPUT_GPIO_VIBRA=m +CONFIG_INPUT_ATI_REMOTE2=m +CONFIG_INPUT_KEYSPAN_REMOTE=m +CONFIG_INPUT_KXTJ9=m +CONFIG_INPUT_POWERMATE=m +CONFIG_INPUT_YEALINK=m +CONFIG_INPUT_CM109=m +CONFIG_INPUT_UINPUT=m +CONFIG_INPUT_PWM_BEEPER=y +CONFIG_INPUT_GPIO_ROTARY_ENCODER=m +CONFIG_INPUT_CMA3000=m +CONFIG_INPUT_CMA3000_I2C=m +CONFIG_RMI4_I2C=m +CONFIG_RMI4_SPI=m +CONFIG_RMI4_SMB=m +CONFIG_RMI4_F34=y +CONFIG_RMI4_F55=y +CONFIG_LEGACY_PTY_COUNT=16 +# CONFIG_LDISC_AUTOLOAD is not set +CONFIG_SERIAL_8250=y +# CONFIG_SERIAL_8250_DEPRECATED_OPTIONS is not set +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=6 +CONFIG_SERIAL_8250_RUNTIME_UARTS=6 +CONFIG_SERIAL_8250_DW=y +CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_EARLYCON_RISCV_SBI=y +CONFIG_HVC_RISCV_SBI=y +CONFIG_VIRTIO_CONSOLE=m +CONFIG_CARDMAN_4000=m +CONFIG_CARDMAN_4040=m +CONFIG_IPWIRELESS=m +CONFIG_TCG_TIS=y +CONFIG_TCG_TIS_SPI=m +CONFIG_TCG_ATMEL=m +CONFIG_TCG_VTPM_PROXY=m +CONFIG_XILLYBUS=m +CONFIG_XILLYBUS_PCIE=m +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=m +CONFIG_I2C_NFORCE2=m +CONFIG_I2C_NVIDIA_GPU=m +CONFIG_I2C_DESIGNWARE_PCI=m +CONFIG_I2C_MV64XXX=y +CONFIG_I2C_SIMTEC=m +CONFIG_I2C_DIOLAN_U2C=m +CONFIG_I2C_TINY_USB=m +CONFIG_I2C_STUB=m +CONFIG_I2C_SLAVE=y +CONFIG_I2C_SLAVE_EEPROM=m +CONFIG_SPI=y +CONFIG_SPI_SUN6I=y +CONFIG_SPI_SPIDEV=y +CONFIG_PPS_CLIENT_LDISC=m +CONFIG_PPS_CLIENT_GPIO=m +CONFIG_PINCTRL=y +CONFIG_GPIO_SYSFS=y +CONFIG_GPIO_CADENCE=m +CONFIG_GPIO_SYSCON=y +CONFIG_GPIO_PCA953X=m +CONFIG_GPIO_PCF857X=y +CONFIG_GPIO_PCI_IDIO_16=m +CONFIG_W1=m +CONFIG_W1_MASTER_DS2490=m +CONFIG_W1_MASTER_DS2482=m +CONFIG_W1_SLAVE_THERM=m +CONFIG_W1_SLAVE_SMEM=m +CONFIG_W1_SLAVE_DS2405=m +CONFIG_W1_SLAVE_DS2408=m +# CONFIG_W1_SLAVE_DS2408_READBACK is not set +CONFIG_W1_SLAVE_DS2413=m +CONFIG_W1_SLAVE_DS2406=m +CONFIG_W1_SLAVE_DS2423=m +CONFIG_W1_SLAVE_DS2805=m +CONFIG_W1_SLAVE_DS2431=m +CONFIG_W1_SLAVE_DS2433=m +CONFIG_W1_SLAVE_DS2433_CRC=y +CONFIG_W1_SLAVE_DS2438=m +CONFIG_W1_SLAVE_DS2780=m +CONFIG_W1_SLAVE_DS2781=m +CONFIG_W1_SLAVE_DS28E04=m +CONFIG_POWER_RESET=y +CONFIG_POWER_RESET_GPIO=y +CONFIG_POWER_RESET_GPIO_RESTART=y +CONFIG_POWER_RESET_RESTART=y +CONFIG_POWER_RESET_SYSCON=y +CONFIG_POWER_RESET_SYSCON_POWEROFF=y +CONFIG_SYSCON_REBOOT_MODE=y +CONFIG_CHARGER_LT3651=m +CONFIG_CHARGER_SMB347=m +CONFIG_SENSORS_AD7314=m +CONFIG_SENSORS_AD7414=m +CONFIG_SENSORS_AD7418=m +CONFIG_SENSORS_ADM1021=m +CONFIG_SENSORS_ADM1025=m +CONFIG_SENSORS_ADM1026=m +CONFIG_SENSORS_ADM1029=m +CONFIG_SENSORS_ADM1031=m +CONFIG_SENSORS_ADM9240=m +CONFIG_SENSORS_ADT7310=m +CONFIG_SENSORS_ADT7410=m +CONFIG_SENSORS_ADT7411=m +CONFIG_SENSORS_ADT7462=m +CONFIG_SENSORS_ADT7470=m +CONFIG_SENSORS_ADT7475=m +CONFIG_SENSORS_ASC7621=m +CONFIG_SENSORS_ASPEED=m +CONFIG_SENSORS_ATXP1=m +CONFIG_SENSORS_DS620=m +CONFIG_SENSORS_DS1621=m +CONFIG_SENSORS_F71805F=m +CONFIG_SENSORS_F71882FG=m +CONFIG_SENSORS_F75375S=m +CONFIG_SENSORS_FTSTEUTATES=m +CONFIG_SENSORS_GL518SM=m +CONFIG_SENSORS_GL520SM=m +CONFIG_SENSORS_G760A=m +CONFIG_SENSORS_G762=m +CONFIG_SENSORS_IT87=m +CONFIG_SENSORS_JC42=m +CONFIG_SENSORS_POWR1220=m +CONFIG_SENSORS_LINEAGE=m +CONFIG_SENSORS_LTC2945=m +CONFIG_SENSORS_LTC2990=m +CONFIG_SENSORS_LTC4151=m +CONFIG_SENSORS_LTC4215=m +CONFIG_SENSORS_LTC4222=m +CONFIG_SENSORS_LTC4245=m +CONFIG_SENSORS_LTC4260=m +CONFIG_SENSORS_LTC4261=m +CONFIG_SENSORS_MAX1111=m +CONFIG_SENSORS_MAX16065=m +CONFIG_SENSORS_MAX1619=m +CONFIG_SENSORS_MAX1668=m +CONFIG_SENSORS_MAX197=m +CONFIG_SENSORS_MAX31722=m +CONFIG_SENSORS_MAX6639=m +CONFIG_SENSORS_MAX6642=m +CONFIG_SENSORS_MAX6650=m +CONFIG_SENSORS_MAX6697=m +CONFIG_SENSORS_MAX31790=m +CONFIG_SENSORS_MCP3021=m +CONFIG_SENSORS_TC654=m +CONFIG_SENSORS_ADCXX=m +CONFIG_SENSORS_LM63=m +CONFIG_SENSORS_LM70=m +CONFIG_SENSORS_LM73=m +CONFIG_SENSORS_LM75=m +CONFIG_SENSORS_LM77=m +CONFIG_SENSORS_LM78=m +CONFIG_SENSORS_LM80=m +CONFIG_SENSORS_LM83=m +CONFIG_SENSORS_LM85=m +CONFIG_SENSORS_LM87=m +CONFIG_SENSORS_LM90=m +CONFIG_SENSORS_LM92=m +CONFIG_SENSORS_LM93=m +CONFIG_SENSORS_LM95234=m +CONFIG_SENSORS_LM95241=m +CONFIG_SENSORS_LM95245=m +CONFIG_SENSORS_PC87360=m +CONFIG_SENSORS_PC87427=m +CONFIG_SENSORS_NTC_THERMISTOR=m +CONFIG_SENSORS_NCT6683=m +CONFIG_SENSORS_NCT6775=m +CONFIG_SENSORS_NCT7802=m +CONFIG_SENSORS_NCT7904=m +CONFIG_SENSORS_NPCM7XX=m +CONFIG_SENSORS_PCF8591=m +CONFIG_PMBUS=m +CONFIG_SENSORS_ADM1275=m +CONFIG_SENSORS_LM25066=m +CONFIG_SENSORS_LTC2978=m +CONFIG_SENSORS_LTC3815=m +CONFIG_SENSORS_MAX16064=m +CONFIG_SENSORS_MAX20751=m +CONFIG_SENSORS_MAX34440=m +CONFIG_SENSORS_MAX8688=m +CONFIG_SENSORS_TPS40422=m +CONFIG_SENSORS_TPS53679=m +CONFIG_SENSORS_UCD9000=m +CONFIG_SENSORS_UCD9200=m +CONFIG_SENSORS_ZL6100=m +CONFIG_SENSORS_PWM_FAN=m +CONFIG_SENSORS_SHT15=m +CONFIG_SENSORS_SHT21=m +CONFIG_SENSORS_SHT3x=m +CONFIG_SENSORS_SHTC1=m +CONFIG_SENSORS_SIS5595=m +CONFIG_SENSORS_DME1737=m +CONFIG_SENSORS_EMC1403=m +CONFIG_SENSORS_EMC6W201=m +CONFIG_SENSORS_SMSC47M1=m +CONFIG_SENSORS_SMSC47M192=m +CONFIG_SENSORS_SMSC47B397=m +CONFIG_SENSORS_SCH5627=m +CONFIG_SENSORS_SCH5636=m +CONFIG_SENSORS_ADC128D818=m +CONFIG_SENSORS_ADS7828=m +CONFIG_SENSORS_ADS7871=m +CONFIG_SENSORS_AMC6821=m +CONFIG_SENSORS_INA209=m +CONFIG_SENSORS_INA2XX=m +CONFIG_SENSORS_INA3221=m +CONFIG_SENSORS_TC74=m +CONFIG_SENSORS_THMC50=m +CONFIG_SENSORS_TMP102=m +CONFIG_SENSORS_TMP103=m +CONFIG_SENSORS_TMP108=m +CONFIG_SENSORS_TMP401=m +CONFIG_SENSORS_TMP421=m +CONFIG_SENSORS_VIA686A=m +CONFIG_SENSORS_VT1211=m +CONFIG_SENSORS_VT8231=m +CONFIG_SENSORS_W83773G=m +CONFIG_SENSORS_W83781D=m +CONFIG_SENSORS_W83791D=m +CONFIG_SENSORS_W83792D=m +CONFIG_SENSORS_W83793=m +CONFIG_SENSORS_W83795=m +CONFIG_SENSORS_W83L785TS=m +CONFIG_SENSORS_W83L786NG=m +CONFIG_SENSORS_W83627HF=m +CONFIG_SENSORS_W83627EHF=m +CONFIG_THERMAL_STATISTICS=y +CONFIG_THERMAL_WRITABLE_TRIPS=y +CONFIG_THERMAL_GOV_FAIR_SHARE=y +CONFIG_THERMAL_GOV_BANG_BANG=y +CONFIG_THERMAL_GOV_USER_SPACE=y +CONFIG_CPU_THERMAL=y +CONFIG_THERMAL_EMULATION=y +CONFIG_SUN8I_THERMAL=y +CONFIG_WATCHDOG=y +CONFIG_WATCHDOG_SYSFS=y +CONFIG_SUNXI_WATCHDOG=y +CONFIG_MFD_BD9571MWV=m +CONFIG_MFD_MAX77650=m +CONFIG_MFD_VIPERBOARD=m +CONFIG_MFD_SM501=m +CONFIG_MFD_SM501_GPIO=y +CONFIG_MFD_WL1273_CORE=m +CONFIG_MFD_VX855=m +CONFIG_REGULATOR=y +CONFIG_REGULATOR_FIXED_VOLTAGE=y +CONFIG_REGULATOR_PWM=y +CONFIG_RC_CORE=y +CONFIG_RC_MAP=m +CONFIG_LIRC=y +CONFIG_BPF_LIRC_MODE2=y +CONFIG_RC_DECODERS=y +CONFIG_IR_NEC_DECODER=m +CONFIG_IR_RC5_DECODER=m +CONFIG_IR_RC6_DECODER=m +CONFIG_IR_JVC_DECODER=m +CONFIG_IR_SONY_DECODER=m +CONFIG_IR_SANYO_DECODER=m +CONFIG_IR_SHARP_DECODER=m +CONFIG_IR_MCE_KBD_DECODER=m +CONFIG_IR_XMP_DECODER=m +CONFIG_IR_IMON_DECODER=m +CONFIG_IR_RCMM_DECODER=m +CONFIG_RC_DEVICES=y +CONFIG_RC_ATI_REMOTE=m +CONFIG_IR_HIX5HD2=m +CONFIG_IR_IMON=m +CONFIG_IR_IMON_RAW=m +CONFIG_IR_MCEUSB=m +CONFIG_IR_REDRAT3=m +CONFIG_IR_SPI=m +CONFIG_IR_STREAMZAP=m +CONFIG_IR_IGORPLUGUSB=m +CONFIG_IR_IGUANA=m +CONFIG_IR_TTUSBIR=m +CONFIG_RC_LOOPBACK=m +CONFIG_IR_GPIO_CIR=m +CONFIG_IR_GPIO_TX=m +CONFIG_IR_PWM_TX=m +CONFIG_MEDIA_CEC_SUPPORT=y +CONFIG_MEDIA_SUPPORT=y +CONFIG_MEDIA_SUPPORT_FILTER=y +# CONFIG_MEDIA_SUBDRV_AUTOSELECT is not set +CONFIG_MEDIA_CAMERA_SUPPORT=y +CONFIG_MEDIA_ANALOG_TV_SUPPORT=y +CONFIG_MEDIA_DIGITAL_TV_SUPPORT=y +CONFIG_MEDIA_RADIO_SUPPORT=y +CONFIG_MEDIA_PLATFORM_SUPPORT=y +CONFIG_MEDIA_USB_SUPPORT=y +CONFIG_USB_VIDEO_CLASS=m +# CONFIG_USB_GSPCA is not set +CONFIG_FB=y +CONFIG_BACKLIGHT_CLASS_DEVICE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY=y +CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y +CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER=y +CONFIG_LOGO=y +# CONFIG_LOGO_LINUX_MONO is not set +# CONFIG_LOGO_LINUX_VGA16 is not set +CONFIG_SOUND=y +CONFIG_SND=y +CONFIG_SND_HRTIMER=m +CONFIG_SND_DYNAMIC_MINORS=y +# CONFIG_SND_SUPPORT_OLD_API is not set +CONFIG_SND_SEQUENCER=m +CONFIG_SND_SEQ_DUMMY=m +CONFIG_SND_DUMMY=m +CONFIG_SND_ALOOP=m +CONFIG_SND_VIRMIDI=m +CONFIG_SND_MTPAV=m +CONFIG_SND_SERIAL_U16550=m +CONFIG_SND_MPU401=m +CONFIG_SND_AC97_POWER_SAVE=y +CONFIG_SND_AD1889=m +CONFIG_SND_ATIIXP=m +CONFIG_SND_ATIIXP_MODEM=m +CONFIG_SND_AU8810=m +CONFIG_SND_AU8820=m +CONFIG_SND_AU8830=m +CONFIG_SND_BT87X=m +CONFIG_SND_CA0106=m +CONFIG_SND_CMIPCI=m +CONFIG_SND_OXYGEN=m +CONFIG_SND_CS4281=m +CONFIG_SND_CS46XX=m +CONFIG_SND_CTXFI=m +CONFIG_SND_DARLA20=m +CONFIG_SND_GINA20=m +CONFIG_SND_LAYLA20=m +CONFIG_SND_DARLA24=m +CONFIG_SND_GINA24=m +CONFIG_SND_LAYLA24=m +CONFIG_SND_MONA=m +CONFIG_SND_MIA=m +CONFIG_SND_ECHO3G=m +CONFIG_SND_INDIGO=m +CONFIG_SND_INDIGOIO=m +CONFIG_SND_INDIGODJ=m +CONFIG_SND_INDIGOIOX=m +CONFIG_SND_INDIGODJX=m +CONFIG_SND_ENS1370=m +CONFIG_SND_ENS1371=m +CONFIG_SND_FM801=m +CONFIG_SND_HDSP=m +CONFIG_SND_HDSPM=m +CONFIG_SND_ICE1724=m +CONFIG_SND_KORG1212=m +CONFIG_SND_LOLA=m +CONFIG_SND_LX6464ES=m +CONFIG_SND_MIXART=m +CONFIG_SND_NM256=m +CONFIG_SND_PCXHR=m +CONFIG_SND_RIPTIDE=m +CONFIG_SND_RME32=m +CONFIG_SND_RME96=m +CONFIG_SND_RME9652=m +CONFIG_SND_VIRTUOSO=m +CONFIG_SND_VX222=m +CONFIG_SND_YMFPCI=m +CONFIG_SND_HDA_PREALLOC_SIZE=4096 +# CONFIG_SND_SPI is not set +CONFIG_SND_USB_AUDIO=m +CONFIG_SND_USB_UA101=m +CONFIG_SND_USB_CAIAQ=m +CONFIG_SND_USB_CAIAQ_INPUT=y +CONFIG_SND_USB_6FIRE=m +CONFIG_SND_USB_HIFACE=m +CONFIG_SND_BCD2000=m +CONFIG_SND_USB_POD=m +CONFIG_SND_USB_PODHD=m +CONFIG_SND_USB_TONEPORT=m +CONFIG_SND_USB_VARIAX=m +CONFIG_SND_DICE=m +CONFIG_SND_OXFW=m +CONFIG_SND_ISIGHT=m +CONFIG_SND_FIREWORKS=m +CONFIG_SND_BEBOB=m +CONFIG_SND_FIREWIRE_DIGI00X=m +CONFIG_SND_FIREWIRE_TASCAM=m +CONFIG_SND_FIREWIRE_MOTU=m +CONFIG_SND_FIREFACE=m +# CONFIG_SND_PCMCIA is not set +CONFIG_SND_SOC=y +CONFIG_SND_SOC_AMD_ACP=m +CONFIG_SND_SOC_AMD_CZ_RT5645_MACH=m +CONFIG_SND_DESIGNWARE_I2S=m +CONFIG_SND_DESIGNWARE_PCM=y +CONFIG_SND_I2S_HI6210_I2S=m +CONFIG_SND_SOC_SOF_TOPLEVEL=y +CONFIG_SND_SOC_SOF_PCI=m +CONFIG_SND_SUN20I_CODEC=y +CONFIG_SND_SUN4I_I2S=y +CONFIG_SND_SUN4I_SPDIF=y +CONFIG_SND_SOC_ADAU1761_I2C=m +CONFIG_SND_SOC_ADAU1761_SPI=m +CONFIG_SND_SOC_AK5558=m +CONFIG_SND_SOC_BD28623=m +CONFIG_SND_SOC_CS35L34=m +CONFIG_SND_SOC_CS35L35=m +CONFIG_SND_SOC_CS35L36=m +CONFIG_SND_SOC_CS42L42=m +CONFIG_SND_SOC_CS43130=m +CONFIG_SND_SOC_CX2072X=m +CONFIG_SND_SOC_ES7134=m +CONFIG_SND_SOC_MAX98088=m +CONFIG_SND_SOC_MAX9867=m +CONFIG_SND_SOC_MAX98927=m +CONFIG_SND_SOC_PCM1789_I2C=m +CONFIG_SND_SOC_PCM186X_I2C=m +CONFIG_SND_SOC_PCM186X_SPI=m +CONFIG_SND_SOC_PCM3060_I2C=m +CONFIG_SND_SOC_PCM3060_SPI=m +CONFIG_SND_SOC_SIMPLE_AMPLIFIER=m +CONFIG_SND_SOC_SPDIF=m +CONFIG_SND_SOC_TAS6424=m +CONFIG_SND_SOC_TDA7419=m +CONFIG_SND_SOC_TLV320AIC32X4_I2C=m +CONFIG_SND_SOC_TLV320AIC32X4_SPI=m +CONFIG_SND_SOC_TSCS42XX=m +CONFIG_SND_SOC_WM8524=m +CONFIG_SND_SOC_MAX9759=m +CONFIG_SND_SOC_NAU8824=m +CONFIG_SND_SIMPLE_CARD=m +CONFIG_HID_BATTERY_STRENGTH=y +CONFIG_HIDRAW=y +CONFIG_UHID=m +CONFIG_HID_A4TECH=m +CONFIG_HID_ACCUTOUCH=m +CONFIG_HID_ACRUX=m +CONFIG_HID_ACRUX_FF=y +CONFIG_HID_APPLE=m +CONFIG_HID_APPLEIR=m +CONFIG_HID_AUREAL=m +CONFIG_HID_BELKIN=m +CONFIG_HID_BETOP_FF=m +CONFIG_HID_BIGBEN_FF=m +CONFIG_HID_CHERRY=m +CONFIG_HID_CHICONY=m +CONFIG_HID_CORSAIR=m +CONFIG_HID_COUGAR=m +CONFIG_HID_MACALLY=m +CONFIG_HID_PRODIKEYS=m +CONFIG_HID_CMEDIA=m +CONFIG_HID_CP2112=m +CONFIG_HID_CYPRESS=m +CONFIG_HID_DRAGONRISE=m +CONFIG_DRAGONRISE_FF=y +CONFIG_HID_EMS_FF=m +CONFIG_HID_ELAN=m +CONFIG_HID_ELECOM=m +CONFIG_HID_ELO=m +CONFIG_HID_EZKEY=m +CONFIG_HID_GEMBIRD=m +CONFIG_HID_GFRM=m +CONFIG_HID_HOLTEK=m +CONFIG_HOLTEK_FF=y +CONFIG_HID_GT683R=m +CONFIG_HID_KEYTOUCH=m +CONFIG_HID_KYE=m +CONFIG_HID_UCLOGIC=m +CONFIG_HID_WALTOP=m +CONFIG_HID_VIEWSONIC=m +CONFIG_HID_GYRATION=m +CONFIG_HID_ICADE=m +CONFIG_HID_ITE=m +CONFIG_HID_JABRA=m +CONFIG_HID_TWINHAN=m +CONFIG_HID_KENSINGTON=m +CONFIG_HID_LCPOWER=m +CONFIG_HID_LENOVO=m +CONFIG_HID_LOGITECH=m +CONFIG_HID_LOGITECH_DJ=m +CONFIG_LOGITECH_FF=y +CONFIG_LOGIRUMBLEPAD2_FF=y +CONFIG_LOGIG940_FF=y +CONFIG_HID_MAGICMOUSE=y +CONFIG_HID_MALTRON=m +CONFIG_HID_MAYFLASH=m +CONFIG_HID_MICROSOFT=m +CONFIG_HID_MONTEREY=m +CONFIG_HID_MULTITOUCH=m +CONFIG_HID_NTI=m +CONFIG_HID_NTRIG=m +CONFIG_HID_ORTEK=m +CONFIG_HID_PANTHERLORD=m +CONFIG_PANTHERLORD_FF=y +CONFIG_HID_PENMOUNT=m +CONFIG_HID_PETALYNX=m +CONFIG_HID_PICOLCD=m +CONFIG_HID_PICOLCD_FB=y +CONFIG_HID_PICOLCD_BACKLIGHT=y +CONFIG_HID_PICOLCD_LEDS=y +CONFIG_HID_PICOLCD_CIR=y +CONFIG_HID_PLANTRONICS=m +CONFIG_HID_PRIMAX=m +CONFIG_HID_RETRODE=m +CONFIG_HID_ROCCAT=m +CONFIG_HID_SAITEK=m +CONFIG_HID_SAMSUNG=m +CONFIG_HID_SONY=m +CONFIG_SONY_FF=y +CONFIG_HID_SPEEDLINK=m +CONFIG_HID_STEAM=m +CONFIG_HID_STEELSERIES=m +CONFIG_HID_SUNPLUS=m +CONFIG_HID_RMI=m +CONFIG_HID_GREENASIA=m +CONFIG_GREENASIA_FF=y +CONFIG_HID_SMARTJOYPLUS=m +CONFIG_SMARTJOYPLUS_FF=y +CONFIG_HID_TIVO=m +CONFIG_HID_TOPSEED=m +CONFIG_HID_THINGM=m +CONFIG_HID_THRUSTMASTER=m +CONFIG_THRUSTMASTER_FF=y +CONFIG_HID_UDRAW_PS3=m +CONFIG_HID_WACOM=m +CONFIG_HID_WIIMOTE=m +CONFIG_HID_XINMO=m +CONFIG_HID_ZEROPLUS=m +CONFIG_ZEROPLUS_FF=y +CONFIG_HID_ZYDACRON=m +CONFIG_HID_SENSOR_HUB=m +CONFIG_HID_ALPS=m +CONFIG_HID_PID=y +CONFIG_USB_HIDDEV=y +CONFIG_USB_LED_TRIG=y +CONFIG_USB_ULPI_BUS=m +CONFIG_USB=y +CONFIG_USB_ANNOUNCE_NEW_DEVICES=y +CONFIG_USB_DYNAMIC_MINORS=y +CONFIG_USB_OTG=y +CONFIG_USB_LEDS_TRIGGER_USBPORT=m +CONFIG_USB_MON=m +CONFIG_USB_XHCI_HCD=m +CONFIG_USB_XHCI_DBGCAP=y +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_EHCI_HCD_PLATFORM=y +CONFIG_USB_OHCI_HCD=y +CONFIG_USB_OHCI_HCD_PLATFORM=y +CONFIG_USB_UHCI_HCD=m +CONFIG_USB_SL811_HCD=m +CONFIG_USB_SL811_HCD_ISO=y +CONFIG_USB_PRINTER=m +CONFIG_USB_TMC=m +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_REALTEK=m +CONFIG_USB_STORAGE_DATAFAB=m +CONFIG_USB_STORAGE_FREECOM=m +CONFIG_USB_STORAGE_ISD200=m +CONFIG_USB_STORAGE_USBAT=m +CONFIG_USB_STORAGE_SDDR09=m +CONFIG_USB_STORAGE_SDDR55=m +CONFIG_USB_STORAGE_JUMPSHOT=m +CONFIG_USB_STORAGE_ALAUDA=m +CONFIG_USB_STORAGE_ONETOUCH=m +CONFIG_USB_STORAGE_KARMA=m +CONFIG_USB_STORAGE_CYPRESS_ATACB=m +CONFIG_USB_STORAGE_ENE_UB6250=m +CONFIG_USB_UAS=m +CONFIG_USB_MDC800=m +CONFIG_USB_MICROTEK=m +CONFIG_USBIP_CORE=m +CONFIG_USBIP_VHCI_HCD=m +CONFIG_USBIP_HOST=m +CONFIG_USB_MUSB_HDRC=y +CONFIG_USB_MUSB_SUNXI=m +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_SIMPLE=m +CONFIG_USB_SERIAL_AIRCABLE=m +CONFIG_USB_SERIAL_ARK3116=m +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_CH341=m +CONFIG_USB_SERIAL_WHITEHEAT=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_CP210X=m +CONFIG_USB_SERIAL_CYPRESS_M8=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_F8153X=m +CONFIG_USB_SERIAL_GARMIN=m +CONFIG_USB_SERIAL_IPW=m +CONFIG_USB_SERIAL_IUU=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_MOS7720=m +CONFIG_USB_SERIAL_MOS7840=m +CONFIG_USB_SERIAL_NAVMAN=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_OTI6858=m +CONFIG_USB_SERIAL_QCAUX=m +CONFIG_USB_SERIAL_QUALCOMM=m +CONFIG_USB_SERIAL_SPCP8X5=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_SIERRAWIRELESS=m +CONFIG_USB_SERIAL_SYMBOL=m +CONFIG_USB_SERIAL_TI=m +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_OPTION=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_SERIAL_OPTICON=m +CONFIG_USB_SERIAL_XSENS_MT=m +CONFIG_USB_SERIAL_SSU100=m +CONFIG_USB_SERIAL_QT2=m +CONFIG_USB_SERIAL_UPD78F0730=m +CONFIG_USB_SERIAL_DEBUG=m +CONFIG_USB_EMI62=m +CONFIG_USB_EMI26=m +CONFIG_USB_ADUTUX=m +CONFIG_USB_SEVSEG=m +CONFIG_USB_LEGOTOWER=m +CONFIG_USB_LCD=m +CONFIG_USB_IDMOUSE=m +CONFIG_USB_FTDI_ELAN=m +CONFIG_USB_APPLEDISPLAY=m +CONFIG_USB_SISUSBVGA=m +CONFIG_USB_LD=m +CONFIG_USB_TRANCEVIBRATOR=m +CONFIG_USB_IOWARRIOR=m +CONFIG_USB_ISIGHTFW=m +CONFIG_USB_YUREX=m +CONFIG_USB_HUB_USB251XB=m +CONFIG_USB_HSIC_USB3503=m +CONFIG_USB_HSIC_USB4604=m +CONFIG_USB_ATM=m +CONFIG_USB_SPEEDTOUCH=m +CONFIG_USB_CXACRU=m +CONFIG_USB_UEAGLEATM=m +CONFIG_USB_XUSBATM=m +CONFIG_NOP_USB_XCEIV=m +CONFIG_USB_GADGET=y +CONFIG_USB_CONFIGFS=y +CONFIG_USB_CONFIGFS_SERIAL=y +CONFIG_USB_CONFIGFS_MASS_STORAGE=y +CONFIG_USB_CONFIGFS_F_FS=y +CONFIG_USB_CONFIGFS_F_UAC1=y +CONFIG_USB_CONFIGFS_F_HID=y +CONFIG_USB_ETH=y +# CONFIG_USB_ETH_RNDIS is not set +CONFIG_USB_ETH_EEM=y +CONFIG_USB_ROLE_SWITCH=y +CONFIG_MMC=y +CONFIG_PWRSEQ_SD8787=m +CONFIG_PWRSEQ_SIMPLE=m +CONFIG_SDIO_UART=m +CONFIG_MMC_SDHCI=m +CONFIG_MMC_SDHCI_PCI=m +CONFIG_MMC_SDHCI_PLTFM=m +CONFIG_MMC_SDHCI_CADENCE=m +CONFIG_MMC_ALCOR=m +CONFIG_MMC_TIFM_SD=m +CONFIG_MMC_SPI=y +CONFIG_MMC_SDRICOH_CS=m +CONFIG_MMC_CB710=m +CONFIG_MMC_VIA_SDMMC=m +CONFIG_MMC_VUB300=m +CONFIG_MMC_USHC=m +CONFIG_MMC_REALTEK_PCI=m +CONFIG_MMC_REALTEK_USB=m +CONFIG_MMC_SUNXI=y +CONFIG_MMC_SDHCI_XENON=m +CONFIG_MEMSTICK=m +CONFIG_MSPRO_BLOCK=m +CONFIG_MEMSTICK_TIFM_MS=m +CONFIG_MEMSTICK_JMICRON_38X=m +CONFIG_MEMSTICK_R592=m +CONFIG_MEMSTICK_REALTEK_PCI=m +CONFIG_MEMSTICK_REALTEK_USB=m +CONFIG_LEDS_CLASS=y +CONFIG_LEDS_CLASS_FLASH=m +CONFIG_LEDS_CLASS_MULTICOLOR=y +CONFIG_LEDS_BRIGHTNESS_HW_CHANGED=y +CONFIG_LEDS_AN30259A=m +CONFIG_LEDS_AS3645A=m +CONFIG_LEDS_CR0014114=m +CONFIG_LEDS_LM3530=m +CONFIG_LEDS_LM3532=m +CONFIG_LEDS_LM3692X=m +CONFIG_LEDS_LM3601X=m +CONFIG_LEDS_PCA9532=m +CONFIG_LEDS_PCA9532_GPIO=y +CONFIG_LEDS_GPIO=m +CONFIG_LEDS_LP3944=m +CONFIG_LEDS_LP3952=m +CONFIG_LEDS_PWM=y +CONFIG_LEDS_LT3593=m +CONFIG_LEDS_MAX77650=m +CONFIG_LEDS_IS31FL32XX=m +CONFIG_LEDS_BLINKM=m +CONFIG_LEDS_SYSCON=y +CONFIG_LEDS_MLXREG=m +CONFIG_LEDS_USER=m +CONFIG_LEDS_SUN20I=y +CONFIG_LEDS_TRIGGER_TIMER=y +CONFIG_LEDS_TRIGGER_ONESHOT=y +CONFIG_LEDS_TRIGGER_DISK=y +CONFIG_LEDS_TRIGGER_MTD=y +CONFIG_LEDS_TRIGGER_HEARTBEAT=y +CONFIG_LEDS_TRIGGER_BACKLIGHT=y +CONFIG_LEDS_TRIGGER_CPU=y +CONFIG_LEDS_TRIGGER_ACTIVITY=y +CONFIG_LEDS_TRIGGER_GPIO=y +CONFIG_LEDS_TRIGGER_DEFAULT_ON=y +CONFIG_LEDS_TRIGGER_TRANSIENT=y +CONFIG_LEDS_TRIGGER_CAMERA=y +CONFIG_LEDS_TRIGGER_PANIC=y +CONFIG_LEDS_TRIGGER_NETDEV=y +CONFIG_LEDS_TRIGGER_PATTERN=y +CONFIG_LEDS_TRIGGER_AUDIO=y +CONFIG_ACCESSIBILITY=y +CONFIG_A11Y_BRAILLE_CONSOLE=y +CONFIG_INFINIBAND=m +CONFIG_INFINIBAND_USER_MAD=m +CONFIG_INFINIBAND_USER_ACCESS=m +CONFIG_INFINIBAND_MTHCA=m +CONFIG_INFINIBAND_CXGB4=m +CONFIG_INFINIBAND_EFA=m +CONFIG_MLX4_INFINIBAND=m +CONFIG_MLX5_INFINIBAND=m +CONFIG_INFINIBAND_OCRDMA=m +CONFIG_INFINIBAND_QEDR=m +CONFIG_RDMA_RXE=m +CONFIG_INFINIBAND_IPOIB=m +CONFIG_INFINIBAND_IPOIB_CM=y +CONFIG_INFINIBAND_IPOIB_DEBUG_DATA=y +CONFIG_INFINIBAND_SRP=m +CONFIG_INFINIBAND_SRPT=m +CONFIG_INFINIBAND_ISER=m +CONFIG_INFINIBAND_ISERT=m +CONFIG_RTC_CLASS=y +CONFIG_RTC_DRV_ABEOZ9=m +CONFIG_RTC_DRV_ABX80X=m +CONFIG_RTC_DRV_DS1307=m +CONFIG_RTC_DRV_DS1374=m +CONFIG_RTC_DRV_DS1374_WDT=y +CONFIG_RTC_DRV_DS1672=m +CONFIG_RTC_DRV_MAX6900=m +CONFIG_RTC_DRV_RS5C372=m +CONFIG_RTC_DRV_ISL1208=m +CONFIG_RTC_DRV_ISL12022=m +CONFIG_RTC_DRV_ISL12026=m +CONFIG_RTC_DRV_X1205=m +CONFIG_RTC_DRV_PCF8523=m +CONFIG_RTC_DRV_PCF85063=m +CONFIG_RTC_DRV_PCF8563=m +CONFIG_RTC_DRV_PCF8583=m +CONFIG_RTC_DRV_M41T80=m +CONFIG_RTC_DRV_M41T80_WDT=y +CONFIG_RTC_DRV_BQ32K=m +CONFIG_RTC_DRV_FM3130=m +CONFIG_RTC_DRV_RX8010=m +CONFIG_RTC_DRV_RX8581=m +CONFIG_RTC_DRV_RX8025=m +CONFIG_RTC_DRV_EM3027=m +CONFIG_RTC_DRV_RV3028=m +CONFIG_RTC_DRV_SD3078=m +CONFIG_RTC_DRV_M41T93=m +CONFIG_RTC_DRV_M41T94=m +CONFIG_RTC_DRV_DS1305=m +CONFIG_RTC_DRV_DS1343=m +CONFIG_RTC_DRV_DS1347=m +CONFIG_RTC_DRV_DS1390=m +CONFIG_RTC_DRV_MAX6916=m +CONFIG_RTC_DRV_R9701=m +CONFIG_RTC_DRV_RX4581=m +CONFIG_RTC_DRV_RS5C348=m +CONFIG_RTC_DRV_MAX6902=m +CONFIG_RTC_DRV_PCF2123=m +CONFIG_RTC_DRV_MCP795=m +CONFIG_RTC_DRV_DS3232=m +# CONFIG_RTC_DRV_DS3232_HWMON is not set +CONFIG_RTC_DRV_PCF2127=m +CONFIG_RTC_DRV_RV3029C2=m +CONFIG_RTC_DRV_DS1286=m +CONFIG_RTC_DRV_DS1511=m +CONFIG_RTC_DRV_DS1553=m +CONFIG_RTC_DRV_DS1685_FAMILY=m +CONFIG_RTC_DRV_DS1742=m +CONFIG_RTC_DRV_DS2404=m +CONFIG_RTC_DRV_STK17TA8=m +CONFIG_RTC_DRV_M48T35=m +CONFIG_RTC_DRV_M48T59=m +CONFIG_RTC_DRV_MSM6242=m +CONFIG_RTC_DRV_BQ4802=m +CONFIG_RTC_DRV_RP5C01=m +CONFIG_RTC_DRV_V3020=m +CONFIG_RTC_DRV_R7301=m +CONFIG_DMADEVICES=y +CONFIG_DMA_SUN6I=y +CONFIG_SYNC_FILE=y +CONFIG_UDMABUF=y +CONFIG_AUXDISPLAY=y +CONFIG_HD44780=m +CONFIG_HT16K33=m +CONFIG_UIO_CIF=m +CONFIG_UIO_AEC=m +CONFIG_UIO_SERCOS3=m +CONFIG_UIO_PCI_GENERIC=m +CONFIG_VIRTIO_PCI=y +CONFIG_VIRTIO_BALLOON=m +CONFIG_VIRTIO_INPUT=m +CONFIG_VIRTIO_MMIO=y +CONFIG_STAGING=y +CONFIG_RTLLIB=m +CONFIG_RTL8192E=m +CONFIG_RTL8723BS=m +CONFIG_R8712U=m +CONFIG_STAGING_MEDIA=y +CONFIG_QLGE=m +CONFIG_COMMON_CLK_SI544=m +CONFIG_COMMON_CLK_PWM=y +CONFIG_SUN8I_DE2_CCU=y +CONFIG_XILINX_VCU=m +CONFIG_HWSPINLOCK=y +CONFIG_HWSPINLOCK_SUN6I=y +CONFIG_MAILBOX=y +CONFIG_SUN50I_IOMMU=y +CONFIG_REMOTEPROC=y +CONFIG_REMOTEPROC_CDEV=y +CONFIG_SUN8I_DSP_REMOTEPROC=y +CONFIG_RPMSG_CHAR=m +CONFIG_RPMSG_VIRTIO=m +CONFIG_SOUNDWIRE=y +CONFIG_PM_DEVFREQ=y +CONFIG_DEVFREQ_GOV_SIMPLE_ONDEMAND=m +CONFIG_PWM=y +CONFIG_PWM_SUN8I_V536=y +CONFIG_PHY_SUN4I_USB=y +CONFIG_POWERCAP=y +CONFIG_ANDROID=y +CONFIG_NVMEM_SUNXI_SID=y +CONFIG_FPGA=m +CONFIG_ALTERA_PR_IP_CORE=m +CONFIG_ALTERA_PR_IP_CORE_PLAT=m +CONFIG_FPGA_MGR_ALTERA_PS_SPI=m +CONFIG_FPGA_MGR_ALTERA_CVP=m +CONFIG_FPGA_MGR_XILINX_SPI=m +CONFIG_FPGA_MGR_ICE40_SPI=m +CONFIG_FPGA_MGR_MACHXO2_SPI=m +CONFIG_XILINX_PR_DECOUPLER=m +CONFIG_OF_FPGA_REGION=m +CONFIG_FPGA_DFL=m +CONFIG_FPGA_DFL_AFU=m +CONFIG_FPGA_DFL_PCI=m +CONFIG_FSI=m +CONFIG_FSI_MASTER_GPIO=m +CONFIG_FSI_MASTER_HUB=m +CONFIG_FSI_SCOM=m +CONFIG_VALIDATE_FS_PARSER=y +CONFIG_EXT4_FS=y +CONFIG_EXT4_FS_POSIX_ACL=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_REISERFS_FS=m +CONFIG_REISERFS_PROC_INFO=y +CONFIG_REISERFS_FS_XATTR=y +CONFIG_REISERFS_FS_POSIX_ACL=y +CONFIG_REISERFS_FS_SECURITY=y +CONFIG_JFS_FS=m +CONFIG_JFS_POSIX_ACL=y +CONFIG_JFS_SECURITY=y +CONFIG_XFS_FS=y +CONFIG_XFS_QUOTA=y +CONFIG_XFS_POSIX_ACL=y +CONFIG_XFS_ONLINE_SCRUB=y +CONFIG_GFS2_FS=m +CONFIG_GFS2_FS_LOCKING_DLM=y +CONFIG_OCFS2_FS=m +# CONFIG_OCFS2_FS_STATS is not set +# CONFIG_OCFS2_DEBUG_MASKLOG is not set +CONFIG_BTRFS_FS=m +CONFIG_BTRFS_FS_POSIX_ACL=y +CONFIG_NILFS2_FS=m +CONFIG_F2FS_FS=m +CONFIG_F2FS_FS_SECURITY=y +CONFIG_FS_DAX=y +CONFIG_FS_ENCRYPTION=y +CONFIG_FS_VERITY=y +CONFIG_FANOTIFY=y +CONFIG_FANOTIFY_ACCESS_PERMISSIONS=y +CONFIG_QUOTA_NETLINK_INTERFACE=y +# CONFIG_PRINT_QUOTA_WARNING is not set +CONFIG_QFMT_V2=y +CONFIG_AUTOFS4_FS=y +CONFIG_FUSE_FS=m +CONFIG_CUSE=m +CONFIG_VIRTIO_FS=m +CONFIG_OVERLAY_FS=m +CONFIG_FSCACHE=m +CONFIG_FSCACHE_STATS=y +CONFIG_FSCACHE_OBJECT_LIST=y +CONFIG_CACHEFILES=m +CONFIG_ISO9660_FS=m +CONFIG_JOLIET=y +CONFIG_ZISOFS=y +CONFIG_UDF_FS=m +CONFIG_MSDOS_FS=m +CONFIG_VFAT_FS=m +CONFIG_FAT_DEFAULT_IOCHARSET="ascii" +CONFIG_PROC_KCORE=y +CONFIG_TMPFS=y +CONFIG_TMPFS_POSIX_ACL=y +CONFIG_HUGETLBFS=y +CONFIG_ORANGEFS_FS=m +CONFIG_AFFS_FS=m +CONFIG_ECRYPT_FS=m +CONFIG_HFS_FS=m +CONFIG_HFSPLUS_FS=m +CONFIG_BEFS_FS=m +CONFIG_JFFS2_FS=m +CONFIG_JFFS2_SUMMARY=y +CONFIG_JFFS2_FS_XATTR=y +CONFIG_CRAMFS=m +CONFIG_SQUASHFS=m +CONFIG_SQUASHFS_XATTR=y +CONFIG_SQUASHFS_LZ4=y +CONFIG_SQUASHFS_LZO=y +CONFIG_SQUASHFS_XZ=y +CONFIG_SQUASHFS_ZSTD=y +CONFIG_MINIX_FS=m +CONFIG_ROMFS_FS=m +CONFIG_PSTORE=y +CONFIG_PSTORE_LZO_COMPRESS=m +CONFIG_PSTORE_LZ4_COMPRESS=m +CONFIG_PSTORE_LZ4HC_COMPRESS=m +CONFIG_PSTORE_842_COMPRESS=y +CONFIG_PSTORE_RAM=m +CONFIG_SYSV_FS=m +CONFIG_UFS_FS=m +CONFIG_NFS_FS=y +# CONFIG_NFS_V2 is not set +CONFIG_NFS_V3_ACL=y +CONFIG_NFS_V4=y +CONFIG_NFS_SWAP=y +CONFIG_NFS_V4_1=y +CONFIG_NFS_V4_2=y +CONFIG_NFSD=m +CONFIG_NFSD_V3_ACL=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_BLOCKLAYOUT=y +CONFIG_NFSD_SCSILAYOUT=y +CONFIG_NFSD_FLEXFILELAYOUT=y +CONFIG_NFSD_V4_SECURITY_LABEL=y +CONFIG_SUNRPC_DEBUG=y +CONFIG_CEPH_FS=m +CONFIG_CEPH_FSCACHE=y +CONFIG_CEPH_FS_POSIX_ACL=y +CONFIG_CEPH_FS_SECURITY_LABEL=y +CONFIG_CIFS=m +CONFIG_CIFS_UPCALL=y +CONFIG_CIFS_XATTR=y +CONFIG_CIFS_POSIX=y +CONFIG_CIFS_DFS_UPCALL=y +CONFIG_CIFS_FSCACHE=y +CONFIG_CODA_FS=m +CONFIG_AFS_FS=m +CONFIG_AFS_DEBUG=y +CONFIG_AFS_FSCACHE=y +CONFIG_9P_FS=m +CONFIG_9P_FSCACHE=y +CONFIG_9P_FS_POSIX_ACL=y +CONFIG_9P_FS_SECURITY=y +CONFIG_NLS_DEFAULT="utf8" +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_CODEPAGE_737=m +CONFIG_NLS_CODEPAGE_775=m +CONFIG_NLS_CODEPAGE_850=m +CONFIG_NLS_CODEPAGE_852=m +CONFIG_NLS_CODEPAGE_855=m +CONFIG_NLS_CODEPAGE_857=m +CONFIG_NLS_CODEPAGE_860=m +CONFIG_NLS_CODEPAGE_861=m +CONFIG_NLS_CODEPAGE_862=m +CONFIG_NLS_CODEPAGE_863=m +CONFIG_NLS_CODEPAGE_864=m +CONFIG_NLS_CODEPAGE_865=m +CONFIG_NLS_CODEPAGE_866=m +CONFIG_NLS_CODEPAGE_869=m +CONFIG_NLS_CODEPAGE_936=m +CONFIG_NLS_CODEPAGE_950=m +CONFIG_NLS_CODEPAGE_932=m +CONFIG_NLS_CODEPAGE_949=m +CONFIG_NLS_CODEPAGE_874=m +CONFIG_NLS_ISO8859_8=m +CONFIG_NLS_CODEPAGE_1250=m +CONFIG_NLS_CODEPAGE_1251=m +CONFIG_NLS_ASCII=y +CONFIG_NLS_ISO8859_1=m +CONFIG_NLS_ISO8859_2=m +CONFIG_NLS_ISO8859_3=m +CONFIG_NLS_ISO8859_4=m +CONFIG_NLS_ISO8859_5=m +CONFIG_NLS_ISO8859_6=m +CONFIG_NLS_ISO8859_7=m +CONFIG_NLS_ISO8859_9=m +CONFIG_NLS_ISO8859_13=m +CONFIG_NLS_ISO8859_14=m +CONFIG_NLS_ISO8859_15=m +CONFIG_NLS_KOI8_R=m +CONFIG_NLS_KOI8_U=m +CONFIG_NLS_MAC_ROMAN=m +CONFIG_NLS_MAC_CELTIC=m +CONFIG_NLS_MAC_CENTEURO=m +CONFIG_NLS_MAC_CROATIAN=m +CONFIG_NLS_MAC_CYRILLIC=m +CONFIG_NLS_MAC_GAELIC=m +CONFIG_NLS_MAC_GREEK=m +CONFIG_NLS_MAC_ICELAND=m +CONFIG_NLS_MAC_INUIT=m +CONFIG_NLS_MAC_ROMANIAN=m +CONFIG_NLS_MAC_TURKISH=m +CONFIG_DLM=m +CONFIG_DLM_DEBUG=y +CONFIG_UNICODE=y +CONFIG_KEYS_REQUEST_CACHE=y +CONFIG_PERSISTENT_KEYRINGS=y +CONFIG_TRUSTED_KEYS=m +CONFIG_ENCRYPTED_KEYS=y +CONFIG_KEY_DH_OPERATIONS=y +CONFIG_SECURITY=y +CONFIG_SECURITY_NETWORK=y +CONFIG_SECURITY_INFINIBAND=y +CONFIG_SECURITY_NETWORK_XFRM=y +CONFIG_HARDENED_USERCOPY=y +CONFIG_SECURITY_SELINUX=y +CONFIG_SECURITY_SELINUX_BOOTPARAM=y +CONFIG_SECURITY_SELINUX_DISABLE=y +CONFIG_SECURITY_SELINUX_CHECKREQPROT_VALUE=1 +CONFIG_SECURITY_YAMA=y +CONFIG_SECURITY_LOCKDOWN_LSM=y +CONFIG_SECURITY_LOCKDOWN_LSM_EARLY=y +CONFIG_INTEGRITY_SIGNATURE=y +CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y +CONFIG_IMA=y +CONFIG_IMA_DEFAULT_HASH_SHA256=y +CONFIG_IMA_WRITE_POLICY=y +CONFIG_IMA_APPRAISE=y +CONFIG_IMA_APPRAISE_MODSIG=y +# CONFIG_IMA_TRUSTED_KEYRING is not set +CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY=y +CONFIG_LSM="yama,loadpin,safesetid,integrity,selinux,smack,tomoyo,apparmor" +CONFIG_CRYPTO_FIPS=y +CONFIG_CRYPTO_USER=y +# CONFIG_CRYPTO_MANAGER_DISABLE_TESTS is not set +CONFIG_CRYPTO_TEST=m +CONFIG_CRYPTO_ECRDSA=m +CONFIG_CRYPTO_CHACHA20POLY1305=m +CONFIG_CRYPTO_AEGIS128=m +CONFIG_CRYPTO_CFB=m +CONFIG_CRYPTO_LRW=m +CONFIG_CRYPTO_OFB=m +CONFIG_CRYPTO_KEYWRAP=m +CONFIG_CRYPTO_ADIANTUM=m +CONFIG_CRYPTO_XCBC=m +CONFIG_CRYPTO_VMAC=m +CONFIG_CRYPTO_RMD160=m +CONFIG_CRYPTO_SHA3=m +CONFIG_CRYPTO_SM3=m +CONFIG_CRYPTO_WP512=m +CONFIG_CRYPTO_AES_TI=m +CONFIG_CRYPTO_ANUBIS=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_CAMELLIA=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_KHAZAD=m +CONFIG_CRYPTO_SEED=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_SM4=m +CONFIG_CRYPTO_TEA=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_ANSI_CPRNG=m +CONFIG_CRYPTO_DRBG_HASH=y +CONFIG_CRYPTO_DRBG_CTR=y +CONFIG_CRYPTO_USER_API_HASH=y +CONFIG_CRYPTO_USER_API_SKCIPHER=y +CONFIG_CRYPTO_USER_API_RNG=y +CONFIG_CRYPTO_USER_API_AEAD=y +CONFIG_CRYPTO_STATS=y +CONFIG_CRYPTO_DEV_SUN8I_CE=y +CONFIG_CRYPTO_DEV_SUN8I_CE_HASH=y +CONFIG_CRYPTO_DEV_SUN8I_CE_PRNG=y +CONFIG_CRYPTO_DEV_SUN8I_CE_TRNG=y +CONFIG_CRYPTO_DEV_VIRTIO=m +CONFIG_PKCS8_PRIVATE_KEY_PARSER=m +CONFIG_SIGNED_PE_FILE_VERIFICATION=y +CONFIG_SECONDARY_TRUSTED_KEYRING=y +CONFIG_SYSTEM_BLACKLIST_KEYRING=y +# CONFIG_RAID6_PQ_BENCHMARK is not set +CONFIG_CRC_CCITT=y +CONFIG_PRINTK_TIME=y +CONFIG_CONSOLE_LOGLEVEL_QUIET=3 +CONFIG_BOOT_PRINTK_DELAY=y +CONFIG_DYNAMIC_DEBUG=y +CONFIG_DEBUG_INFO=y +CONFIG_STRIP_ASM_SYMS=y +# CONFIG_SECTION_MISMATCH_WARN_ONLY is not set +# CONFIG_FRAME_POINTER is not set +CONFIG_VMLINUX_MAP=y +CONFIG_MAGIC_SYSRQ=y +CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x0 +# CONFIG_DEBUG_MISC is not set +CONFIG_DEBUG_VM=y +CONFIG_DEBUG_MEMORY_INIT=y +CONFIG_DEBUG_SHIRQ=y +CONFIG_SOFTLOCKUP_DETECTOR=y +# CONFIG_DETECT_HUNG_TASK is not set +CONFIG_DEBUG_ATOMIC_SLEEP=y +CONFIG_BUG_ON_DATA_CORRUPTION=y +CONFIG_RCU_TORTURE_TEST=m +CONFIG_FUNCTION_PROFILER=y +CONFIG_STACK_TRACER=y +CONFIG_SCHED_TRACER=y +CONFIG_HWLAT_TRACER=y +CONFIG_FTRACE_SYSCALLS=y +CONFIG_BLK_DEV_IO_TRACE=y +CONFIG_RING_BUFFER_BENCHMARK=m +CONFIG_TRACE_EVAL_MAP_FILE=y +CONFIG_ATOMIC64_SELFTEST=y +CONFIG_ASYNC_RAID6_TEST=m +CONFIG_TEST_KSTRTOX=y From 53f312c2056b4e927671ac09afa39821490eb7ba Mon Sep 17 00:00:00 2001 From: Fu Wei Date: Tue, 16 Nov 2021 01:13:45 +0800 Subject: [PATCH 119/120] tmp fix --- arch/riscv/include/asm/pgtable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h index 4e58a4367d04cc..8a400bad57fb80 100644 --- a/arch/riscv/include/asm/pgtable.h +++ b/arch/riscv/include/asm/pgtable.h @@ -117,7 +117,7 @@ /* Page protection bits */ #define _PAGE_BASE (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER | _PAGE_DMA_CACHE) -#define PAGE_NONE __pgprot(_PAGE_PROT_NONE) +#define PAGE_NONE __pgprot(_PAGE_PROT_NONE | _PAGE_DMA_CACHE) #define PAGE_READ __pgprot(_PAGE_BASE | _PAGE_READ) #define PAGE_WRITE __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE) #define PAGE_EXEC __pgprot(_PAGE_BASE | _PAGE_EXEC) From 990df34557d5866dcc7d769b985f76e161a0ecff Mon Sep 17 00:00:00 2001 From: Heinrich Schuchardt Date: Thu, 18 Nov 2021 14:46:36 +0100 Subject: [PATCH 120/120] configs: update nezha_defconfig Enable missing configuration items: * CONFIG_CGROUPS - needed for running systemd * CONFIG_EFI - needed for booting via UEFI * CONFIG_VFAT - needed for accessing the ESP Signed-off-by: Heinrich Schuchardt --- arch/riscv/configs/nezha_defconfig | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/riscv/configs/nezha_defconfig b/arch/riscv/configs/nezha_defconfig index 59e76fcadf2e93..f774f13bd92129 100644 --- a/arch/riscv/configs/nezha_defconfig +++ b/arch/riscv/configs/nezha_defconfig @@ -4,6 +4,7 @@ CONFIG_DEFAULT_HOSTNAME="nezha" CONFIG_NO_HZ_IDLE=y CONFIG_HIGH_RES_TIMERS=y CONFIG_PREEMPT=y +CONFIG_CGROUPS=y CONFIG_EXPERT=y # CONFIG_SYSFS_SYSCALL is not set # CONFIG_VM_EVENT_COUNTERS is not set @@ -12,8 +13,8 @@ CONFIG_EXPERT=y # CONFIG_SLAB_MERGE_DEFAULT is not set CONFIG_SOC_SUNXI=y # CONFIG_RISCV_ERRATA_ALTERNATIVE is not set -# CONFIG_RISCV_ISA_C is not set -# CONFIG_EFI is not set +CONFIG_RISCV_ISA_C=y +CONFIG_EFI=y CONFIG_PHYS_RAM_BASE=0x40000000 CONFIG_PM=y CONFIG_PM_DEBUG=y @@ -198,11 +199,14 @@ CONFIG_EXT4_FS=y # CONFIG_MANDATORY_FILE_LOCKING is not set # CONFIG_DNOTIFY is not set CONFIG_FANOTIFY=y +CONFIG_VFAT_FS=y CONFIG_TMPFS=y CONFIG_TMPFS_XATTR=y CONFIG_TMPFS_INODE64=y # CONFIG_MISC_FILESYSTEMS is not set # CONFIG_NETWORK_FILESYSTEMS is not set +CONFIG_NLS_CODEPAGE_437=y +CONFIG_NLS_ISO8859_1=y CONFIG_CRYPTO_USER_API_HASH=y CONFIG_CRYPTO_USER_API_SKCIPHER=y CONFIG_CRYPTO_USER_API_RNG=y